User:Elominius/diff2.js
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
// history-core
var history = {
getVisits(details) {
return new Promise(resolve => {
chrome.history.getVisits(details, function(visitItems) {
resolve(visitItems)
})
})
},
search(query) {
return new Promise(resolve => {
chrome.history.search(query, function(historyItems) {
resolve(historyItems)
})
})
},
unlimitedSearch(query) {
var now = (new Date).getTime()
Object.assign(query, {
endTime: now,
maxResults: 100,
})
var data = {
visitItemsHash: {},
historyItems: [],
}
function recursiveSearch(query) {
return history.search(query).then((historyItems) => {
historyItems = historyItems.filter(historyItem => {
if (data.visitItemsHash[historyItem.id]) {
return false
} else {
data.visitItemsHash[historyItem.id] = true
return true
}
})
if (historyItems.length == 0) {
return data.visitItemsHash
} else {
var promises = []
for (var historyItem of historyItems) {
var details = {url: historyItem.url}
var promise = history.getVisits(details)
promises.push(promise)
}
return Promise.all(promises).then((allVisitItems) => {
var oldestLastVisitTime = now
for (var i = 0; i < historyItems.length; i++) {
var historyItem = historyItems[i]
var visitItems = allVisitItems[i]
data.visitItemsHash[historyItem.id] = visitItems
for (visitItem of visitItems) {
visitItem.title = ''
Object.assign(visitItem, historyItem)
}
if (oldestLastVisitTime > historyItem.lastVisitTime) {
oldestLastVisitTime = historyItem.lastVisitTime
}
}
query.endTime = oldestLastVisitTime
return recursiveSearch(query)
})
}
})
}
return recursiveSearch(query).then((visitItemsHash) => {
var allVisitItems = []
for (visitItems of Object.keys(visitItemsHash)) {
allVisitItems = allVisitItems.concat(visitItemsHash[visitItems])
}
allVisitItems.sort((a, b) => {
return b.visitTime - a.visitTime
})
allVisitItems = allVisitItems.filter(a => {
return a.visitTime > query.startTime
})
return allVisitItems
})
}
}
function downloadJson(historyItems) {
var historyItemsString = JSON.stringify(historyItems, null, 2)
var blob = new Blob([historyItemsString], {type: 'application/json'})
var url = URL.createObjectURL(blob)
var filename = 'history.json'
chrome.downloads.download({
filename,
url,
})
}
function csvDate(date) {
return `${date.getMonth()+1}/${date.getDate()}/${date.getFullYear()}`
}
function csvTime(date) {
var minutes = date.getMinutes()
var minutesString = minutes < 10 ? '0' + minutes : '' + minutes
var seconds = date.getSeconds()
var secondsString = seconds < 10 ? '0' + seconds : '' + seconds
return `${date.getHours()}:${minutesString}:${secondsString}`
}
function csvEscapify(str) {
var escapeChars = [',', '"', '\r', '\n']
var needsEscaping = false
for (var escapeChar of escapeChars) {
needsEscaping = needsEscaping || str.indexOf(escapeChar) > -1
}
if (!needsEscaping) return str
return `"${str.replace(/"/g, '""')}"`
}
function downloadCsv(historyItems) {
var raw = '\ufeff'
raw += 'order,id,date,time,title,url,visitCount,typedCount,transition\r\n'
for (var i = 0; i < historyItems.length; i++) {
historyItem = historyItems[i]
var order = i
var {id, visitCount, typedCount, transition} = historyItem
var visitTime = new Date(historyItem.visitTime)
var date = csvDate(visitTime)
var time = csvTime(visitTime)
var title = csvEscapify(historyItem.title)
var url = csvEscapify(historyItem.url)
var entry = [
order,
id,
date,
time,
title,
url,
visitCount,
typedCount,
transition,
]
var entryString = entry.join(',')
raw += entryString + '\r\n'
}
var blob = new Blob([raw], {type: 'text/csv;charset=UTF-16LE;'})
var url = URL.createObjectURL(blob)
var filename = 'history.csv'
chrome.downloads.download({
filename,
url,
})
}
// history-popup
function downloadHistory() {
var timeSelect = document.getElementById('timeSelect')
var millisecondsPerDay = 1000 * 60 * 60 * 24
var back
var query = {
text: '',
}
switch (timeSelect.value) {
case 'day':
query.startTime = (new Date).getTime() - millisecondsPerDay
break
case 'week':
query.startTime = (new Date).getTime() - 7 * millisecondsPerDay
break
case 'month':
query.startTime = (new Date).getTime() - 31 * millisecondsPerDay
break
case 'forever':
query.startTime = 0
break
default:
}
return history.unlimitedSearch(query)
}
window.addEventListener('load', function() {
var timeSelect = document.getElementById('timeSelect')
var cache = false
timeSelect.onchange = function(element) {
cache = false
var msg
switch (timeSelect.value) {
case 'month':
case 'forever':
msg = 'This may take a while...\r\n\r\nChrome only saves 3 months (90 days) of history.'
break
case 'day':
case 'week':
default:
msg = '\xa0'
}
var msgDiv = document.getElementById('msgDiv')
msgDiv.innerText = msg
}
var jsonButton = document.getElementById('jsonButton')
jsonButton.onclick = function(element) {
if (cache) {
downloadJson(cache)
return
}
downloadHistory().then((historyItems) => {
cache = historyItems
downloadJson(historyItems)
})
}
var csvButton = document.getElementById('csvButton')
csvButton.onclick = function(element) {
if (cache) {
downloadCsv(cache)
return
}
downloadHistory().then((historyItems) => {
cache = historyItems
downloadCsv(historyItems)
})
}
})
// tab-export
var
popupButtonSettings, popupCounter, popupTextarea, popupTextareaContainer, popupFilterTabs, popupFilterTabsContainer,
popupButtonCopy, popupButtonExport,
popupFormat, popupLabelFormatTitles, popupLabelFormatCustom, popupLimitWindow,
currentWindowId, os,
optionsIgnoreNonHTTP, optionsIgnorePinned, optionsFormatCustom, optionsFilterTabs, optionsCustomHeader
var defaultPopupStates = {
'states': {
format: false,
popupLimitWindow: false
}
}
browser.runtime.getPlatformInfo(function (info) {
os = info.os
})
browser.windows.getLastFocused(function (currentWindow) {
currentWindowId = currentWindow.id
})
w.addEventListener('load', function () {
popupCounter = d.getElementsByClassName('popup-counter')[0]
popupFilterTabs = d.getElementsByClassName('popup-filter-tabs')[0]
popupFilterTabsContainer = d.getElementsByClassName('popup-filter-tabs-container')[0]
popupTextarea = d.getElementsByClassName('popup-textarea')[0]
popupTextareaContainer = d.getElementsByClassName('popup-textarea-container')[0]
popupFormat = d.getElementById('popup-format')
popupLabelFormatTitles = d.getElementsByClassName('popup-label-format-titles')[0]
popupLabelFormatCustom = d.getElementsByClassName('popup-label-format-custom')[0]
popupLimitWindow = d.getElementById('popup-limit-window')
popupButtonCopy = d.getElementsByClassName('popup-button-copy')[0]
popupButtonExport = d.getElementsByClassName('popup-button-export')[0]
popupButtonSettings = d.getElementsByClassName('popup-button-settings')[0]
setLimitWindowVisibility()
popupFormat.addEventListener('change', function () {
savePopupStates()
updatePopup()
})
popupButtonSettings.addEventListener('click', function () {
browser.runtime.openOptionsPage()
})
popupLimitWindow.addEventListener('change', function () {
savePopupStates()
updatePopup()
})
popupFilterTabs.addEventListener('input', function () {
updatePopup()
})
popupButtonCopy.addEventListener('click', function () {
copyToClipboard()
})
popupButtonExport.addEventListener('click', function () {
download()
})
getOptions()
restorePopupStates()
localization()
})
function updatePopup () {
browser.tabs.query(
{},
function (tabs) {
var list = ''
var header = ''
var format = '{url}\r\n'
var actualNbTabs = 0
var totalNbTabs = tabs.length
var nbFilterMatch = 0
var userInput = popupFilterTabs.value
if (popupFormat.checked) format = '{title}\r\n{url}\r\n\r\n'
if (optionsFormatCustom) {
popupLabelFormatTitles.classList.add('hidden')
popupLabelFormatCustom.classList.remove('hidden')
if (popupFormat.checked) format = optionsFormatCustom.replace(/\\n/g, '\n').replace(/\\r/g, '\r')
}
if (optionsFilterTabs) popupFilterTabsContainer.classList.remove('hidden')
for (var i = 0; i < totalNbTabs; i++) {
var tabWindowId = tabs[i].windowId
var tabPinned = tabs[i].pinned
var tabURL = tabs[i].url
var tabTitle = tabs[i].title
if (optionsIgnorePinned && tabPinned) continue
if (popupLimitWindow.checked && tabWindowId !== currentWindowId) continue
if ((optionsIgnoreNonHTTP && tabURL.startsWith('http')) || !optionsIgnoreNonHTTP) {
actualNbTabs += 1
if (filterMatch(userInput, [tabTitle, tabURL]) || userInput === '') {
nbFilterMatch += 1
if (/<\/?[a-zA-Z]+\/?>/.test(format)) tabTitle = tabTitle.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"')
list += format.replace(/{title}/g, tabTitle).replace(/{url}/g, tabURL).replace(/{window-id}/g, tabWindowId)
}
}
}
popupTextarea.value = ''
if (optionsCustomHeader) {
var nbTabs = (userInput !== '') ? nbFilterMatch : actualNbTabs
header = optionsCustomHeader.replace(/\\n/g, '\n').replace(/\\r/g, '\r').replace(/{num-tabs}/g, nbTabs)
popupTextarea.value += header + '\r\n\r\n'
}
popupTextarea.value += list
popupCounter.textContent = (userInput !== '') ? nbFilterMatch + ' / ' + actualNbTabs : actualNbTabs
setSeparatorStyle()
popupFilterTabs.focus()
}
)
}
function filterMatch (needle, haystack) {
var regex = new RegExp(needle, 'i')
var match = false
haystack.forEach(function (element) {
if (regex.test(element)) match = true
})
return match
}
function setSeparatorStyle () {
if (hasScrollbar(popupTextarea)) {
popupTextareaContainer.classList.add('has-scrollbar')
} else {
popupTextareaContainer.classList.remove('has-scrollbar')
}
}
function setLimitWindowVisibility () {
var getting = browser.windows.getAll()
getting.then(function (windowInfoArray) {
if (windowInfoArray.length > 1) {
popupLimitWindow.parentNode.classList.remove('hidden')
}
})
}
function copyToClipboard () {
if (popupButtonCopy.classList.contains('disabled')) return
popupTextarea.select()
var message = d.execCommand('copy') ? 'copiedToClipboard' : 'notCopiedToClipboard'
browser.notifications.create('ExportTabsURLs', {
'type': 'basic',
'title': browser.i18n.getMessage('appName'),
'iconUrl': '../img/icon.svg',
'message': browser.i18n.getMessage(message)
})
popupButtonCopy.classList.add('disabled')
setTimeout(function () {
browser.notifications.clear('ExportTabsURLs')
popupButtonCopy.classList.remove('disabled')
}, 3000)
}
function download () {
var list = popupTextarea.value
// fix inconsistent behaviour on Windows, see https://github.com/alct/export-tabs-urls/issues/2
if (os === 'win') list = list.replace(/\r?\n/g, '\r\n')
var element = d.createElement('a')
element.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(list)
element.download = moment().format('YYYYMMDDTHHmmssZZ') + '_ExportTabsURLs.txt'
element.style.display = 'none'
d.body.appendChild(element)
element.click()
d.body.removeChild(element)
}
function restorePopupStates () {
var gettingItem = browser.storage.local.get(defaultPopupStates)
gettingItem.then(function (items) {
popupLimitWindow.checked = items.states.popupLimitWindow
popupFormat.checked = items.states.format
updatePopup()
})
}
function savePopupStates () {
browser.storage.local.set({
'states': {
format: popupFormat.checked,
popupLimitWindow: popupLimitWindow.checked
}
})
}
function getOptions () {
var gettingItem = browser.storage.local.get(defaultOptions)
gettingItem.then(function (items) {
optionsIgnoreNonHTTP = items.options.ignoreNonHTTP
optionsIgnorePinned = items.options.ignorePinned
optionsFormatCustom = items.options.formatCustom
optionsFilterTabs = items.options.filterTabs
optionsCustomHeader = items.options.customHeader
})
}
// exptabs
var targetWindow = null;
var tabCount = 0;
function start(tab) {
chrome.windows.getCurrent(getWindows);
}
function getWindows(win) {
targetWindow = win;
chrome.tabs.getAllInWindow(targetWindow.id, getTabs);
}
function getTabs(tabs) {
tabCount = tabs.length;
chrome.windows.getAll({"populate" : true}, expTabs);
}
function expTabs(windows) {
var numWindows = windows.length;
var exportAll = document.getElementById('inclAll').checked == true ? 1 : 0;
document.getElementById('content').value = '';
for (var i = 0; i < numWindows; i++) {
var win = windows[i];
if (targetWindow.id == win.id || exportAll == 1) {
var numTabs = win.tabs.length;
for (var j = 0; j < numTabs; j++) {
var tab = win.tabs[j];
if (document.getElementById('inclTitle').checked == true) {
document.getElementById('content').value += tab.title + '\n';
}
document.getElementById('content').value += tab.url + '\n\n';
}
}
}
}
function openTabs() {
var content = document.getElementById('content').value;
var rExp = new RegExp(
"(^|[ \t\r\n])((ftp|http|https|news|file|view-source|chrome):(([A-Za-z0-9$_.+!*(),;/?:@&~=-])|%[A-Fa-f0-9]{2}){2,}(#([a-zA-Z0-9][a-zA-Z0-9$_.+!*(),;/?:@&~=%-]*))?([A-Za-z0-9$_+!*();/?:~-])*)"
,"g"
);
var newTabs = content.match(rExp);
if (newTabs != null) {
var newTabsLen = newTabs.length;
for (var j = 0; j < newTabsLen; j++) {
var nt = newTabs[j];
chrome.tabs.create({url: nt, active: false });
}
} else {
alert('Only fully qualified URLs will be opened.');
}
}
function sendMail(gm) {
var action_url = "mailto:?";
//action_url += "subject=" + encodeURIComponent(subject) + "&";
action_url += "body=" + encodeURIComponent(document.getElementById('content').value);
if (gm == 1) {
var custom_url = "https://mail.google.com/mail/?extsrc=mailto&url=%s";
action_url = custom_url.replace("%s", encodeURIComponent(action_url));
chrome.tabs.create({ url: action_url });
} else {
chrome.tabs.update(tab_id, { url: action_url });
}
}
function download() {
var content = document.getElementById('content').value
var content_arr = content.split('\n\n');
var data = '<html><head></head><body>';
for (var i = 0; i < content_arr.length; i++) {
var content_url = content_arr[i].split('\n');
if (document.getElementById('inclTitle').checked == true) {
data+='<a href="'+content_url[1]+'">'+content_url[0]+'</a><br/>';
} else {
data+='<a href="'+content_arr[i]+'">'+content_arr[i]+'</a><br/>';
}
}
data+='</body></html>';
var blob = new Blob([data], {type: "text/html;charset=utf-8"});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.download = "tabs.html";
a.href = url;
a.click();
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('#btOpenTabs').addEventListener('click', openTabs);
document.querySelector('#inclTitle').addEventListener('click', start);
document.querySelector('#inclAll').addEventListener('click', start);
document.querySelector('#sendMail0').addEventListener('click', function(){sendMail(0)});
document.querySelector('#sendMail1').addEventListener('click', function(){sendMail(1)});
document.querySelector('#download').addEventListener('click', download);
start();
});