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

Delta Between Two Patch Sets: new-options.js

Issue 29338983: issue 3741 - Add "remove" option to list items in new options page (Closed)
Left Patch Set: Added title attribute to whitelisting and custom list table Created June 8, 2016, 3:53 p.m.
Right Patch Set: Removed label's "for" attribute, added "aria-lable" to addItem Created June 24, 2016, 4:35 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-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 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 "use strict"; 18 "use strict";
19 19
20 (function() 20 (function()
21 { 21 {
22 var subscriptionsMap = Object.create(null); 22 var subscriptionsMap = Object.create(null);
23 var recommendationsMap = Object.create(null);
24 var filtersMap = Object.create(null); 23 var filtersMap = Object.create(null);
25 var collections = Object.create(null); 24 var collections = Object.create(null);
26 var acceptableAdsUrl = null; 25 var acceptableAdsUrl = null;
27 var maxItemId = 0;
28 var getMessage = ext.i18n.getMessage; 26 var getMessage = ext.i18n.getMessage;
29 var filterErrors = 27 var filterErrors =
30 { 28 {
31 "synchronize_invalid_url": "options_filterList_lastDownload_invalidURL", 29 "synchronize_invalid_url": "options_filterList_lastDownload_invalidURL",
32 "synchronize_connection_error": "options_filterList_lastDownload_connectionE rror", 30 "synchronize_connection_error": "options_filterList_lastDownload_connectionE rror",
33 "synchronize_invalid_data": "options_filterList_lastDownload_invalidData", 31 "synchronize_invalid_data": "options_filterList_lastDownload_invalidData",
34 "synchronize_checksum_mismatch": "options_filterList_lastDownload_checksumMi smatch" 32 "synchronize_checksum_mismatch": "options_filterList_lastDownload_checksumMi smatch"
35 }; 33 };
36 34
37 function Collection(details) 35 function Collection(details)
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 }.bind(this)); 93 }.bind(this));
96 94
97 for (var j = 0; j < this.details.length; j++) 95 for (var j = 0; j < this.details.length; j++)
98 { 96 {
99 var table = E(this.details[j].id); 97 var table = E(this.details[j].id);
100 var template = table.querySelector("template"); 98 var template = table.querySelector("template");
101 for (var i = 0; i < arguments.length; i++) 99 for (var i = 0; i < arguments.length; i++)
102 { 100 {
103 var item = arguments[i]; 101 var item = arguments[i];
104 var listItem = document.createElement("li"); 102 var listItem = document.createElement("li");
105 var ItemId = "item-" + (++maxItemId);
106 listItem.appendChild(document.importNode(template.content, true)); 103 listItem.appendChild(document.importNode(template.content, true));
104 listItem.setAttribute("aria-label", this._getItemTitle(item, j));
107 listItem.setAttribute("data-access", item.url || item.text); 105 listItem.setAttribute("data-access", item.url || item.text);
108 listItem.setAttribute("id", ItemId);
109 listItem.setAttribute("role", "section"); 106 listItem.setAttribute("role", "section");
110 107
111 var label = listItem.querySelector(".display"); 108 var label = listItem.querySelector(".display");
112 label.setAttribute("for", ItemId); 109 if (item.recommended && label.hasAttribute("data-tooltip"))
110 {
111 var tooltipId = label.getAttribute("data-tooltip");
112 tooltipId = tooltipId.replace("%value%", item.recommended);
113 label.setAttribute("data-tooltip", tooltipId);
114 }
113 115
114 var controls = listItem.querySelectorAll(".control"); 116 var controls = listItem.querySelectorAll(".control");
115 for (var k = 0; k < controls.length; k++) 117 for (var k = 0; k < controls.length; k++)
116 controls[k].setAttribute("aria-labelledby", ItemId); 118 {
119 if (controls[k].hasAttribute("title"))
120 {
121 var titleValue = getMessage(controls[k].getAttribute("title"));
122 controls[k].setAttribute("title", titleValue)
123 }
124 }
117 125
118 this._setEmpty(table, null); 126 this._setEmpty(table, null);
119 if (table.hasChildNodes()) 127 if (table.hasChildNodes())
120 { 128 {
121 table.insertBefore(listItem, 129 table.insertBefore(listItem,
122 table.childNodes[this.items.indexOf(item)]); 130 table.childNodes[this.items.indexOf(item)]);
123 } 131 }
124 else 132 else
125 table.appendChild(listItem); 133 table.appendChild(listItem);
126 this.updateItem(item); 134 this.updateItem(item);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 var access = (item.url || item.text).replace(/'/g, "\\'"); 181 var access = (item.url || item.text).replace(/'/g, "\\'");
174 for (var i = 0; i < this.details.length; i++) 182 for (var i = 0; i < this.details.length; i++)
175 { 183 {
176 var table = E(this.details[i].id); 184 var table = E(this.details[i].id);
177 var element = table.querySelector("[data-access='" + access + "']"); 185 var element = table.querySelector("[data-access='" + access + "']");
178 if (!element) 186 if (!element)
179 continue; 187 continue;
180 188
181 var title = this._getItemTitle(item, i); 189 var title = this._getItemTitle(item, i);
182 element.querySelector(".display").textContent = title; 190 element.querySelector(".display").textContent = title;
183 element.setAttribute("label", title); 191 element.setAttribute("aria-label", title);
184 if (title) 192 if (this.details[i].searchable)
185 element.setAttribute("data-search", title.toLowerCase()); 193 element.setAttribute("data-search", title.toLowerCase());
186 var control = element.querySelector(".control[role='checkbox']"); 194 var control = element.querySelector(".control[role='checkbox']");
187 if (control) 195 if (control)
188 { 196 {
189 control.setAttribute("aria-checked", item.disabled == false); 197 control.setAttribute("aria-checked", item.disabled == false);
190 if (item.url == acceptableAdsUrl && this == collections.filterLists) 198 if (item.url == acceptableAdsUrl && this == collections.filterLists)
191 control.setAttribute("disabled", true); 199 control.setAttribute("disabled", true);
192 } 200 }
193 201
194 var dateElement = element.querySelector(".date"); 202 var dateElement = element.querySelector(".date");
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 }, 290 },
283 { 291 {
284 id: "blocking-languages-dialog-table", 292 id: "blocking-languages-dialog-table",
285 emptyText: "options_dialog_language_added_empty" 293 emptyText: "options_dialog_language_added_empty"
286 } 294 }
287 ]); 295 ]);
288 collections.allLangs = new Collection( 296 collections.allLangs = new Collection(
289 [ 297 [
290 { 298 {
291 id: "all-lang-table", 299 id: "all-lang-table",
292 emptyText: "options_dialog_language_other_empty" 300 emptyText: "options_dialog_language_other_empty",
301 searchable: true
293 } 302 }
294 ]); 303 ]);
295 collections.acceptableAds = new Collection( 304 collections.acceptableAds = new Collection(
296 [ 305 [
297 { 306 {
298 id: "acceptableads-table" 307 id: "acceptableads-table"
299 } 308 }
300 ]); 309 ]);
301 collections.custom = new Collection( 310 collections.custom = new Collection(
302 [ 311 [
(...skipping 18 matching lines...) Expand all
321 collections.filterLists = new Collection( 330 collections.filterLists = new Collection(
322 [ 331 [
323 { 332 {
324 id: "all-filter-lists-table", 333 id: "all-filter-lists-table",
325 useOriginalTitle: true 334 useOriginalTitle: true
326 } 335 }
327 ]); 336 ]);
328 337
329 function updateLanguageCollections(subscription) 338 function updateLanguageCollections(subscription)
330 { 339 {
331 var recommendation = recommendationsMap[subscription.url]; 340 if (subscription.recommended == "ads")
332
333 if (recommendation && recommendation.type == "ads")
334 { 341 {
335 if (subscription.disabled) 342 if (subscription.disabled)
336 { 343 {
337 collections.allLangs.addItems(subscription); 344 collections.allLangs.addItems(subscription);
338 collections.langs.removeItem(subscription); 345 collections.langs.removeItem(subscription);
339 } 346 }
340 else 347 else
341 { 348 {
342 collections.allLangs.removeItem(subscription); 349 collections.allLangs.removeItem(subscription);
343 collections.langs.addItems(subscription); 350 collections.langs.addItems(subscription);
344 } 351 }
345 } 352 }
346 } 353 }
347 354
348 function addSubscription(subscription) 355 function addSubscription(subscription)
349 { 356 {
350 var collection; 357 var collection;
351 if (subscription.url in recommendationsMap) 358 if (subscription.recommended)
352 { 359 {
353 var recommendation = recommendationsMap[subscription.url]; 360 if (subscription.recommended != "ads")
354 if (recommendation.type != "ads")
355 collection = collections.popular; 361 collection = collections.popular;
356 else if (subscription.disabled == false) 362 else if (subscription.disabled == false)
357 collection = collections.langs; 363 collection = collections.langs;
358 else 364 else
359 collection = collections.allLangs; 365 collection = collections.allLangs;
360 } 366 }
361 else if (subscription.url == acceptableAdsUrl) 367 else if (subscription.url == acceptableAdsUrl)
362 collection = collections.acceptableAds; 368 collection = collections.acceptableAds;
363 else 369 else
364 collection = collections.custom; 370 collection = collections.custom;
365 371
366 collection.addItems(subscription); 372 collection.addItems(subscription);
367 subscriptionsMap[subscription.url] = subscription; 373 subscriptionsMap[subscription.url] = subscription;
374 updateTooltips();
368 } 375 }
369 376
370 function updateSubscription(subscription) 377 function updateSubscription(subscription)
371 { 378 {
372 var knownSubscription = subscriptionsMap[subscription.url]; 379 var knownSubscription = subscriptionsMap[subscription.url];
373 for (var property in subscription) 380 for (var property in subscription)
374 { 381 {
375 if (property == "title" && subscription.url in recommendationsMap) 382 if (property == "title" && subscription.recommended)
376 knownSubscription.originalTitle = subscription.title; 383 knownSubscription.originalTitle = subscription.title;
377 else 384 else
378 knownSubscription[property] = subscription[property]; 385 knownSubscription[property] = subscription[property];
379 } 386 }
380 387
381 for (var name in collections) 388 for (var name in collections)
382 collections[name].updateItem(knownSubscription); 389 collections[name].updateItem(knownSubscription);
383 390
384 return knownSubscription; 391 return knownSubscription;
385 } 392 }
(...skipping 20 matching lines...) Expand all
406 return response.text(); 413 return response.text();
407 }) 414 })
408 .then(function(text) 415 .then(function(text)
409 { 416 {
410 var list = document.getElementById("subscriptionSelector"); 417 var list = document.getElementById("subscriptionSelector");
411 var doc = new DOMParser().parseFromString(text, "application/xml"); 418 var doc = new DOMParser().parseFromString(text, "application/xml");
412 var elements = doc.documentElement.getElementsByTagName("subscription"); 419 var elements = doc.documentElement.getElementsByTagName("subscription");
413 for (var i = 0; i < elements.length; i++) 420 for (var i = 0; i < elements.length; i++)
414 { 421 {
415 var element = elements[i]; 422 var element = elements[i];
416 var subscription = Object.create(null); 423 var type = element.getAttribute("type");
417 subscription.originalTitle = element.getAttribute("title"); 424 var subscription = {
418 subscription.url = element.getAttribute("url"); 425 disabled: null,
419 subscription.disabled = true; 426 downloadStatus: null,
420 subscription.downloadStatus = null; 427 homepage: null,
421 subscription.homepage = null; 428 originalTitle: element.getAttribute("title"),
422 var recommendation = Object.create(null); 429 recommended: type,
423 recommendation.type = element.getAttribute("type"); 430 url: element.getAttribute("url")
431 };
432
424 var prefix = element.getAttribute("prefixes"); 433 var prefix = element.getAttribute("prefixes");
425 if (prefix) 434 if (prefix)
426 { 435 {
427 prefix = prefix.replace(/\W/g, "_"); 436 prefix = prefix.replace(/\W/g, "_");
428 subscription.title = getMessage("options_language_" + prefix); 437 subscription.title = getMessage("options_language_" + prefix);
429 } 438 }
430 else 439 else
431 { 440 {
432 var type = recommendation.type.replace(/\W/g, "_"); 441 type = type.replace(/\W/g, "_");
433 subscription.title = getMessage("common_feature_" + type + "_title") ; 442 subscription.title = getMessage("common_feature_" + type + "_title") ;
434 } 443 }
435 444
436 recommendationsMap[subscription.url] = recommendation;
437 addSubscription(subscription); 445 addSubscription(subscription);
438 } 446 }
439 }); 447 });
440 } 448 }
441 449
442 function findParentData(element, dataName, returnElement) 450 function findParentData(element, dataName, returnElement)
443 { 451 {
444 while (element) 452 while (element)
445 { 453 {
446 if (element.hasAttribute("data-" + dataName)) 454 if (element.hasAttribute("data-" + dataName))
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 { 650 {
643 E("link-version").setAttribute("href", link); 651 E("link-version").setAttribute("href", link);
644 }); 652 });
645 653
646 getDocLink("contribute", function(link) 654 getDocLink("contribute", function(link)
647 { 655 {
648 document.querySelector("#tab-contribute a").setAttribute("href", link); 656 document.querySelector("#tab-contribute a").setAttribute("href", link);
649 }); 657 });
650 658
651 updateShareLink(); 659 updateShareLink();
660 updateTooltips();
652 661
653 // Initialize interactive UI elements 662 // Initialize interactive UI elements
654 document.body.addEventListener("click", onClick, false); 663 document.body.addEventListener("click", onClick, false);
655 var placeholderValue = getMessage("options_dialog_language_find"); 664 var placeholderValue = getMessage("options_dialog_language_find");
656 E("find-language").setAttribute("placeholder", placeholderValue); 665 E("find-language").setAttribute("placeholder", placeholderValue);
657 E("find-language").addEventListener("keyup", onFindLanguageKeyUp, false); 666 E("find-language").addEventListener("keyup", onFindLanguageKeyUp, false);
658 E("whitelisting-textbox").addEventListener("keypress", function(e) 667 E("whitelisting-textbox").addEventListener("keypress", function(e)
659 { 668 {
660 if (getKey(e) == "Enter") 669 if (getKey(e) == "Enter")
661 addWhitelistedDomain(); 670 addWhitelistedDomain();
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 dialog.setAttribute("aria-hidden", true); 772 dialog.setAttribute("aria-hidden", true);
764 dialog.removeAttribute("aria-labelledby"); 773 dialog.removeAttribute("aria-labelledby");
765 document.body.removeAttribute("data-dialog"); 774 document.body.removeAttribute("data-dialog");
766 focusedBeforeDialog.focus(); 775 focusedBeforeDialog.focus();
767 } 776 }
768 777
769 function populateLists() 778 function populateLists()
770 { 779 {
771 subscriptionsMap = Object.create(null); 780 subscriptionsMap = Object.create(null);
772 filtersMap = Object.create(null); 781 filtersMap = Object.create(null);
773 recommendationsMap = Object.create(null);
774 782
775 // Empty collections and lists 783 // Empty collections and lists
776 for (var property in collections) 784 for (var property in collections)
777 collections[property].clearAll(); 785 collections[property].clearAll();
778 786
779 ext.backgroundPage.sendMessage( 787 ext.backgroundPage.sendMessage(
780 { 788 {
781 type: "subscriptions.get", 789 type: "subscriptions.get",
782 special: true 790 special: true
783 }, 791 },
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
912 if (subscription.url in subscriptionsMap) 920 if (subscription.url in subscriptionsMap)
913 subscription = updateSubscription(subscription); 921 subscription = updateSubscription(subscription);
914 else 922 else
915 addSubscription(subscription); 923 addSubscription(subscription);
916 924
917 collections.filterLists.addItems(subscription); 925 collections.filterLists.addItems(subscription);
918 updateLanguageCollections(subscription); 926 updateLanguageCollections(subscription);
919 break; 927 break;
920 case "removed": 928 case "removed":
921 var knownSubscription = subscriptionsMap[subscription.url]; 929 var knownSubscription = subscriptionsMap[subscription.url];
922 930 if (subscription.url == acceptableAdsUrl || subscription.recommended)
923 if (subscription.url == acceptableAdsUrl ||
924 subscription.url in recommendationsMap)
925 { 931 {
926 subscription.disabled = true; 932 subscription.disabled = true;
927 onSubscriptionMessage("disabled", subscription); 933 onSubscriptionMessage("disabled", subscription);
928 } 934 }
929 else 935 else
930 { 936 {
931 collections.custom.removeItem(knownSubscription); 937 collections.custom.removeItem(knownSubscription);
932 delete subscriptionsMap[subscription.url]; 938 delete subscriptionsMap[subscription.url];
933 } 939 }
934 collections.filterLists.removeItem(knownSubscription); 940 collections.filterLists.removeItem(knownSubscription);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 tab.hidden = true; 1034 tab.hidden = true;
1029 tab.removeEventListener("click", onShareLinkClick, false); 1035 tab.removeEventListener("click", onShareLinkClick, false);
1030 } 1036 }
1031 else 1037 else
1032 tab.addEventListener("click", onShareLinkClick, false); 1038 tab.addEventListener("click", onShareLinkClick, false);
1033 } 1039 }
1034 } 1040 }
1035 1041
1036 for (var i = 0; i < shareResources.length; i++) 1042 for (var i = 0; i < shareResources.length; i++)
1037 checkShareResource(shareResources[i], onResult); 1043 checkShareResource(shareResources[i], onResult);
1044 }
1045
1046 function getMessages(id)
1047 {
1048 var messages = [];
1049 for (var i = 1; true; i++)
1050 {
1051 var message = ext.i18n.getMessage(id + "_" + i);
1052 if (!message)
1053 break;
1054
1055 messages.push(message);
1056 }
1057 return messages;
1058 }
1059
1060 function updateTooltips()
1061 {
1062 var anchors = document.querySelectorAll(":not(.tooltip) > [data-tooltip]");
1063 for (var i = 0; i < anchors.length; i++)
1064 {
1065 var anchor = anchors[i];
1066 var id = anchor.getAttribute("data-tooltip");
1067
1068 var wrapper = document.createElement("div");
1069 wrapper.className = "tooltip";
1070 anchor.parentNode.replaceChild(wrapper, anchor);
1071 wrapper.appendChild(anchor);
1072
1073 var topTexts = getMessages(id);
1074 var bottomTexts = getMessages(id + "_notes");
1075
1076 // We have to use native tooltips to avoid issues when attaching a tooltip
1077 // to an element in a scrollable list or otherwise it might get cut off
1078 if (anchor.hasAttribute("data-tooltip-native"))
1079 {
1080 var title = topTexts.concat(bottomTexts).join("\n\n");
1081 anchor.setAttribute("title", title);
1082 continue;
1083 }
1084
1085 var tooltip = document.createElement("div");
1086 tooltip.setAttribute("role", "tooltip");
1087
1088 var flip = anchor.getAttribute("data-tooltip-flip");
1089 if (flip)
1090 tooltip.className = "flip-" + flip;
1091
1092 var imageSource = anchor.getAttribute("data-tooltip-image");
1093 if (imageSource)
1094 {
1095 var image = document.createElement("img");
1096 image.src = imageSource;
1097 image.alt = "";
1098 tooltip.appendChild(image);
1099 }
1100
1101 for (var j = 0; j < topTexts.length; j++)
1102 {
1103 var paragraph = document.createElement("p");
1104 paragraph.innerHTML = topTexts[j];
1105 tooltip.appendChild(paragraph);
1106 }
1107 if (bottomTexts.length > 0)
1108 {
1109 var notes = document.createElement("div");
1110 notes.className = "notes";
1111 for (var j = 0; j < bottomTexts.length; j++)
1112 {
1113 var paragraph = document.createElement("p");
1114 paragraph.innerHTML = bottomTexts[j];
1115 notes.appendChild(paragraph);
1116 }
1117 tooltip.appendChild(notes);
1118 }
1119
1120 wrapper.appendChild(tooltip);
1121 }
1038 } 1122 }
1039 1123
1040 ext.onMessage.addListener(function(message) 1124 ext.onMessage.addListener(function(message)
1041 { 1125 {
1042 switch (message.type) 1126 switch (message.type)
1043 { 1127 {
1044 case "app.respond": 1128 case "app.respond":
1045 switch (message.action) 1129 switch (message.action)
1046 { 1130 {
1047 case "addSubscription": 1131 case "addSubscription":
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 }); 1171 });
1088 ext.backgroundPage.sendMessage( 1172 ext.backgroundPage.sendMessage(
1089 { 1173 {
1090 type: "subscriptions.listen", 1174 type: "subscriptions.listen",
1091 filter: ["added", "disabled", "homepage", "lastDownload", "removed", 1175 filter: ["added", "disabled", "homepage", "lastDownload", "removed",
1092 "title", "downloadStatus", "downloading"] 1176 "title", "downloadStatus", "downloading"]
1093 }); 1177 });
1094 1178
1095 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); 1179 window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
1096 })(); 1180 })();
LEFTRIGHT

Powered by Google App Engine
This is Rietveld