Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: new-options.js

Issue 29411555: Issue 5169 - Add whitelisted tab to the new options page (Closed)
Left Patch Set: Addressed Thomas comments Created May 16, 2017, 8:10 p.m.
Right Patch Set: Fixed the TYPO Created July 3, 2017, 4:10 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « new-options.html ('k') | skin/new-options.css » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH 3 * Copyright (C) 2006-2017 eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 /* globals checkShareResource, getDocLink, i18nFormatDateTime, openSharePopup, 18 /* globals checkShareResource, getDocLink, i18nFormatDateTime, openSharePopup,
19 E */ 19 E */
20 20
21 "use strict"; 21 "use strict";
22 22
23 { 23 {
24 let subscriptionsMap = Object.create(null); 24 let subscriptionsMap = Object.create(null);
25 let filtersMap = Object.create(null); 25 let filtersMap = Object.create(null);
26 let collections = Object.create(null); 26 let collections = Object.create(null);
27 let acceptableAdsUrl = null; 27 let acceptableAdsUrl = null;
28 let isCustomFiltersLoaded = false;
28 let {getMessage} = ext.i18n; 29 let {getMessage} = ext.i18n;
29 let filterErrors = new Map([ 30 let filterErrors = new Map([
30 ["synchronize_invalid_url", 31 ["synchronize_invalid_url",
31 "options_filterList_lastDownload_invalidURL"], 32 "options_filterList_lastDownload_invalidURL"],
32 ["synchronize_connection_error", 33 ["synchronize_connection_error",
33 "options_filterList_lastDownload_connectionError"], 34 "options_filterList_lastDownload_connectionError"],
34 ["synchronize_invalid_data", 35 ["synchronize_invalid_data",
35 "options_filterList_lastDownload_invalidData"], 36 "options_filterList_lastDownload_invalidData"],
36 ["synchronize_checksum_mismatch", 37 ["synchronize_checksum_mismatch",
37 "options_filterList_lastDownload_checksumMismatch"] 38 "options_filterList_lastDownload_checksumMismatch"]
38 ]); 39 ]);
40 const timestampUI = Symbol();
39 41
40 function Collection(details) 42 function Collection(details)
41 { 43 {
42 this.details = details; 44 this.details = details;
43 this.items = []; 45 this.items = [];
44 } 46 }
45 47
46 Collection.prototype._setEmpty = function(table, texts) 48 Collection.prototype._setEmpty = function(table, texts)
47 { 49 {
48 let placeholders = table.querySelectorAll(".empty-placeholder"); 50 let placeholders = table.querySelectorAll(".empty-placeholder");
(...skipping 26 matching lines...) Expand all
75 77
76 Collection.prototype._getItemTitle = function(item, i) 78 Collection.prototype._getItemTitle = function(item, i)
77 { 79 {
78 if (item.url == acceptableAdsUrl) 80 if (item.url == acceptableAdsUrl)
79 return getMessage("options_acceptableAds_description"); 81 return getMessage("options_acceptableAds_description");
80 if (this.details[i].useOriginalTitle && item.originalTitle) 82 if (this.details[i].useOriginalTitle && item.originalTitle)
81 return item.originalTitle; 83 return item.originalTitle;
82 return item.title || item.url || item.text; 84 return item.title || item.url || item.text;
83 }; 85 };
84 86
85 Collection.prototype.addItem = function(item) 87 Collection.prototype._sortItems = function()
86 { 88 {
87 if (this.items.indexOf(item) >= 0)
88 return;
89
90 this.items.push(item);
91 this.items.sort((a, b) => 89 this.items.sort((a, b) =>
92 { 90 {
93 // Make sure that Acceptable Ads is always last, since it cannot be 91 // Make sure that Acceptable Ads is always last, since it cannot be
94 // disabled, but only be removed. That way it's grouped together with 92 // disabled, but only be removed. That way it's grouped together with
95 // the "Own filter list" which cannot be disabled either at the bottom 93 // the "Own filter list" which cannot be disabled either at the bottom
96 // of the filter lists in the Advanced tab. 94 // of the filter lists in the Advanced tab.
97 if (a.url == acceptableAdsUrl) 95 if (a.url == acceptableAdsUrl)
98 return 1; 96 return 1;
99 if (b.url == acceptableAdsUrl) 97 if (b.url == acceptableAdsUrl)
100 return -1; 98 return -1;
101 99
100 // Make sure that newly added entries always appear on top in descending
101 // chronological order
102 let aTimestamp = a[timestampUI] || 0;
103 let bTimestamp = b[timestampUI] || 0;
104 if (aTimestamp || bTimestamp)
105 return bTimestamp - aTimestamp;
106
102 let aTitle = this._getItemTitle(a, 0).toLowerCase(); 107 let aTitle = this._getItemTitle(a, 0).toLowerCase();
103 let bTitle = this._getItemTitle(b, 0).toLowerCase(); 108 let bTitle = this._getItemTitle(b, 0).toLowerCase();
104 return aTitle.localeCompare(bTitle); 109 return aTitle.localeCompare(bTitle);
105 }); 110 });
106 111 };
112
113 Collection.prototype.addItem = function(item)
114 {
115 if (this.items.indexOf(item) >= 0)
116 return;
117
118 this.items.push(item);
119 this._sortItems();
107 for (let j = 0; j < this.details.length; j++) 120 for (let j = 0; j < this.details.length; j++)
108 { 121 {
109 let table = E(this.details[j].id); 122 let table = E(this.details[j].id);
110 let template = table.querySelector("template"); 123 let template = table.querySelector("template");
111 let listItem = document.createElement("li"); 124 let listItem = document.createElement("li");
112 listItem.appendChild(document.importNode(template.content, true)); 125 listItem.appendChild(document.importNode(template.content, true));
113 listItem.setAttribute("aria-label", this._getItemTitle(item, j)); 126 listItem.setAttribute("aria-label", this._getItemTitle(item, j));
114 listItem.setAttribute("data-access", item.url || item.text); 127 listItem.setAttribute("data-access", item.url || item.text);
115 listItem.setAttribute("role", "section"); 128 listItem.setAttribute("role", "section");
116 129
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 } 191 }
179 192
180 element.parentElement.removeChild(element); 193 element.parentElement.removeChild(element);
181 if (this.items.length == 0) 194 if (this.items.length == 0)
182 this._setEmpty(table, detail.emptyText); 195 this._setEmpty(table, detail.emptyText);
183 } 196 }
184 }; 197 };
185 198
186 Collection.prototype.updateItem = function(item) 199 Collection.prototype.updateItem = function(item)
187 { 200 {
201 let oldIndex = this.items.indexOf(item);
202 this._sortItems();
188 let access = (item.url || item.text).replace(/'/g, "\\'"); 203 let access = (item.url || item.text).replace(/'/g, "\\'");
189 for (let i = 0; i < this.details.length; i++) 204 for (let i = 0; i < this.details.length; i++)
190 { 205 {
191 let table = E(this.details[i].id); 206 let table = E(this.details[i].id);
192 let element = table.querySelector("[data-access='" + access + "']"); 207 let element = table.querySelector("[data-access='" + access + "']");
193 if (!element) 208 if (!element)
194 continue; 209 continue;
195 210
196 let title = this._getItemTitle(item, i); 211 let title = this._getItemTitle(item, i);
197 element.querySelector(".display").textContent = title; 212 element.querySelector(".display").textContent = title;
198 element.setAttribute("aria-label", title); 213 element.setAttribute("aria-label", title);
199 if (this.details[i].searchable) 214 if (this.details[i].searchable)
200 element.setAttribute("data-search", title.toLowerCase()); 215 element.setAttribute("data-search", title.toLowerCase());
201 let control = element.querySelector(".control[role='checkbox']"); 216 let control = element.querySelector(".control[role='checkbox']");
202 if (control) 217 if (control)
203 { 218 {
204 control.setAttribute("aria-checked", item.disabled == false); 219 control.setAttribute("aria-checked", item.disabled == false);
205 if (item.url == acceptableAdsUrl && this == collections.filterLists) 220 if (item.url == acceptableAdsUrl && this == collections.filterLists)
206 control.setAttribute("disabled", true); 221 control.disabled = true;
saroyanm 2017/05/18 16:21:52 Use disabled property for assigning disabled in cu
saroyanm 2017/05/22 09:38:24 Done.
207 } 222 }
208 223
209 let dateElement = element.querySelector(".date"); 224 let dateElement = element.querySelector(".date");
210 let timeElement = element.querySelector(".time"); 225 let timeElement = element.querySelector(".time");
211 if (dateElement && timeElement) 226 if (dateElement && timeElement)
212 { 227 {
213 let message = element.querySelector(".message"); 228 let message = element.querySelector(".message");
214 if (item.isDownloading) 229 if (item.isDownloading)
215 { 230 {
216 let text = getMessage("options_filterList_lastDownload_inProgress"); 231 let text = getMessage("options_filterList_lastDownload_inProgress");
(...skipping 23 matching lines...) Expand all
240 { 255 {
241 if (item.homepage) 256 if (item.homepage)
242 websiteElement.setAttribute("href", item.homepage); 257 websiteElement.setAttribute("href", item.homepage);
243 else 258 else
244 websiteElement.setAttribute("aria-hidden", true); 259 websiteElement.setAttribute("aria-hidden", true);
245 } 260 }
246 261
247 let sourceElement = element.querySelector(".context-menu .source"); 262 let sourceElement = element.querySelector(".context-menu .source");
248 if (sourceElement) 263 if (sourceElement)
249 sourceElement.setAttribute("href", item.url); 264 sourceElement.setAttribute("href", item.url);
265
266 let newIndex = this.items.indexOf(item);
267 if (oldIndex != newIndex)
268 table.insertBefore(element, table.childNodes[newIndex]);
250 } 269 }
251 }; 270 };
252 271
253 Collection.prototype.clearAll = function() 272 Collection.prototype.clearAll = function()
254 { 273 {
255 this.items = []; 274 this.items = [];
256 for (let detail of this.details) 275 for (let detail of this.details)
257 { 276 {
258 let table = E(detail.id); 277 let table = E(detail.id);
259 let element = table.firstChild; 278 let element = table.firstChild;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 else 492 else
474 location.href = link; 493 location.href = link;
475 }); 494 });
476 } 495 }
477 496
478 function switchTab(id) 497 function switchTab(id)
479 { 498 {
480 location.hash = id; 499 location.hash = id;
481 } 500 }
482 501
502 function execAction(action, element)
503 {
504 switch (action)
505 {
506 case "add-domain-exception":
507 addWhitelistedDomain();
508 break;
509 case "add-language-subscription":
510 addEnableSubscription(findParentData(element, "access", false));
511 break;
512 case "add-predefined-subscription": {
513 let dialog = E("dialog-content-predefined");
514 let title = dialog.querySelector("h3").textContent;
515 let url = dialog.querySelector(".url").textContent;
516 addEnableSubscription(url, title);
517 closeDialog();
518 break;
519 }
520 case "cancel-custom-filters":
521 E("custom-filters").classList.remove("mode-edit");
522 break;
523 case "close-dialog":
524 closeDialog();
525 break;
526 case "edit-custom-filters":
527 editCustomFilters();
528 break;
529 case "import-subscription": {
530 let url = E("blockingList-textbox").value;
531 addEnableSubscription(url);
532 closeDialog();
533 break;
534 }
535 case "open-context-menu": {
536 let listItem = findParentData(element, "access", true);
537 if (listItem && !listItem.classList.contains("show-context-menu"))
538 listItem.classList.add("show-context-menu");
539 break;
540 }
541 case "open-dialog": {
542 let dialog = findParentData(element, "dialog", false);
543 openDialog(dialog);
544 break;
545 }
546 case "open-doclink": {
547 let doclink = findParentData(element, "doclink", false);
548 openDocLink(doclink);
549 break;
550 }
551 case "remove-filter":
552 ext.backgroundPage.sendMessage({
553 type: "filters.remove",
554 text: findParentData(element, "access", false)
555 });
556 break;
557 case "remove-subscription":
558 ext.backgroundPage.sendMessage({
559 type: "subscriptions.remove",
560 url: findParentData(element, "access", false)
561 });
562 break;
563 case "save-custom-filters":
564 sendMessageHandleErrors({
565 type: "filters.importRaw",
566 text: E("custom-filters-raw").value,
567 removeExisting: true
568 },
569 () =>
570 {
571 E("custom-filters").classList.remove("mode-edit");
572 });
573 break;
574 case "switch-tab":
575 let tabId = findParentData(element, "tab", false);
576 switchTab(tabId);
577 break;
578 case "toggle-disable-subscription":
579 ext.backgroundPage.sendMessage({
580 type: "subscriptions.toggle",
581 keepInstalled: true,
582 url: findParentData(element, "access", false)
583 });
584 break;
585 case "toggle-pref":
586 ext.backgroundPage.sendMessage({
587 type: "prefs.toggle",
588 key: findParentData(element, "pref", false)
589 });
590 break;
591 case "toggle-remove-subscription":
592 let subscriptionUrl = findParentData(element, "access", false);
593 if (element.getAttribute("aria-checked") == "true")
594 {
595 ext.backgroundPage.sendMessage({
596 type: "subscriptions.remove",
597 url: subscriptionUrl
598 });
599 }
600 else
601 addEnableSubscription(subscriptionUrl);
602 break;
603 case "update-all-subscriptions":
604 ext.backgroundPage.sendMessage({
605 type: "subscriptions.update"
606 });
607 break;
608 case "update-subscription":
609 ext.backgroundPage.sendMessage({
610 type: "subscriptions.update",
611 url: findParentData(element, "access", false)
612 });
613 break;
614 }
615 }
616
483 function onClick(e) 617 function onClick(e)
484 { 618 {
485 let context = document.querySelector(".show-context-menu"); 619 let context = document.querySelector(".show-context-menu");
486 if (context) 620 if (context)
487 context.classList.remove("show-context-menu"); 621 context.classList.remove("show-context-menu");
488 622
489 let element = findParentData(e.target, "action", true); 623 let actions = findParentData(e.target, "action", false);
490 if (!element) 624 if (!actions)
491 return; 625 return;
492 626
493 let actions = element.getAttribute("data-action").split(","); 627 actions = actions.split(",");
494 for (let action of actions) 628 for (let action of actions)
495 { 629 {
496 switch (action) 630 execAction(action, e.target);
497 {
498 case "add-domain-exception":
499 addWhitelistedDomain();
500 break;
501 case "add-predefined-subscription": {
502 let dialog = E("dialog-content-predefined");
503 let title = dialog.querySelector("h3").textContent;
504 let url = dialog.querySelector(".url").textContent;
505 addEnableSubscription(url, title);
506 closeDialog();
507 break;
508 }
509 case "cancel-custom-filters":
510 E("custom-filters").classList.remove("mode-edit");
511 break;
512 case "close-dialog":
513 closeDialog();
514 break;
515 case "edit-custom-filters":
516 E("custom-filters").classList.add("mode-edit");
517 editCustomFilters();
518 break;
519 case "import-subscription": {
520 let url = E("blockingList-textbox").value;
521 addEnableSubscription(url);
522 closeDialog();
523 break;
524 }
525 case "open-dialog": {
526 let dialog = findParentData(element, "dialog", false);
527 openDialog(dialog);
528 break;
529 }
530 case "open-doclink": {
531 let doclink = findParentData(element, "doclink", false);
532 openDocLink(doclink);
533 break;
534 }
535 case "save-custom-filters":
536 sendMessageHandleErrors({
537 type: "filters.importRaw",
538 text: E("custom-filters-raw").value,
539 removeExisting: true
540 },
541 () =>
542 {
543 E("custom-filters").classList.remove("mode-edit");
544 });
545 break;
546 case "switch-tab": {
547 let tabId = findParentData(e.target, "tab", false);
548 switchTab(tabId);
549 break;
550 }
551 case "toggle-pref":
552 ext.backgroundPage.sendMessage({
553 type: "prefs.toggle",
554 key: findParentData(element, "pref", false)
555 });
556 break;
557 case "update-all-subscriptions":
558 ext.backgroundPage.sendMessage({
559 type: "subscriptions.update"
560 });
561 break;
562 case "open-context-menu": {
563 let listItem = findParentData(element, "access", true);
564 if (listItem != context)
565 listItem.classList.add("show-context-menu");
566 break;
567 }
568 case "update-subscription":
569 ext.backgroundPage.sendMessage({
570 type: "subscriptions.update",
571 url: findParentData(element, "access", false)
572 });
573 break;
574 case "remove-subscription":
575 ext.backgroundPage.sendMessage({
576 type: "subscriptions.remove",
577 url: findParentData(element, "access", false)
578 });
579 break;
580 case "toggle-remove-subscription": {
581 let subscriptionUrl = findParentData(element, "access", false);
582 if (element.getAttribute("aria-checked") == "true")
583 {
584 ext.backgroundPage.sendMessage({
585 type: "subscriptions.remove",
586 url: subscriptionUrl
587 });
588 }
589 else
590 addEnableSubscription(subscriptionUrl);
591 break;
592 }
593 case "toggle-disable-subscription":
594 ext.backgroundPage.sendMessage({
595 type: "subscriptions.toggle",
596 keepInstalled: true,
597 url: findParentData(element, "access", false)
598 });
599 break;
600 case "add-language-subscription":
601 addEnableSubscription(findParentData(element, "access", false));
602 break;
603 case "remove-filter":
604 ext.backgroundPage.sendMessage({
605 type: "filters.remove",
606 text: findParentData(element, "access", false)
607 });
608 break;
609 }
610 } 631 }
611 } 632 }
612 633
613 function getKey(e) 634 function getKey(e)
614 { 635 {
615 // e.keyCode has been deprecated so we attempt to use e.key 636 // e.keyCode has been deprecated so we attempt to use e.key
616 if ("key" in e) 637 if ("key" in e)
617 return e.key; 638 return e.key;
618 return getKey.keys[e.keyCode]; 639 return getKey.keys[e.keyCode];
619 } 640 }
(...skipping 15 matching lines...) Expand all
635 return; 656 return;
636 657
637 let container = findParentData(element, "action", true); 658 let container = findParentData(element, "action", true);
638 if (!container || !container.hasAttribute("data-keys")) 659 if (!container || !container.hasAttribute("data-keys"))
639 return; 660 return;
640 661
641 let keys = container.getAttribute("data-keys").split(" "); 662 let keys = container.getAttribute("data-keys").split(" ");
642 if (keys.indexOf(key) < 0) 663 if (keys.indexOf(key) < 0)
643 return; 664 return;
644 665
645 switch (container.getAttribute("data-action")) 666 if (element.getAttribute("role") == "tab")
646 { 667 {
647 case "add-domain-exception": 668 if (key == "ArrowLeft" || key == "ArrowUp")
648 addWhitelistedDomain(); 669 element = element.previousElementSibling || container.lastElementChild;
649 break; 670 else if (key == "ArrowRight" || key == "ArrowDown")
650 case "open-doclink": 671 element = element.nextElementSibling || container.firstElementChild;
651 let doclink = findParentData(element, "doclink", false); 672 }
652 openDocLink(doclink); 673
653 break; 674 let actions = container.getAttribute("data-action").split(",");
654 case "switch-tab": 675 for (let action of actions)
655 if (key == "Enter") 676 {
656 { 677 execAction(action, element);
657 let tabId = findParentData(element, "tab", false);
658 switchTab(tabId);
659 }
660 else if (element.hasAttribute("aria-selected"))
661 {
662 if (key == "ArrowLeft" || key == "ArrowUp")
663 {
664 element = element.previousElementSibling ||
665 container.lastElementChild;
666 }
667 else if (key == "ArrowRight" || key == "ArrowDown")
668 {
669 element = element.nextElementSibling ||
670 container.firstElementChild;
671 }
672
673 let tabId = findParentData(element, "tab", false);
674 switchTab(tabId);
675 }
676 break;
677 } 678 }
678 } 679 }
679 680
680 function selectTabItem(tabId, container, focus) 681 function selectTabItem(tabId, container, focus)
681 { 682 {
682 // Show tab content 683 // Show tab content
683 document.body.setAttribute("data-tab", tabId); 684 document.body.setAttribute("data-tab", tabId);
684 685
685 // Select tab 686 // Select tab
686 let tabList = container.querySelector("[role='tablist']"); 687 let tabList = container.querySelector("[role='tablist']");
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 758
758 updateShareLink(); 759 updateShareLink();
759 updateTooltips(); 760 updateTooltips();
760 761
761 // Initialize interactive UI elements 762 // Initialize interactive UI elements
762 document.body.addEventListener("click", onClick, false); 763 document.body.addEventListener("click", onClick, false);
763 document.body.addEventListener("keyup", onKeyUp, false); 764 document.body.addEventListener("keyup", onKeyUp, false);
764 let placeholderValue = getMessage("options_dialog_language_find"); 765 let placeholderValue = getMessage("options_dialog_language_find");
765 E("find-language").setAttribute("placeholder", placeholderValue); 766 E("find-language").setAttribute("placeholder", placeholderValue);
766 E("find-language").addEventListener("keyup", onFindLanguageKeyUp, false); 767 E("find-language").addEventListener("keyup", onFindLanguageKeyUp, false);
767 let exampleValue = getMessage("options_whitelist_placeholder_example"); 768 let exampleValue = getMessage("options_whitelist_placeholder_example",
769 ["www.example.com"]);
768 E("whitelisting-textbox").setAttribute("placeholder", exampleValue); 770 E("whitelisting-textbox").setAttribute("placeholder", exampleValue);
769 E("whitelisting-textbox").addEventListener("keyup", (e) => 771 E("whitelisting-textbox").addEventListener("keyup", (e) =>
770 { 772 {
771 let addWhitelistButton = E("whitelisting-add-button"); 773 E("whitelisting-add-button").disabled = !e.target.value;
772 addWhitelistButton.disabled = false;
773 if (getKey(e) == "Enter")
774 {
775 if (!addWhitelistButton.disabled)
776 addWhitelistedDomain();
777 }
778 else
779 {
780 for (let whitelistItem of collections.whitelist.items)
781 {
782 if (!e.target.value)
783 {
784 addWhitelistButton.disabled = true;
785 }
786 if (whitelistItem.title == e.target.value)
787 {
788 addWhitelistButton.disabled = true;
789 E("whitelisting-validation").textContent =
saroyanm 2017/05/16 20:20:07 I keep this solution here for now, adding the item
saroyanm 2017/05/18 16:21:52 Every new item needs to be added on top of the "co
saroyanm 2017/05/22 09:38:24 Done.
790 getMessage("options_whitelist_duplicate");
791 }
792 }
793 }
794 }, false); 774 }, false);
795 775
796 // Advanced tab 776 // Advanced tab
797 let tweaks = document.querySelectorAll("#tweaks li[data-pref]"); 777 let tweaks = document.querySelectorAll("#tweaks li[data-pref]");
798 tweaks = Array.prototype.map.call(tweaks, (checkbox) => 778 tweaks = Array.prototype.map.call(tweaks, (checkbox) =>
799 { 779 {
800 return checkbox.getAttribute("data-pref"); 780 return checkbox.getAttribute("data-pref");
801 }); 781 });
802 for (let key of tweaks) 782 for (let key of tweaks)
803 { 783 {
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 for (let subscription of subscriptions) 938 for (let subscription of subscriptions)
959 { 939 {
960 ext.backgroundPage.sendMessage({ 940 ext.backgroundPage.sendMessage({
961 type: "filters.get", 941 type: "filters.get",
962 subscriptionUrl: subscription.url 942 subscriptionUrl: subscription.url
963 }, 943 },
964 (filters) => 944 (filters) =>
965 { 945 {
966 for (let filter of filters) 946 for (let filter of filters)
967 updateFilter(filter); 947 updateFilter(filter);
948
949 isCustomFiltersLoaded = true;
968 }); 950 });
969 } 951 }
970 }); 952 });
971 loadRecommendations(); 953 loadRecommendations();
972 ext.backgroundPage.sendMessage({ 954 ext.backgroundPage.sendMessage({
973 type: "prefs.get", 955 type: "prefs.get",
974 key: "subscriptions_exceptionsurl" 956 key: "subscriptions_exceptionsurl"
975 }, 957 },
976 (url) => 958 (url) =>
977 { 959 {
(...skipping 12 matching lines...) Expand all
990 { 972 {
991 for (let subscription of subscriptions) 973 for (let subscription of subscriptions)
992 onSubscriptionMessage("added", subscription); 974 onSubscriptionMessage("added", subscription);
993 }); 975 });
994 }); 976 });
995 } 977 }
996 978
997 function addWhitelistedDomain() 979 function addWhitelistedDomain()
998 { 980 {
999 let domain = E("whitelisting-textbox"); 981 let domain = E("whitelisting-textbox");
982 for (let whitelistItem of collections.whitelist.items)
983 {
984 if (whitelistItem.title == domain.value)
985 {
986 whitelistItem[timestampUI] = Date.now();
987 collections.whitelist.updateItem(whitelistItem);
988 domain.value = "";
989 break;
990 }
991 }
1000 if (domain.value) 992 if (domain.value)
1001 { 993 {
1002 sendMessageHandleErrors({ 994 sendMessageHandleErrors({
1003 type: "filters.add", 995 type: "filters.add",
1004 text: "@@||" + domain.value.toLowerCase() + "^$document" 996 text: "@@||" + domain.value.toLowerCase() + "^$document"
1005 }); 997 });
1006 } 998 }
1007 999
1008 domain.value = ""; 1000 domain.value = "";
1009 E("whitelisting-add-button").disabled = true; 1001 E("whitelisting-add-button").disabled = true;
1010 } 1002 }
1011 1003
1012 function editCustomFilters() 1004 function editCustomFilters()
1013 { 1005 {
1006 if (!isCustomFiltersLoaded)
1007 {
1008 console.error("Custom filters are not loaded");
1009 return;
1010 }
1011
1012 E("custom-filters").classList.add("mode-edit");
1014 let filterTexts = []; 1013 let filterTexts = [];
1015 for (let customFilterItem of collections.customFilters.items) 1014 for (let customFilterItem of collections.customFilters.items)
1016 filterTexts.push(customFilterItem.text); 1015 filterTexts.push(customFilterItem.text);
1017 E("custom-filters-raw").value = filterTexts.join("\n"); 1016 E("custom-filters-raw").value = filterTexts.join("\n");
1018 } 1017 }
1019 1018
1020 function addEnableSubscription(url, title, homepage) 1019 function addEnableSubscription(url, title, homepage)
1021 { 1020 {
1022 let messageType = null; 1021 let messageType = null;
1023 let knownSubscription = subscriptionsMap[url]; 1022 let knownSubscription = subscriptionsMap[url];
(...skipping 12 matching lines...) Expand all
1036 message.homepage = homepage; 1035 message.homepage = homepage;
1037 1036
1038 ext.backgroundPage.sendMessage(message); 1037 ext.backgroundPage.sendMessage(message);
1039 } 1038 }
1040 1039
1041 function onFilterMessage(action, filter) 1040 function onFilterMessage(action, filter)
1042 { 1041 {
1043 switch (action) 1042 switch (action)
1044 { 1043 {
1045 case "added": 1044 case "added":
1045 filter[timestampUI] = Date.now();
1046 updateFilter(filter); 1046 updateFilter(filter);
1047 updateShareLink(); 1047 updateShareLink();
1048 break; 1048 break;
1049 case "loaded": 1049 case "loaded":
1050 populateLists(); 1050 populateLists();
1051 break; 1051 break;
1052 case "removed": 1052 case "removed":
1053 let knownFilter = filtersMap[filter.text]; 1053 let knownFilter = filtersMap[filter.text];
1054 collections.whitelist.removeItem(knownFilter); 1054 collections.whitelist.removeItem(knownFilter);
1055 collections.customFilters.removeItem(knownFilter); 1055 collections.customFilters.removeItem(knownFilter);
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 }); 1316 });
1317 ext.backgroundPage.sendMessage({ 1317 ext.backgroundPage.sendMessage({
1318 type: "subscriptions.listen", 1318 type: "subscriptions.listen",
1319 filter: ["added", "disabled", "homepage", "lastDownload", "removed", 1319 filter: ["added", "disabled", "homepage", "lastDownload", "removed",
1320 "title", "downloadStatus", "downloading"] 1320 "title", "downloadStatus", "downloading"]
1321 }); 1321 });
1322 1322
1323 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); 1323 window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
1324 window.addEventListener("hashchange", onHashChange, false); 1324 window.addEventListener("hashchange", onHashChange, false);
1325 } 1325 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld