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

Delta Between Two Patch Sets: new-options.js

Issue 29502647: Issue 5482 - Sidebar and about ABP dialog (Closed)
Left Patch Set: Addressed comments Created Aug. 23, 2017, 12:23 p.m.
Right Patch Set: Fixed nit Created Aug. 28, 2017, 11:38 a.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/abp-logo.svg » ('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-present 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 setLinks, E */ 19 setLinks, 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 acceptableAdsPrivacyUrl = null; 28 let acceptableAdsPrivacyUrl = null;
29 let subscriptionToChange = null;
30 let isCustomFiltersLoaded = false; 29 let isCustomFiltersLoaded = false;
31 let {getMessage} = ext.i18n; 30 let {getMessage} = ext.i18n;
32 let customFilters = []; 31 let customFilters = [];
33 let filterErrors = new Map([ 32 let filterErrors = new Map([
34 ["synchronize_invalid_url", 33 ["synchronize_invalid_url",
35 "options_filterList_lastDownload_invalidURL"], 34 "options_filterList_lastDownload_invalidURL"],
36 ["synchronize_connection_error", 35 ["synchronize_connection_error",
37 "options_filterList_lastDownload_connectionError"], 36 "options_filterList_lastDownload_connectionError"],
38 ["synchronize_invalid_data", 37 ["synchronize_invalid_data",
39 "options_filterList_lastDownload_invalidData"], 38 "options_filterList_lastDownload_invalidData"],
40 ["synchronize_checksum_mismatch", 39 ["synchronize_checksum_mismatch",
41 "options_filterList_lastDownload_checksumMismatch"] 40 "options_filterList_lastDownload_checksumMismatch"]
42 ]); 41 ]);
43 const timestampUI = Symbol(); 42 const timestampUI = Symbol();
44 const whitelistedDomainRegexp = /^@@\|\|([^/:]+)\^\$document$/; 43 const whitelistedDomainRegexp = /^@@\|\|([^/:]+)\^\$document$/;
45 // Period of time in milliseconds 44 // Period of time in milliseconds
46 const minuteInMs = 60000; 45 const minuteInMs = 60000;
47 const hourInMs = 3600000; 46 const hourInMs = 3600000;
48 const fullDayInMs = 86400000; 47 const fullDayInMs = 86400000;
49 const privacySubscriptions = ["privacy", "social"];
50 const moreSubscriptions = ["malware", "anti-adblock"];
51 48
52 function Collection(details) 49 function Collection(details)
53 { 50 {
54 this.details = details; 51 this.details = details;
55 this.items = []; 52 this.items = [];
56 } 53 }
57 54
58 Collection.prototype._setEmpty = function(table, texts) 55 Collection.prototype._setEmpty = function(table, texts)
59 { 56 {
60 let placeholders = table.querySelectorAll(".empty-placeholder"); 57 let placeholders = table.querySelectorAll(".empty-placeholder");
(...skipping 19 matching lines...) Expand all
80 { 77 {
81 let access = (item.url || item.text).replace(/'/g, "\\'"); 78 let access = (item.url || item.text).replace(/'/g, "\\'");
82 return function(container) 79 return function(container)
83 { 80 {
84 return container.querySelector("[data-access='" + access + "']"); 81 return container.querySelector("[data-access='" + access + "']");
85 }; 82 };
86 }; 83 };
87 84
88 Collection.prototype._getItemTitle = function(item, i) 85 Collection.prototype._getItemTitle = function(item, i)
89 { 86 {
90 if (item.url === acceptableAdsUrl)
91 return getMessage("options_aa_tracking_label");
92 if (item.url === acceptableAdsPrivacyUrl)
93 return getMessage("options_aa_no_tracking_label");
94 if (this.details[i].useOriginalTitle && item.originalTitle) 87 if (this.details[i].useOriginalTitle && item.originalTitle)
95 return item.originalTitle; 88 return item.originalTitle;
96 return item.title || item.url || item.text; 89 return item.title || item.url || item.text;
97 }; 90 };
98 91
99 Collection.prototype._sortItems = function() 92 Collection.prototype._sortItems = function()
100 { 93 {
101 this.items.sort((a, b) => 94 this.items.sort((a, b) =>
102 { 95 {
103 // Make sure that Acceptable Ads is always last, since it cannot be 96 // Make sure that Acceptable Ads is always last, since it cannot be
104 // disabled, but only be removed. That way it's grouped together with 97 // disabled, but only be removed. That way it's grouped together with
105 // the "Own filter list" which cannot be disabled either at the bottom 98 // the "Own filter list" which cannot be disabled either at the bottom
106 // of the filter lists in the Advanced tab. 99 // of the filter lists in the Advanced tab.
107 if (a.url == acceptableAdsUrl || a.url == acceptableAdsPrivacyUrl) 100 if (isAcceptableAds(a.url))
108 return 1; 101 return 1;
109 if (b.url == acceptableAdsUrl || b.url == acceptableAdsPrivacyUrl) 102 if (isAcceptableAds(b.url))
110 return -1; 103 return -1;
111 104
112 // Make sure that newly added entries always appear on top in descending 105 // Make sure that newly added entries always appear on top in descending
113 // chronological order 106 // chronological order
114 let aTimestamp = a[timestampUI] || 0; 107 let aTimestamp = a[timestampUI] || 0;
115 let bTimestamp = b[timestampUI] || 0; 108 let bTimestamp = b[timestampUI] || 0;
116 if (aTimestamp || bTimestamp) 109 if (aTimestamp || bTimestamp)
117 return bTimestamp - aTimestamp; 110 return bTimestamp - aTimestamp;
118 111
119 let aTitle = this._getItemTitle(a, 0).toLowerCase(); 112 let aTitle = this._getItemTitle(a, 0).toLowerCase();
(...skipping 14 matching lines...) Expand all
134 let detail = this.details[j]; 127 let detail = this.details[j];
135 let table = E(detail.id); 128 let table = E(detail.id);
136 let template = table.querySelector("template"); 129 let template = table.querySelector("template");
137 let listItem = document.createElement("li"); 130 let listItem = document.createElement("li");
138 listItem.appendChild(document.importNode(template.content, true)); 131 listItem.appendChild(document.importNode(template.content, true));
139 listItem.setAttribute("aria-label", this._getItemTitle(item, j)); 132 listItem.setAttribute("aria-label", this._getItemTitle(item, j));
140 listItem.setAttribute("data-access", item.url || item.text); 133 listItem.setAttribute("data-access", item.url || item.text);
141 listItem.setAttribute("role", "section"); 134 listItem.setAttribute("role", "section");
142 135
143 let tooltip = listItem.querySelector("[data-tooltip]"); 136 let tooltip = listItem.querySelector("[data-tooltip]");
144 if (tooltip && tooltip.hasAttribute("data-tooltip")) 137 if (tooltip)
145 { 138 {
146 if (item.recommended) 139 let tooltipId = tooltip.getAttribute("data-tooltip");
147 { 140 tooltipId = tooltipId.replace("%value%", item.recommended);
148 let tooltipId = tooltip.getAttribute("data-tooltip"); 141 if (getMessage(tooltipId))
149 tooltipId = tooltipId.replace("%value%", item.recommended); 142 {
150 tooltip.setAttribute("data-tooltip", tooltipId); 143 tooltip.setAttribute("data-tooltip", tooltipId);
151 }
152 else
153 {
154 tooltip.parentNode.removeChild(tooltip);
155 } 144 }
156 } 145 }
157 146
158 for (let control of listItem.querySelectorAll(".control")) 147 for (let control of listItem.querySelectorAll(".control"))
159 { 148 {
160 if (control.hasAttribute("title")) 149 if (control.hasAttribute("title"))
161 { 150 {
162 let titleValue = getMessage(control.getAttribute("title")); 151 let titleValue = getMessage(control.getAttribute("title"));
163 control.setAttribute("title", titleValue); 152 control.setAttribute("title", titleValue);
164 } 153 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 this._sortItems(); 209 this._sortItems();
221 let access = (item.url || item.text).replace(/'/g, "\\'"); 210 let access = (item.url || item.text).replace(/'/g, "\\'");
222 for (let i = 0; i < this.details.length; i++) 211 for (let i = 0; i < this.details.length; i++)
223 { 212 {
224 let table = E(this.details[i].id); 213 let table = E(this.details[i].id);
225 let element = table.querySelector("[data-access='" + access + "']"); 214 let element = table.querySelector("[data-access='" + access + "']");
226 if (!element) 215 if (!element)
227 continue; 216 continue;
228 217
229 let title = this._getItemTitle(item, i); 218 let title = this._getItemTitle(item, i);
230 element.querySelector(".display").textContent = title; 219 let displays = element.querySelectorAll(".display");
220 for (let j = 0; j < displays.length; j++)
221 displays[j].textContent = title;
222
231 element.setAttribute("aria-label", title); 223 element.setAttribute("aria-label", title);
232 if (this.details[i].searchable) 224 if (this.details[i].searchable)
233 element.setAttribute("data-search", title.toLowerCase()); 225 element.setAttribute("data-search", title.toLowerCase());
234 let control = element.querySelector(".control[role='checkbox']"); 226 let control = element.querySelector(".control[role='checkbox']");
235 if (control) 227 if (control)
236 { 228 {
237 control.setAttribute("aria-checked", item.disabled == false); 229 control.setAttribute("aria-checked", item.disabled == false);
238 if ((item.url == acceptableAdsUrl || 230 if (isAcceptableAds(item.url) && this == collections.filterLists)
239 item.url == acceptableAdsPrivacyUrl) &&
240 this == collections.filterLists)
241 control.disabled = true; 231 control.disabled = true;
242 } 232 }
243 233
244 let lastUpdateElement = element.querySelector(".last-update"); 234 let lastUpdateElement = element.querySelector(".last-update");
245 if (lastUpdateElement) 235 if (lastUpdateElement)
246 { 236 {
247 let message = element.querySelector(".message"); 237 let message = element.querySelector(".message");
248 if (item.isDownloading) 238 if (item.isDownloading)
249 { 239 {
250 let text = getMessage("options_filterList_lastDownload_inProgress"); 240 let text = getMessage("options_filterList_lastDownload_inProgress");
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 index += (index == focusables.length - 1) ? -1 : 1; 328 index += (index == focusables.length - 1) ? -1 : 1;
339 329
340 let nextElement = focusables[index]; 330 let nextElement = focusables[index];
341 if (!nextElement) 331 if (!nextElement)
342 return false; 332 return false;
343 333
344 nextElement.focus(); 334 nextElement.focus();
345 return true; 335 return true;
346 } 336 }
347 337
348 collections.security = new Collection([ 338 collections.protection = new Collection([
349 { 339 {
350 id: "recommend-security-list-table" 340 id: "recommend-protection-list-table"
351 } 341 }
352 ]); 342 ]);
353 collections.langs = new Collection([ 343 collections.langs = new Collection([
354 { 344 {
355 id: "blocking-languages-table", 345 id: "blocking-languages-table",
356 emptyText: ["options_language_empty"], 346 emptyText: ["options_language_empty"]
357 switchSingleEntryControl: true
358 } 347 }
359 ]); 348 ]);
360 collections.allLangs = new Collection([ 349 collections.allLangs = new Collection([
361 { 350 {
362 id: "all-lang-table-add", 351 id: "all-lang-table-add",
363 emptyText: ["options_dialog_language_other_empty"] 352 emptyText: ["options_dialog_language_other_empty"]
364 },
365 {
366 id: "all-lang-table-change",
367 emptyText: ["options_dialog_language_other_empty"]
368 } 353 }
369 ]); 354 ]);
370 collections.custom = new Collection([ 355 collections.custom = new Collection([
371 { 356 {
372 id: "custom-list-table" 357 id: "custom-list-table"
373 } 358 }
374 ]); 359 ]);
375 collections.whitelist = new Collection([ 360 collections.whitelist = new Collection([
376 { 361 {
377 id: "whitelisting-table", 362 id: "whitelisting-table",
378 emptyText: ["options_whitelist_empty_1", "options_whitelist_empty_2"] 363 emptyText: ["options_whitelist_empty_1", "options_whitelist_empty_2"]
379 } 364 }
380 ]); 365 ]);
381 collections.filterLists = new Collection([ 366 collections.filterLists = new Collection([
382 { 367 {
383 id: "all-filter-lists-table", 368 id: "all-filter-lists-table",
384 useOriginalTitle: true 369 useOriginalTitle: true
385 } 370 }
386 ]); 371 ]);
387 372
388 function toggleShowRecommendation(subscription) 373 function addSubscription(subscription)
389 { 374 {
375 let collection = null;
376 if (subscription.recommended)
377 {
378 if (subscription.recommended == "ads")
379 {
380 if (subscription.disabled == false)
381 collection = collections.langs;
382
383 collections.allLangs.addItem(subscription);
384 }
385 else
386 {
387 collection = collections.protection;
388 }
389 }
390 else if (!isAcceptableAds(subscription.url))
391 {
392 collection = collections.custom;
393 }
394
395 if (collection)
396 collection.addItem(subscription);
397
398 subscriptionsMap[subscription.url] = subscription;
399 updateTooltips();
400 }
401
402 function updateSubscription(subscription)
403 {
404 for (let name in collections)
405 collections[name].updateItem(subscription);
406
390 if (subscription.recommended == "ads") 407 if (subscription.recommended == "ads")
391 { 408 {
392 if (subscription.disabled) 409 if (subscription.disabled)
393 collections.langs.removeItem(subscription); 410 collections.langs.removeItem(subscription);
394 else 411 else
395 collections.langs.addItem(subscription); 412 collections.langs.addItem(subscription);
396 } 413 }
397 414 else if (!subscription.recommended && !isAcceptableAds(subscription.url))
398 if (moreSubscriptions.indexOf(subscription.recommended) >= 0 && 415 {
399 subscription.disabled == false) 416 if (subscription.disabled == false)
400 { 417 {
401 collections.custom.addItem(subscription); 418 collections.custom.addItem(subscription);
402 updateTooltips(); 419 updateTooltips();
403 }
404 }
405
406 function addSubscription(subscription)
407 {
408 let collection;
409 if (subscription.recommended)
410 {
411 if (privacySubscriptions.indexOf(subscription.recommended) >= 0)
412 collection = collections.security;
413 else if (subscription.recommended == "ads")
414 {
415 if (subscription.disabled == false)
416 collection = collections.langs;
417 else
418 collection = collections.allLangs;
419 }
420 else if (subscription.disabled == false)
421 {
422 collection = collections.custom;
423 } 420 }
424 else 421 else
425 { 422 {
426 subscriptionsMap[subscription.url] = subscription; 423 collections.custom.removeItem(subscription);
427 return; 424 }
428 } 425 }
429 }
430 else if (subscription.url == acceptableAdsUrl ||
431 subscription.url == acceptableAdsPrivacyUrl)
432 {
433 return;
434 }
435 else
436 collection = collections.custom;
437
438 collection.addItem(subscription);
439 subscriptionsMap[subscription.url] = subscription;
440 toggleShowRecommendation(subscription);
441 updateTooltips();
442 }
443
444 function updateSubscription(subscription)
445 {
446 for (let name in collections)
447 collections[name].updateItem(subscription);
448
449 toggleShowRecommendation(subscription);
450 } 426 }
451 427
452 function updateFilter(filter) 428 function updateFilter(filter)
453 { 429 {
454 let match = filter.text.match(whitelistedDomainRegexp); 430 let match = filter.text.match(whitelistedDomainRegexp);
455 if (match && !filtersMap[filter.text]) 431 if (match && !filtersMap[filter.text])
456 { 432 {
457 filter.title = match[1]; 433 filter.title = match[1];
458 collections.whitelist.addItem(filter); 434 collections.whitelist.addItem(filter);
435 if (isCustomFiltersLoaded)
436 {
437 let text = getMessage("options_whitelist_notification", [filter.title]);
438 showNotification(text);
439 }
459 } 440 }
460 else 441 else
461 { 442 {
462 customFilters.push(filter.text); 443 customFilters.push(filter.text);
463 if (isCustomFiltersLoaded) 444 if (isCustomFiltersLoaded)
464 updateCustomFiltersUi(); 445 updateCustomFiltersUi();
465 } 446 }
466 447
467 filtersMap[filter.text] = filter; 448 filtersMap[filter.text] = filter;
468 } 449 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 addEnableSubscription(findParentData(element, "access", false)); 547 addEnableSubscription(findParentData(element, "access", false));
567 break; 548 break;
568 case "add-predefined-subscription": { 549 case "add-predefined-subscription": {
569 let dialog = E("dialog-content-predefined"); 550 let dialog = E("dialog-content-predefined");
570 let title = dialog.querySelector("h3").textContent; 551 let title = dialog.querySelector("h3").textContent;
571 let url = dialog.querySelector(".url").textContent; 552 let url = dialog.querySelector(".url").textContent;
572 addEnableSubscription(url, title); 553 addEnableSubscription(url, title);
573 closeDialog(); 554 closeDialog();
574 break; 555 break;
575 } 556 }
576 case "block-all":
577 ext.backgroundPage.sendMessage({
578 type: "subscriptions.remove",
579 url: acceptableAdsPrivacyUrl
580 });
581 ext.backgroundPage.sendMessage({
582 type: "subscriptions.remove",
583 url: acceptableAdsUrl
584 });
585 setDntNotification(false);
586 break;
587 case "cancel-custom-filters": 557 case "cancel-custom-filters":
588 setCustomFiltersView("read"); 558 setCustomFiltersView("read");
589 break; 559 break;
590 case "change-language-subscription": 560 case "change-language-subscription":
591 ext.backgroundPage.sendMessage({ 561 for (let key in subscriptionsMap)
592 type: "subscriptions.remove", 562 {
593 url: subscriptionToChange 563 let subscription = subscriptionsMap[key];
594 }); 564 let subscriptionType = subscription.recommended;
595 ext.backgroundPage.sendMessage({ 565 if (subscriptionType == "ads" && subscription.disabled == false)
596 type: "subscriptions.add", 566 {
597 url: findParentData(element, "access", false) 567 ext.backgroundPage.sendMessage({
598 }); 568 type: "subscriptions.remove",
569 url: subscription.url
570 });
571 ext.backgroundPage.sendMessage({
572 type: "subscriptions.add",
573 url: findParentData(element, "access", false)
574 });
575 break;
576 }
577 }
599 break; 578 break;
600 case "close-dialog": 579 case "close-dialog":
601 closeDialog(); 580 closeDialog();
602 break; 581 break;
603 case "edit-custom-filters": 582 case "edit-custom-filters":
604 setCustomFiltersView("write"); 583 setCustomFiltersView("write");
605 break; 584 break;
606 case "enable-aa": 585 case "hide-notification":
607 ext.backgroundPage.sendMessage({ 586 hideNotification();
608 type: "subscriptions.remove",
609 url: acceptableAdsPrivacyUrl
610 });
611 ext.backgroundPage.sendMessage({
612 type: "subscriptions.add",
613 url: acceptableAdsUrl
614 });
615 setDntNotification(false);
616 break;
617 case "enable-privacy-aa":
618 ext.backgroundPage.sendMessage({
619 type: "subscriptions.remove",
620 url: acceptableAdsUrl
621 });
622 ext.backgroundPage.sendMessage({
623 type: "subscriptions.add",
624 url: acceptableAdsPrivacyUrl
625 });
626 break; 587 break;
627 case "import-subscription": { 588 case "import-subscription": {
628 let url = E("blockingList-textbox").value; 589 let url = E("blockingList-textbox").value;
629 addEnableSubscription(url); 590 addEnableSubscription(url);
630 closeDialog(); 591 closeDialog();
631 break; 592 break;
632 } 593 }
633 case "open-context-menu": { 594 case "open-context-menu": {
634 let listItem = findParentData(element, "access", true); 595 let listItem = findParentData(element, "access", true);
635 if (listItem && !listItem.classList.contains("show-context-menu")) 596 if (listItem && !listItem.classList.contains("show-context-menu"))
636 listItem.classList.add("show-context-menu"); 597 listItem.classList.add("show-context-menu");
637 break; 598 break;
638 } 599 }
639 case "open-dialog": { 600 case "open-dialog": {
640 let dialog = findParentData(element, "dialog", false); 601 let dialog = findParentData(element, "dialog", false);
641 openDialog(dialog); 602 openDialog(dialog);
642 break; 603 break;
643 } 604 }
644 case "remove-filter": 605 case "remove-filter":
645 ext.backgroundPage.sendMessage({ 606 ext.backgroundPage.sendMessage({
646 type: "filters.remove", 607 type: "filters.remove",
647 text: findParentData(element, "access", false) 608 text: findParentData(element, "access", false)
648 }); 609 });
649 break; 610 break;
650 case "remove-subscription": 611 case "remove-subscription":
651 ext.backgroundPage.sendMessage({ 612 ext.backgroundPage.sendMessage({
652 type: "subscriptions.remove", 613 type: "subscriptions.remove",
653 url: findParentData(element, "access", false) 614 url: findParentData(element, "access", false)
654 }); 615 });
655 break;
656 case "save-change-subscription":
657 subscriptionToChange = findParentData(element, "access", false);
658 break; 616 break;
659 case "save-custom-filters": 617 case "save-custom-filters":
660 sendMessageHandleErrors({ 618 sendMessageHandleErrors({
661 type: "filters.importRaw", 619 type: "filters.importRaw",
662 text: E("custom-filters-raw").value, 620 text: E("custom-filters-raw").value,
663 removeExisting: true 621 removeExisting: true
664 }, 622 },
665 () => 623 () =>
666 { 624 {
667 setCustomFiltersView("read"); 625 setCustomFiltersView("read");
626 });
627 break;
628 case "switch-acceptable-ads":
629 let {value} = element;
630 ext.backgroundPage.sendMessage({
631 type: value == "privacy" ? "subscriptions.add" :
632 "subscriptions.remove",
633 url: acceptableAdsPrivacyUrl
634 });
635 ext.backgroundPage.sendMessage({
636 type: value == "ads" ? "subscriptions.add" : "subscriptions.remove",
637 url: acceptableAdsUrl
668 }); 638 });
669 break; 639 break;
670 case "switch-tab": 640 case "switch-tab":
671 switchTab(element.getAttribute("href").substr(1)); 641 switchTab(element.getAttribute("href").substr(1));
672 break; 642 break;
673 case "toggle-disable-subscription": 643 case "toggle-disable-subscription":
674 ext.backgroundPage.sendMessage({ 644 ext.backgroundPage.sendMessage({
675 type: "subscriptions.toggle", 645 type: "subscriptions.toggle",
676 keepInstalled: true, 646 keepInstalled: true,
677 url: findParentData(element, "access", false) 647 url: findParentData(element, "access", false)
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 // Show tab content 771 // Show tab content
802 document.body.setAttribute("data-tab", tabId); 772 document.body.setAttribute("data-tab", tabId);
803 773
804 // Select tab 774 // Select tab
805 let tabList = container.querySelector("[role='tablist']"); 775 let tabList = container.querySelector("[role='tablist']");
806 if (!tabList) 776 if (!tabList)
807 return null; 777 return null;
808 778
809 let previousTab = tabList.querySelector("[aria-selected]"); 779 let previousTab = tabList.querySelector("[aria-selected]");
810 previousTab.removeAttribute("aria-selected"); 780 previousTab.removeAttribute("aria-selected");
781 previousTab.setAttribute("tabindex", -1);
811 782
812 let tab = tabList.querySelector("a[href='#" + tabId + "']"); 783 let tab = tabList.querySelector("a[href='#" + tabId + "']");
813 tab.setAttribute("aria-selected", true); 784 tab.setAttribute("aria-selected", true);
785 tab.setAttribute("tabindex", 0);
814 786
815 let tabContentId = tab.getAttribute("aria-controls"); 787 let tabContentId = tab.getAttribute("aria-controls");
816 let tabContent = document.getElementById(tabContentId); 788 let tabContent = document.getElementById(tabContentId);
817 789
818 if (tab && focus) 790 if (tab && focus)
819 tab.focus(); 791 tab.focus();
820 792
821 return tabContent; 793 return tabContent;
822 } 794 }
823 795
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 878
907 getDocLink("subscriptions", (link) => 879 getDocLink("subscriptions", (link) =>
908 { 880 {
909 setLinks("filter-lists-description", link); 881 setLinks("filter-lists-description", link);
910 }); 882 });
911 883
912 E("custom-filters-raw").setAttribute("placeholder", 884 E("custom-filters-raw").setAttribute("placeholder",
913 getMessage("options_customFilters_edit_placeholder", ["/ads/track/*"])); 885 getMessage("options_customFilters_edit_placeholder", ["/ads/track/*"]));
914 886
915 // Help tab 887 // Help tab
916 getDocLink("faq", (link) => 888 getDocLink("adblock_plus_report_issue", (link) =>
917 { 889 {
918 E("link-faq").setAttribute("href", link); 890 setLinks("report-issue", link);
891 });
892 getDocLink("adblock_plus_report_ad", (link) =>
893 {
894 setLinks("report-ad", link);
895 });
896 getDocLink("adblock_plus_report_bug", (link) =>
897 {
898 setLinks("report-bug", link);
899 });
900 getDocLink("reporter_other_link", (link) =>
901 {
902 setLinks("report-forum", link);
919 }); 903 });
920 getDocLink("social_twitter", (link) => 904 getDocLink("social_twitter", (link) =>
921 { 905 {
922 E("link-twitter").setAttribute("href", link); 906 E("twitter").setAttribute("href", link);
923 }); 907 });
924 getDocLink("social_facebook", (link) => 908 getDocLink("social_facebook", (link) =>
925 { 909 {
926 E("link-facebook").setAttribute("href", link); 910 E("facebook").setAttribute("href", link);
927 }); 911 });
928 getDocLink("social_gplus", (link) => 912 getDocLink("social_gplus", (link) =>
929 { 913 {
930 E("link-gplus").setAttribute("href", link); 914 E("google-plus").setAttribute("href", link);
931 });
932 getDocLink("social_renren", (link) =>
933 {
934 E("link-renren").setAttribute("href", link);
935 }); 915 });
936 getDocLink("social_weibo", (link) => 916 getDocLink("social_weibo", (link) =>
937 { 917 {
938 E("link-weibo").setAttribute("href", link); 918 E("weibo").setAttribute("href", link);
939 });
940
941 // Set forum link
942 ext.backgroundPage.sendMessage({
943 type: "app.get",
944 what: "platform"
945 },
946 (platform) =>
947 {
948 ext.backgroundPage.sendMessage({
949 type: "app.get",
950 what: "application"
951 },
952 (application) =>
953 {
954 if (platform == "chromium" && application != "opera")
955 application = "chrome";
956
957 getDocLink(application + "_support", (link) =>
958 {
959 E("link-forum").setAttribute("href", link);
960 });
961 });
962 }); 919 });
963 920
964 E("dialog").addEventListener("keydown", function(e) 921 E("dialog").addEventListener("keydown", function(e)
965 { 922 {
966 switch (getKey(e)) 923 switch (getKey(e))
967 { 924 {
968 case "Escape": 925 case "Escape":
969 closeDialog(); 926 closeDialog();
970 break; 927 break;
971 case "Tab": 928 case "Tab":
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 965
1009 function closeDialog() 966 function closeDialog()
1010 { 967 {
1011 let dialog = E("dialog"); 968 let dialog = E("dialog");
1012 dialog.setAttribute("aria-hidden", true); 969 dialog.setAttribute("aria-hidden", true);
1013 dialog.removeAttribute("aria-labelledby"); 970 dialog.removeAttribute("aria-labelledby");
1014 document.body.removeAttribute("data-dialog"); 971 document.body.removeAttribute("data-dialog");
1015 focusedBeforeDialog.focus(); 972 focusedBeforeDialog.focus();
1016 } 973 }
1017 974
1018 function setDntNotification(state) 975 function showNotification(text)
1019 { 976 {
1020 if (state) 977 E("notification").setAttribute("aria-hidden", false);
1021 E("acceptable-ads").classList.add("show-dnt-notification"); 978 E("notification-text").textContent = text;
1022 else 979 setTimeout(hideNotification, 3000);
1023 E("acceptable-ads").classList.remove("show-dnt-notification"); 980 }
981
982 function hideNotification()
983 {
984 E("notification").setAttribute("aria-hidden", true);
985 E("notification-text").textContent = "";
986 }
987
988 function setAcceptableAds()
989 {
990 let option = "none";
991 document.forms["acceptable-ads"].classList.remove("show-dnt-notification");
992 if (acceptableAdsUrl in subscriptionsMap)
993 {
994 option = "ads";
995 }
996 else if (acceptableAdsPrivacyUrl in subscriptionsMap)
997 {
998 option = "privacy";
999
1000 if (!navigator.doNotTrack)
1001 document.forms["acceptable-ads"].classList.add("show-dnt-notification");
1002 }
1003 document.forms["acceptable-ads"]["acceptable-ads"].value = option;
1004 }
1005
1006 function isAcceptableAds(url)
1007 {
1008 return url == acceptableAdsUrl || url == acceptableAdsPrivacyUrl;
1024 } 1009 }
1025 1010
1026 function populateLists() 1011 function populateLists()
1027 { 1012 {
1028 subscriptionsMap = Object.create(null); 1013 subscriptionsMap = Object.create(null);
1029 filtersMap = Object.create(null); 1014 filtersMap = Object.create(null);
1030 1015
1031 // Empty collections and lists 1016 // Empty collections and lists
1032 for (let property in collections) 1017 for (let property in collections)
1033 collections[property].clearAll(); 1018 collections[property].clearAll();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 disabled: true 1053 disabled: true
1069 }); 1054 });
1070 1055
1071 ext.backgroundPage.sendMessage({ 1056 ext.backgroundPage.sendMessage({
1072 type: "prefs.get", 1057 type: "prefs.get",
1073 key: "subscriptions_exceptionsurl_privacy" 1058 key: "subscriptions_exceptionsurl_privacy"
1074 }, 1059 },
1075 (urlPrivacy) => 1060 (urlPrivacy) =>
1076 { 1061 {
1077 acceptableAdsPrivacyUrl = urlPrivacy; 1062 acceptableAdsPrivacyUrl = urlPrivacy;
1078 addSubscription({
1079 url: acceptableAdsPrivacyUrl,
1080 disabled: true
1081 });
1082 1063
1083 // Load user subscriptions 1064 // Load user subscriptions
1084 ext.backgroundPage.sendMessage({ 1065 ext.backgroundPage.sendMessage({
1085 type: "subscriptions.get", 1066 type: "subscriptions.get",
1086 downloadable: true 1067 downloadable: true
1087 }, 1068 },
1088 (subscriptions) => 1069 (subscriptions) =>
1089 { 1070 {
1090 for (let subscription of subscriptions) 1071 for (let subscription of subscriptions)
1091 onSubscriptionMessage("added", subscription); 1072 onSubscriptionMessage("added", subscription);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1188 case "lastDownload": 1169 case "lastDownload":
1189 case "title": 1170 case "title":
1190 updateSubscription(subscription); 1171 updateSubscription(subscription);
1191 break; 1172 break;
1192 case "added": 1173 case "added":
1193 if (subscription.url in subscriptionsMap) 1174 if (subscription.url in subscriptionsMap)
1194 updateSubscription(subscription); 1175 updateSubscription(subscription);
1195 else 1176 else
1196 addSubscription(subscription); 1177 addSubscription(subscription);
1197 1178
1198 if (subscription.url == acceptableAdsUrl) 1179 if (isAcceptableAds(subscription.url))
1199 document.querySelector( 1180 setAcceptableAds();
1200 "[name='acceptable-ads'][value='tracking']").checked = true;
1201 if (subscription.url == acceptableAdsPrivacyUrl)
1202 {
1203 document.querySelector(
1204 "[name='acceptable-ads'][value='no-tracking']").checked = true;
1205 if (!navigator.doNotTrack)
1206 setDntNotification(true);
1207 }
1208 1181
1209 collections.filterLists.addItem(subscription); 1182 collections.filterLists.addItem(subscription);
1210 break; 1183 break;
1211 case "removed": 1184 case "removed":
1212 if (subscription.url == acceptableAdsUrl || 1185 if (subscription.recommended)
1213 subscription.url == acceptableAdsPrivacyUrl ||
1214 subscription.recommended &&
1215 moreSubscriptions.indexOf(subscription.recommended) == -1)
1216 { 1186 {
1217 subscription.disabled = true; 1187 subscription.disabled = true;
1218 onSubscriptionMessage("disabled", subscription); 1188 onSubscriptionMessage("disabled", subscription);
1219 } 1189 }
1220 else 1190 else
1221 { 1191 {
1222 collections.custom.removeItem(subscription);
1223 delete subscriptionsMap[subscription.url]; 1192 delete subscriptionsMap[subscription.url];
1193 if (isAcceptableAds(subscription.url))
1194 {
1195 setAcceptableAds();
1196 }
1197 else
1198 {
1199 collections.custom.removeItem(subscription);
1200 }
1224 } 1201 }
1225 collections.filterLists.removeItem(subscription); 1202 collections.filterLists.removeItem(subscription);
1226 break; 1203 break;
1227 } 1204 }
1228 1205
1229 } 1206 }
1230 1207
1231 function hidePref(key, value) 1208 function hidePref(key, value)
1232 { 1209 {
1233 let element = document.querySelector("[data-pref='" + key + "']"); 1210 let element = document.querySelector("[data-pref='" + key + "']");
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 break; 1256 break;
1280 } 1257 }
1281 1258
1282 let checkbox = document.querySelector( 1259 let checkbox = document.querySelector(
1283 "[data-pref='" + key + "'] button[role='checkbox']" 1260 "[data-pref='" + key + "'] button[role='checkbox']"
1284 ); 1261 );
1285 if (checkbox) 1262 if (checkbox)
1286 checkbox.setAttribute("aria-checked", value); 1263 checkbox.setAttribute("aria-checked", value);
1287 } 1264 }
1288 1265
1289 function getMessages(id)
1290 {
1291 let messages = [];
1292 for (let i = 1; true; i++)
1293 {
1294 let message = ext.i18n.getMessage(id + "_" + i);
1295 if (!message)
1296 break;
1297
1298 messages.push(message);
1299 }
1300 return messages;
1301 }
1302
1303 function updateTooltips() 1266 function updateTooltips()
1304 { 1267 {
1305 let anchors = document.querySelectorAll(":not(.tooltip) > [data-tooltip]"); 1268 let anchors = document.querySelectorAll(":not(.tooltip) > [data-tooltip]");
1306 for (let anchor of anchors) 1269 for (let anchor of anchors)
1307 { 1270 {
1308 let id = anchor.getAttribute("data-tooltip"); 1271 let id = anchor.getAttribute("data-tooltip");
1309 1272
1310 let wrapper = document.createElement("div"); 1273 let wrapper = document.createElement("div");
1311 wrapper.className = "tooltip"; 1274 wrapper.className = "tooltip";
1312 anchor.parentNode.replaceChild(wrapper, anchor); 1275 anchor.parentNode.replaceChild(wrapper, anchor);
1313 wrapper.appendChild(anchor); 1276 wrapper.appendChild(anchor);
1314 1277
1315 let topTexts = getMessages(id);
1316 let bottomTexts = getMessages(id + "_notes");
1317
1318 // We have to use native tooltips to avoid issues when attaching a tooltip
1319 // to an element in a scrollable list or otherwise it might get cut off
1320 if (anchor.hasAttribute("data-tooltip-native"))
1321 {
1322 let title = topTexts.concat(bottomTexts).join("\n\n");
1323 anchor.setAttribute("title", title);
1324 continue;
1325 }
1326
1327 let tooltip = document.createElement("div"); 1278 let tooltip = document.createElement("div");
1328 tooltip.setAttribute("role", "tooltip"); 1279 tooltip.setAttribute("role", "tooltip");
1329 1280
1330 let imageSource = anchor.getAttribute("data-tooltip-image"); 1281 let paragraph = document.createElement("p");
1331 if (imageSource) 1282 paragraph.textContent = getMessage(id);
1332 { 1283 tooltip.appendChild(paragraph);
1333 let image = document.createElement("img");
1334 image.src = imageSource;
1335 image.alt = "";
1336 tooltip.appendChild(image);
1337 }
1338
1339 for (let topText of topTexts)
1340 {
1341 let paragraph = document.createElement("p");
1342 paragraph.innerHTML = topText;
1343 tooltip.appendChild(paragraph);
1344 }
1345 if (bottomTexts.length > 0)
1346 {
1347 let notes = document.createElement("div");
1348 notes.className = "notes";
1349 for (let bottomText of bottomTexts)
1350 {
1351 let paragraph = document.createElement("p");
1352 paragraph.innerHTML = bottomText;
1353 notes.appendChild(paragraph);
1354 }
1355 tooltip.appendChild(notes);
1356 }
1357 1284
1358 wrapper.appendChild(tooltip); 1285 wrapper.appendChild(tooltip);
1359 } 1286 }
1360 } 1287 }
1361 1288
1362 ext.onMessage.addListener((message) => 1289 ext.onMessage.addListener((message) =>
1363 { 1290 {
1364 switch (message.type) 1291 switch (message.type)
1365 { 1292 {
1366 case "app.respond": 1293 case "app.respond":
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 }); 1332 });
1406 ext.backgroundPage.sendMessage({ 1333 ext.backgroundPage.sendMessage({
1407 type: "subscriptions.listen", 1334 type: "subscriptions.listen",
1408 filter: ["added", "disabled", "homepage", "lastDownload", "removed", 1335 filter: ["added", "disabled", "homepage", "lastDownload", "removed",
1409 "title", "downloadStatus", "downloading"] 1336 "title", "downloadStatus", "downloading"]
1410 }); 1337 });
1411 1338
1412 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); 1339 window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
1413 window.addEventListener("hashchange", onHashChange, false); 1340 window.addEventListener("hashchange", onHashChange, false);
1414 } 1341 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld