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

Side by Side Diff: options.js

Issue 29334038: Issue 2802/2358 - Dynamically generate tooltips in options page (Closed)
Patch Set: Rebased to 536c9b810423 Created March 21, 2016, 2:04 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
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
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 var table = E(this.details[j].id); 80 var table = E(this.details[j].id);
81 var template = table.querySelector("template"); 81 var template = table.querySelector("template");
82 for (var i = 0; i < arguments.length; i++) 82 for (var i = 0; i < arguments.length; i++)
83 { 83 {
84 var item = arguments[i]; 84 var item = arguments[i];
85 var listItem = document.createElement("li"); 85 var listItem = document.createElement("li");
86 listItem.appendChild(document.importNode(template.content, true)); 86 listItem.appendChild(document.importNode(template.content, true));
87 listItem.setAttribute("data-access", item.url || item.text); 87 listItem.setAttribute("data-access", item.url || item.text);
88 88
89 var labelId = "label-" + (++maxLabelId); 89 var labelId = "label-" + (++maxLabelId);
90 listItem.querySelector(".display").setAttribute("id", labelId); 90 var display = listItem.querySelector(".display");
91 display.setAttribute("id", labelId);
92 if (item.type)
93 display.setAttribute("data-tooltip-value", item.type);
91 var control = listItem.querySelector(".control"); 94 var control = listItem.querySelector(".control");
92 if (control) 95 if (control)
93 { 96 {
94 // We use aria-labelledby to avoid triggering the control when 97 // We use aria-labelledby to avoid triggering the control when
95 // interacting with the label 98 // interacting with the label
96 control.setAttribute("aria-labelledby", labelId); 99 control.setAttribute("aria-labelledby", labelId);
97 control.addEventListener("click", this.details[j].onClick, false); 100 control.addEventListener("click", this.details[j].onClick, false);
98 } 101 }
99 102
100 this._setEmpty(table, null); 103 this._setEmpty(table, null);
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 { 372 {
370 collections.allLangs.removeItem(subscription); 373 collections.allLangs.removeItem(subscription);
371 collections.langs.addItems(subscription); 374 collections.langs.addItems(subscription);
372 } 375 }
373 else 376 else
374 { 377 {
375 collections.allLangs.addItems(subscription); 378 collections.allLangs.addItems(subscription);
376 collections.langs.removeItem(subscription); 379 collections.langs.removeItem(subscription);
377 } 380 }
378 } 381 }
382 updateTooltips();
saroyanm 2016/03/24 18:27:51 Why do you update tooltip on every update ? I thin
Thomas Greiner 2016/05/31 17:00:01 Since we no longer use `observeSubscription()` I m
379 } 383 }
380 for (var i in collections) 384 for (var i in collections)
381 collections[i].updateItem(subscription); 385 collections[i].updateItem(subscription);
382 } 386 }
383 } 387 }
384 388
385 if (!Object.observe) 389 if (!Object.observe)
386 { 390 {
387 ["disabled", "lastDownload"].forEach(function(property) 391 ["disabled", "lastDownload"].forEach(function(property)
388 { 392 {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 return response.text(); 476 return response.text();
473 }) 477 })
474 .then(function(text) 478 .then(function(text)
475 { 479 {
476 var list = document.getElementById("subscriptionSelector"); 480 var list = document.getElementById("subscriptionSelector");
477 var doc = new DOMParser().parseFromString(text, "application/xml"); 481 var doc = new DOMParser().parseFromString(text, "application/xml");
478 var elements = doc.documentElement.getElementsByTagName("subscription"); 482 var elements = doc.documentElement.getElementsByTagName("subscription");
479 for (var i = 0; i < elements.length; i++) 483 for (var i = 0; i < elements.length; i++)
480 { 484 {
481 var element = elements[i]; 485 var element = elements[i];
482 var subscription = Object.create(null); 486 var recommendation = {type: element.getAttribute("type")};
saroyanm 2016/03/24 18:27:51 Do we need reccomendationMap ? I think it's possib
Thomas Greiner 2016/05/31 17:00:02 Indeed, `recommendationsMap` was no longer necessa
483 subscription.title = element.getAttribute("title"); 487 var subscription = {
484 subscription.url = element.getAttribute("url"); 488 disabled: null,
485 subscription.disabled = null; 489 downloadStatus: null,
486 subscription.downloadStatus = null; 490 homepage: null,
487 subscription.homepage = null; 491 lastDownload: null,
488 var recommendation = Object.create(null); 492 title: element.getAttribute("title"),
489 recommendation.type = element.getAttribute("type"); 493 type: recommendation.type,
494 url: element.getAttribute("url")
495 };
490 var prefix = element.getAttribute("prefixes"); 496 var prefix = element.getAttribute("prefixes");
491 if (prefix) 497 if (prefix)
492 { 498 {
493 prefix = prefix.replace(/\W/g, "_"); 499 prefix = prefix.replace(/\W/g, "_");
494 subscription.title = getMessage("options_language_" + prefix); 500 subscription.title = getMessage("options_language_" + prefix);
495 } 501 }
496 else 502 else
497 { 503 {
498 var type = recommendation.type.replace(/\W/g, "_"); 504 var type = recommendation.type.replace(/\W/g, "_");
499 subscription.title = getMessage("common_feature_" + type + "_title") ; 505 subscription.title = getMessage("common_feature_" + type + "_title") ;
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 } 1074 }
1069 else 1075 else
1070 tab.addEventListener("click", onShareLinkClick, false); 1076 tab.addEventListener("click", onShareLinkClick, false);
1071 } 1077 }
1072 } 1078 }
1073 1079
1074 for (var i = 0; i < shareResources.length; i++) 1080 for (var i = 0; i < shareResources.length; i++)
1075 checkShareResource(shareResources[i], onResult); 1081 checkShareResource(shareResources[i], onResult);
1076 } 1082 }
1077 1083
1084 function getMessages(id)
1085 {
1086 var messages = [];
1087 for (var i = 1; true; i++)
1088 {
1089 var message = ext.i18n.getMessage(id + "_" + i);
1090 if (!message)
1091 break;
1092
1093 messages.push(message);
1094 }
1095 return messages;
1096 }
1097
1098 function updateTooltips()
1099 {
1100 var anchors = document.querySelectorAll(":not(.tooltip) > [data-tooltip]");
1101 for (var i = 0; i < anchors.length; i++)
1102 {
1103 var anchor = anchors[i];
saroyanm 2016/03/24 18:27:50 Why does it called anchor ?
Thomas Greiner 2016/05/31 17:00:01 Because it's the element the tooltip is anchored/a
1104 var id = anchor.getAttribute("data-tooltip");
1105 id = id.replace("%value%", anchor.getAttribute("data-tooltip-value"));
saroyanm 2016/03/24 18:27:50 Why not to do this when the item is added ? Curre
Thomas Greiner 2016/05/31 17:00:02 Done.
1106
1107 var wrapper = document.createElement("div");
saroyanm 2016/03/24 18:27:50 Why do we need create a wrapper for elements that
Thomas Greiner 2016/05/31 17:00:01 Because the alternative would be to put the toolti
1108 wrapper.className = "tooltip";
1109 anchor.parentNode.replaceChild(wrapper, anchor);
1110 wrapper.appendChild(anchor);
1111
1112 var topTexts = getMessages(id);
1113 var bottomTexts = getMessages(id + "_notes");
1114
1115 // We have to use native tooltips to avoid issues when attaching a tooltip
1116 // to an element in a scrollable list or otherwise it might get cut off
1117 if (anchor.hasAttribute("data-tooltip-native"))
1118 {
1119 var title = topTexts.concat(bottomTexts).join("\n\n");
1120 anchor.setAttribute("title", title);
1121 continue;
1122 }
1123
1124 var tooltip = document.createElement("div");
1125 tooltip.setAttribute("role", "tooltip");
1126
1127 var flip = anchor.getAttribute("data-tooltip-flip");
1128 if (flip)
1129 tooltip.className = "flip-" + flip;
1130
1131 var imageSource = anchor.getAttribute("data-tooltip-image");
saroyanm 2016/03/24 18:27:51 According to the ticket image attribute should be
Thomas Greiner 2016/05/31 17:00:02 It's just tricky to determine whether the image ex
1132 if (imageSource)
1133 {
1134 var image = document.createElement("img");
1135 image.src = imageSource;
1136 image.alt = "";
1137 tooltip.appendChild(image);
1138 }
1139
1140 for (var j = 0; j < topTexts.length; j++)
1141 {
1142 var paragraph = document.createElement("p");
1143 paragraph.textContent = topTexts[j];
1144 tooltip.appendChild(paragraph);
1145 }
1146 if (bottomTexts.length > 0)
1147 {
1148 var notes = document.createElement("div");
1149 notes.className = "notes";
1150 for (var j = 0; j < bottomTexts.length; j++)
1151 {
1152 var paragraph = document.createElement("p");
1153 paragraph.textContent = bottomTexts[j];
1154 notes.appendChild(paragraph);
1155 }
1156 tooltip.appendChild(notes);
1157 }
1158
1159 wrapper.appendChild(tooltip);
1160 }
1161 }
1162
1078 ext.onMessage.addListener(function(message) 1163 ext.onMessage.addListener(function(message)
1079 { 1164 {
1080 switch (message.type) 1165 switch (message.type)
1081 { 1166 {
1082 case "app.listen": 1167 case "app.listen":
1083 if (message.action == "addSubscription") 1168 if (message.action == "addSubscription")
1084 { 1169 {
1085 var subscription = message.args[0]; 1170 var subscription = message.args[0];
1086 var dialog = E("dialog-content-predefined"); 1171 var dialog = E("dialog-content-predefined");
1087 dialog.querySelector("h3").textContent = subscription.title || ""; 1172 dialog.querySelector("h3").textContent = subscription.title || "";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 }); 1205 });
1121 ext.backgroundPage.sendMessage( 1206 ext.backgroundPage.sendMessage(
1122 { 1207 {
1123 type: "subscriptions.listen", 1208 type: "subscriptions.listen",
1124 filter: ["added", "disabled", "homepage", "lastDownload", "removed", 1209 filter: ["added", "disabled", "homepage", "lastDownload", "removed",
1125 "title"] 1210 "title"]
1126 }); 1211 });
1127 1212
1128 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); 1213 window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
1129 })(); 1214 })();
OLDNEW
« options.html ('K') | « options.html ('k') | skin/options.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld