1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Add event listeners once the DOM has fully loaded by listening for the
6 // `DOMContentLoaded` event on the document, and adding your listeners to
7 // specific elements when it triggers.
8 document
.addEventListener('DOMContentLoaded', function () {
9 //document.querySelector('button').addEventListener('click', testf);
10 //document.getElementById("menuItem_restoreNow").addEventListener('click', menu_restoreNow);
11 document
.getElementById("menuItem_showOlderBackups").addEventListener('click', menu_ShowOlderBackups
);
12 document
.getElementById("restoreSelectedDiv").addEventListener('click', menu_RestoreSelected
);
13 document
.getElementById("restoreSelectedClearSelectionLink").addEventListener('click', menu_ClearSelection
);
15 document
.getElementById("restoreSelectedRadioSingleWindowSpanLabel").addEventListener('click', function() {
16 $('#restoreSelectedRadioSingleWindow').prop('checked', true);
19 document
.getElementById("restoreSelectedRadioMultipleWindowsSpanLabel").addEventListener('click', function() {
20 $('#restoreSelectedRadioMultipleWindows').prop('checked', true);
24 initBackupsList (false /*showAll*/);
27 $( "#dialog-confirm" ).dialog({
32 "Delete all items": function() {
33 $( this ).dialog( "close" );
36 $( this ).dialog( "close" );
45 function menu_ShowOptions () {
46 chrome
.runtime
.openOptionsPage();
49 function menu_ShowAdvancedView() {
50 chrome
.tabs
.create({url
: "/advanced.html"});
53 function menu_ClearSelection () {
54 var selectedCheckboxes
= $("input:checked");
55 for (var i
= 0; i
< selectedCheckboxes
.length
; i
++) {
56 var checkbox
= selectedCheckboxes
[i
];
57 if (checkbox
.type
== 'checkbox') {
58 checkbox
.checked
= false;
62 updateRestoreSelectedDiv();
65 function menu_RestoreSelected_Real() {
66 var selectedCheckboxes
= $("input:checked");
68 var restoreToMultipleWindows
= $('#restoreSelectedRadioMultipleWindows').is(':checked');
75 for (var i
= 0; i
< selectedCheckboxes
.length
; i
++) {
76 var checkbox
= selectedCheckboxes
[i
];
77 //if (!checkbox.hasAttribute('tbrBackupName') || !checkbox.hasAttribute('tbrWindowIndex')) {
78 if (checkbox
.tbrBackupName
=== undefined ||
79 checkbox
.tbrWindowIndex
=== undefined ||
80 checkbox
.tbrTabUrl
=== undefined) {
83 //checkbox.tbrBackupName
84 //checkbox.tbrWindowIndex
85 console
.log("Restoring " + checkbox
.tbrBackupName
+ " --> " + checkbox
.tbrWindowIndex
);
87 var tabUrl
= checkbox
.tbrTabUrl
;
89 var windowIdx
= checkbox
.tbrWindowIndex
;
90 var bkpName
= checkbox
.tbrBackupName
;
91 var key
= bkpName
+ "_" + windowIdx
;
93 if (!(key
in windows
)) {
95 windowsKeys
.push(key
);
98 windows
[key
].push(tabUrl
);
100 allUrls
.push(checkbox
.tbrTabUrl
);
103 if (restoreToMultipleWindows
) {
104 for (var i
= 0; i
< windowsKeys
.length
; i
++) {
105 var key
= windowsKeys
[i
];
106 var urls
= windows
[key
];
108 var windowProperties
= {
112 // Create a new Window
113 chrome
.windows
.create(windowProperties
, function(createdWindow
) {
118 var windowProperties
= {
122 // Create a new Window
123 chrome
.windows
.create(windowProperties
, function(createdWindow
) {
129 function menu_RestoreSelected() {
130 bootbox
.confirm("Restore selection?", function(confirmed
) {
132 menu_RestoreSelected_Real();
140 function updateRestoreSelectedDiv() {
141 var selectedCheckboxes
= $("input:checked");
143 var numSelectedTabs
= 0;
144 var numSelectedWindows
= 0;
145 for (var i
= 0; i
< selectedCheckboxes
.length
; i
++) {
146 var checkbox
= selectedCheckboxes
[i
];
148 if (checkbox
.tbrIsWindow
!== undefined) {
149 if (checkbox
.tbrIsWindow
) {
150 numSelectedWindows
++;
154 if (checkbox
.tbrBackupName
=== undefined ||
155 checkbox
.tbrWindowIndex
=== undefined ||
156 checkbox
.tbrTabUrl
=== undefined) {
162 // find the first selected tab checkbox
166 $('#restoreSelectedInfoNumTabs').html(numSelectedTabs
);
168 var restoreDiv
= $('#floatingRightDiv');
170 if (numSelectedTabs
> 0) {
173 if (!restoreDiv
.is(':visible')) {
174 restoreDiv
.fadeIn(600);
180 if (restoreDiv
.is(':visible')) {
181 restoreDiv
.fadeOut(600);
186 function menu_ShowOlderBackups () {
187 // save current scrollbar position
188 //var scrollPosition = $(document).scrollTop();
190 // Re-initialize backups list
191 //initBackupsList(true /*showAll*/, function () {
192 // Update the scrollbar position to the saved one
193 // $(document).scrollTop(scrollPosition);
198 var oldestVisibleBackupItem
= $(".backupItem:last");
199 var oldestVisibleBackupItemId
= oldestVisibleBackupItem
.attr('id');
200 // the id is in the form 'div_' + backupName
201 var oldestVisibleBackupName
= oldestVisibleBackupItemId
.substring(4);
204 var backupsDiv
= document
.getElementById ('backupsDiv');
206 chrome
.storage
.local
.get(null, function(items
) {
207 var backupsList
= [];
208 if(items
.backups_list
) {
209 backupsList
= items
.backups_list
;
212 var shouldInsert
= false;
214 for (var i
= backupsList
.length
-1; i
>= 0; i
--) {
215 var backupName
= backupsList
[i
];
216 var backupObj
= items
[backupName
];
222 if (backupObj
.isAutomatic
=== undefined) {
223 backupObj
.isAutomatic
= true;
226 if (oldestVisibleBackupName
== backupName
) {
227 // found last visible item, start inserting
232 insertBackupItem(backupName
, backupObj
, false /*insertAtBeginning*/, false /*doAnimation*/);
237 // Hide the "show all" link
238 $("#showOlderBackupsDiv").hide();
243 function insertBackupItem (backupName
, backupObj
, insertAtBeginning
, doAnimation
) {
244 var backupsDiv
= document
.getElementById ('backupsDiv');
246 var restoreButtonId
= 'restoreSelectedBackup_' + backupName
;
247 var deleteButtonId
= 'deleteSelectedBackup_' + backupName
;
248 var divId
= 'div_' + backupName
;
250 var elem
= document
.createElement("div");
252 // start with hidden element (only if we are doing the animation later)
253 elem
.style
.cssText
= 'display: none';
256 var backupTitleDivId
= 'backup_title_' + backupName
;
257 var backupItemClickId
= 'backup_click_' + backupName
;
260 elem
.className
= 'backupItem';
261 elem
.innerHTML
= '<div class="backupItemWrapper" id="' + backupTitleDivId
+ '">' +
262 '<div class="backupItemContent" id="' + backupItemClickId
+ '">' +
263 '<div class="backupItemTitle">' + backupName
+ "</div>" +
264 '<div class="backupItemDetails">' +
265 'Nr. Windows:<span class="backupItemDetailsNr">' + backupObj
.windows
.length
+ '</span><br />' +
266 'Nr. Tabs:<span class="backupItemDetailsNr">' + backupObj
.totNumTabs
+ '</span>' +
269 // '<div class="backupItemToolbar">' +
270 // '<a id="' + restoreButtonId + '"><img src="icon_48.png" title="Open Windows & Tabs" style="border: 0; width: 24px; height: 24px" /></a>' +
271 // '<a id="' + deleteButtonId + '"><img src="trash_48.png" title="Delete Backup" style="border: 0; width: 22px; height: 22px" /></a>' +
274 '<div class="backupItemFooter">' +
275 (backupObj
.isAutomatic
? '<span class="backupItemFooterAutoBackup">AUTO BACKUP</span>' :
276 '<span class="backupItemFooterManualBackup">MANUAL BACKUP</span>') +
281 //elem.innerHTML += "# Windows: " +
282 //backupsDiv.appendChild(elem);
284 //var restoreFuncHandler = (function(backupName) {
285 // return function(event) {
286 // bootbox.confirm("Open Windows & Tabs of backup '" + backupName + "'?", function(confirmed) {
288 // chrome.extension.getBackgroundPage().restoreNow(backupName);
292 /*if (!confirm("Open Windows & Tabs of backup '" + backupName + "'?")) {
300 //var deleteFuncHandler = (function(backupName, elem) {
301 // return function(event) {
302 /*if (!confirm("Delete backup '" + backupName + "'?")) {
306 // bootbox.confirm("Delete backup '" + backupName + "'?", function(confirmed) {
308 // chrome.extension.getBackgroundPage().deleteBackup(backupName, function() {
312 //if (elem.parentNode) {
313 // elem.parentNode.removeChild(elem);
315 // removeBackupItemDiv (backupName);
321 //})(backupName, elem);
323 if (insertAtBeginning
&& backupsDiv
.childNodes
.length
> 0) {
324 // some items already exist
325 var firstNode
= backupsDiv
.childNodes
[0];
326 backupsDiv
.insertBefore(elem
, firstNode
);
328 backupsDiv
.appendChild(elem
);
331 $(jq(backupItemClickId
)).click(function() {
332 var restoreDivId
= "restoreDiv_" + backupName
;
333 var restoreDiv
= $(jq(restoreDivId
));
334 if (restoreDiv
.length
== 0) {
335 // element never created, create it
336 showAdvancedRestoreFor(backupName
);
338 if (restoreDiv
.is(':visible')) {
340 restoreDiv
.slideUp();
341 //$('#restoreSelectedDiv').slideUp();
343 restoreDiv
.slideDown();
344 //$('#restoreSelectedDiv').slideDown();
346 //restoreDiv.remove();
353 //document.getElementById(restoreButtonId).addEventListener('click', restoreFuncHandler);
354 //document.getElementById(deleteButtonId).addEventListener('click', deleteFuncHandler);
357 var divIdJQ
= jq(divId
);
358 $(divIdJQ
).slideDown(1000);
360 /*obj.animate({ height: 1, opacity: 1 }, {
362 complete: function(){obj.css('display', 'block');}
368 //$(divId).display = 'none';
369 //$(divId).slideUp();
370 //$(divId).fadeOut(1000);
371 /*var bkp = $("backupsDiv");
375 /*setTimeout( function() {
376 var obj = $("#" + divId);
383 return '#' + myid
.replace(/(:|\.| )/g,'\\$1');
386 function addClickListenerForWindowTitle (windowTitleDiv
, tabsDivId
) {
387 windowTitleDiv
.addEventListener('click', function(e
) {
388 var clickedElem
= e
.target
;
390 if (clickedElem
.className
.indexOf("parentIgnoreClick") != -1) {
395 $(jq(tabsDivId
)).slideToggle();
399 function addClickListenerForWindowCheckbox(checkboxWindowElem
, windowTabs
, backupName
, i
) {
400 checkboxWindowElem
.addEventListener('click', function(e
) {
401 var isChecked
= checkboxWindowElem
.checked
;
403 for (var j
= 0; j
< windowTabs
.length
; j
++) {
405 var checkboxId
= 'checkbox_tab_' + backupName
+ '_' + i
+ '_' + j
;
406 $(jq(checkboxId
)).prop('checked', isChecked
);
407 //var el = document.getElementById(checkboxId);
408 //document.getElementById(checkboxId).change()
409 //document.getElementById(checkboxId).checked = isChecked;
412 updateRestoreSelectedDiv();
418 function showAdvancedRestoreFor (backupName
) {
419 chrome
.storage
.local
.get(backupName
, function(items
) {
420 if(!items
[backupName
]) {
421 alert("An error occured. Please reload the page.");
425 var backupTitleDivId
= 'backup_title_' + backupName
;
427 var elem
= document
.createElement("div");
428 var divId
= "restoreDiv_" + backupName
;
431 elem
.className
= 'restoreDiv';
434 var expandCollapseDiv
= document
.createElement('div');
435 expandCollapseDiv
.className
= "restoreDivCollapseExpand";
436 //expandCollapseDiv.innerHTML = 'Collapse all';
437 var collapseAElem
= document
.createElement('a');
438 collapseAElem
.innerHTML
= "Collapse all";
439 var expandAElem
= document
.createElement('a');
440 expandAElem
.innerHTML
= "Expand all";
443 expandCollapseDiv
.appendChild(collapseAElem
);
444 expandCollapseDiv
.appendChild(document
.createTextNode(' / '));
445 expandCollapseDiv
.appendChild(expandAElem
);
447 elem
.appendChild(expandCollapseDiv
);
449 var allTabsDivsIds
= [];
451 var fullBackup
= items
[backupName
];
453 for(var i
= 0; i
< fullBackup
.windows
.length
; i
++) {
454 var window
= fullBackup
.windows
[i
];
455 var windowTabs
= window
.tabs
;
457 var windowTitleDiv
= document
.createElement('div');
459 //windowTitleDiv.innerHTML = "<span>Window " + (i+1) + '</span>' +
460 // '<span style="float: right; font-size: 12px;">Nr. Tabs: ' + windowTabs.length + '</span>';
462 windowTitleDiv
.className
= 'windowTitleDiv';
464 var tabsDiv
= document
.createElement('div');
465 tabsDiv
.id
= 'tabsDiv_' + backupName
+ '_' + i
;
466 tabsDiv
.className
= 'tabsDiv';
467 tabsDiv
.hidden
= true;
469 allTabsDivsIds
.push(tabsDiv
.id
);
471 addClickListenerForWindowTitle(windowTitleDiv
, tabsDiv
.id
);
473 var checkboxWindowId
= 'checkbox_window_' + backupName
+ '_' + i
;
475 var checkboxWindowElem
= document
.createElement('input');
476 checkboxWindowElem
.type
= "checkbox";
477 checkboxWindowElem
.id
= checkboxWindowId
;
478 checkboxWindowElem
.className
= "regular-checkbox parentIgnoreClick";
480 checkboxWindowElem
.tbrIsWindow
= true;
482 var checkboxWindowLabelElem
= document
.createElement('label')
483 checkboxWindowLabelElem
.className
= "parentIgnoreClick";
484 checkboxWindowLabelElem
.htmlFor
= checkboxWindowId
;
485 checkboxWindowLabelElem
.style
.cssText
= 'margin-bottom: -4px; margin-right: 8px;';
487 addClickListenerForWindowCheckbox(checkboxWindowElem
, windowTabs
, backupName
, i
);
490 var windowTitleSpan
= document
.createElement('span');
491 windowTitleSpan
.innerHTML
=
492 `<span style="font-weight: bold">Window ${i + 1} (${window.state}) ${window.width}×${window.height} @ ${window.top}×${window.left}</span>` +
493 `<span style="float: right; font-size: 11px;">Tabs: ${windowTabs.length}</span>`;
494 //windowTitleSpan.innerHTML = '<span>Window ' + (i+1) + '</span>' +
495 // '<br /><span style="font-size: 10px;">Nr. Tabs: ' + windowTabs.length + '</span>';
497 windowTitleDiv
.appendChild(checkboxWindowElem
);
498 windowTitleDiv
.appendChild(checkboxWindowLabelElem
);
499 windowTitleDiv
.appendChild(windowTitleSpan
);
504 for (var j
= 0; j
< windowTabs
.length
; j
++) {
505 var tab
= windowTabs
[j
];
506 var tabTitle
= tab
.title
;
507 var tabUrl
= tab
.url
;
509 var checkboxId
= 'checkbox_tab_' + backupName
+ '_' + i
+ '_' + j
;
511 var tabElem
= document
.createElement('div');
512 tabElem
.style
.cssText
= "position: relative";
514 var checkboxTabElem
= document
.createElement('input');
515 checkboxTabElem
.type
= "checkbox";
516 //checkboxTabElem.name = "name";
517 //checkboxTabElem.value = "value";
518 checkboxTabElem
.id
= checkboxId
;
519 checkboxTabElem
.className
= "regular-checkbox";
522 checkboxTabElem
.tbrBackupName
= backupName
;
523 checkboxTabElem
.tbrWindowIndex
= i
;
524 checkboxTabElem
.tbrTabUrl
= tabUrl
;
526 var checkboxTabLabelElem
= document
.createElement('label')
527 checkboxTabLabelElem
.htmlFor
= checkboxId
;
529 var tabSpanElem
= document
.createElement('span');
530 tabSpanElem
.className
= "restoreTabSpan";
531 var title
= tabTitle
=== '' ? tabUrl
: tabTitle
;
532 tabSpanElem
.innerHTML
=
533 (tab
.pinned
? '📌 ' : '') +
534 `<a href="${tabUrl}" target="_blank">${title}</a>`;
536 tabElem
.appendChild(checkboxTabElem
);
537 tabElem
.appendChild(checkboxTabLabelElem
);
538 tabElem
.appendChild(tabSpanElem
);
540 tabsDiv
.appendChild(tabElem
);
542 checkboxTabElem
.addEventListener('change', function (e
) {
543 console
.log('cb changed - ' + e
.target
.id
+ ' : ' + e
.target
.checked
);
545 updateRestoreSelectedDiv();
547 //addClickListenerFor(checkboxId
548 //checkboxTabElem.addEventListener('click', function() {
551 //var checkboxId = 'checkbox_tab_' + backupName + '_' + i + '_' + j;
552 //var checkboxHtml = '<input type="checkbox" id="' + checkboxId + '" class="regular-checkbox" /><label for="' + checkboxId + '" class="labelCheckbox"></label>'
553 //tabsDiv.innerHTML += '<div style="position: relative">' + checkboxHtml + '<span class="restoreTabSpan"><a href="' + tabUrl + '" target="_blank">' + tabTitle + '</a></span>' + '<br />' +
558 elem
.appendChild(windowTitleDiv
);
559 elem
.appendChild(tabsDiv
);
564 collapseAElem
.addEventListener('click', function () {
565 for (var i
= 0; i
< allTabsDivsIds
.length
; i
++) {
566 $(jq(allTabsDivsIds
[i
])).slideUp();
570 expandAElem
.addEventListener('click', function () {
571 for (var i
= 0; i
< allTabsDivsIds
.length
; i
++) {
572 $(jq(allTabsDivsIds
[i
])).slideDown();
576 var backupTitleDiv
= document
.getElementById(backupTitleDivId
);
577 backupTitleDiv
.appendChild(elem
);
579 $(jq(divId
)).slideDown();
580 //$('#restoreSelectedDiv').slideDown();
582 //$('#restoreSelectedDiv').fadeIn(1000);
587 function removeBackupItemDiv (backupName
) {
588 var divId
= 'div_' + backupName
;
589 var divIdClean
= jq(divId
);
590 var obj
= $(divIdClean
);
593 obj
.animate({ height
: 0, opacity
: 0 }, {
595 complete: function(){obj
.remove();}
598 var backupItemDiv
= document
.getElementById (divId
);
599 if (backupItemDiv
.parentNode
) {
600 // backupItemDiv.parentNode.removeChild(backupItemDiv);
604 function initBackupsList(showAll
, callback
) {
605 var backupsDiv
= document
.getElementById ('backupsDiv');
606 //var node = backupsDiv.childNodes[0];
607 backupsDiv
.innerHTML
= '';
608 //backupsDiv.style = 'display: none';
609 //$("#backupsDiv").html("");
610 /*while (backupsDiv.hasChildNodes()) {
611 backupsDiv.removeChild(backupsDiv.lastChild);
614 $("#showOlderBackupsDiv").hide();
617 $("#backupsDiv").hide();
620 chrome
.storage
.local
.get(null, function(items
) {
621 var backupsList
= [];
622 if(items
.backups_list
) {
623 backupsList
= items
.backups_list
;
626 var numInsertedItems
= 0;
627 for (var i
= backupsList
.length
-1; i
>= 0; i
--) {
628 //for (var i = 0; i < backupsList.length; i++) {
629 var backupName
= backupsList
[i
];
630 var backupObj
= items
[backupName
];
636 if (backupObj
.isAutomatic
=== undefined) {
637 backupObj
.isAutomatic
= true;
641 if (numInsertedItems
>= 10) {
642 $("#showOlderBackupsDiv").show();
647 insertBackupItem(backupName
, backupObj
, false /*insertAtBeginning*/, false /*doAnimation*/);
653 $("#backupsDiv").slideDown();
665 var lastTimeBackupNowClicked
= 0;
667 function menu_backupNow() {
668 // Ignore clicks if less than 1 second has passed since last click (avoids rapid useless backups)
669 if (lastTimeBackupNowClicked
!= 0) {
670 var diffTime
= Math
.abs(new Date().getTime() - lastTimeBackupNowClicked
);
671 if (diffTime
< 1000) {
676 lastTimeBackupNowClicked
= new Date().getTime();
678 chrome
.runtime
.sendMessage({
679 action
: 'backupNowManual',
680 }, function({success
, backupName
, backupObj
}) {
682 //updateBackupsList();
683 insertBackupItem (backupName
, backupObj
, true /*insertAtBeginning*/, true /*doAnimation*/);
686 //bootbox.alert("Backup successfully created!");
688 alert('An error occured while creating the backup..');
694 function menu_restoreNow() {
695 chrome
.runtime
.sendMessage({
696 action
: 'restoreNow',
697 args
: ['full_backup'],
701 //document.onload(function () {
702 //var a = document.getElementById("myid");
703 //a.innerHTML = "ciaociao";
707 var storageLocal = chrome.storage.local;
708 storageLocal.getBytesInUse(null, function(bytesInUse) {
709 var elem = document.createElement("div");
710 elem.innerHTML = "<b>BYTES IN USE: " + bytesInUse + "</b><br />";
711 document.body.appendChild(elem);