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

Delta Between Two Patch Sets: options.js

Issue 6088024630755328: issue 1526 - Implement new options page design for Chrome/Opera/Safari (Closed)
Left Patch Set: Created Feb. 13, 2015, 10:52 a.m.
Right Patch Set: Comment about solution being temprorary is added to subscriptions.xml Created June 13, 2015, 12:59 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 | « options.html ('k') | skin/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-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 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 acceptableAdsUrl = null; 22 var subscriptionsMap = Object.create(null);
23 23 var recommendationsMap = Object.create(null);
24 var optionObj = 24 var filtersMap = Object.create(null);
25 { 25 var collections = Object.create(null);
26 collections: 26
27 { 27 function Collection(details)
28 push: function() 28 {
29 { 29 this.details = details;
30 var length = Array.prototype.push.apply(this, arguments); 30 this.items = [];
31 this.sort(function(a, b) 31 }
32 { 32
33 var aValue = (a.title || a.url || a.text).toLowerCase(); 33 Collection.prototype.addItems = function()
34 var bValue = (b.title || b.url || a.text).toLowerCase(); 34 {
35 if (aValue < bValue) 35 var length = Array.prototype.push.apply(this.items, arguments);
36 return -1; 36 if (length == 0)
37 if (aValue > bValue) 37 return;
38 return 1; 38
39 return 0; 39 this.items.sort(function(a, b)
40 }); 40 {
41 for (var i=0; i < arguments.length; i++) 41 var aValue = (a.title || a.url || a.text).toLowerCase();
42 { 42 var bValue = (b.title || b.url || a.text).toLowerCase();
43 for (var j=0; j < this.table.length; j++) 43 return aValue.localeCompare(bValue);
44 });
45
46 for (var j = 0; j < this.details.length; j++)
47 {
48 var table = E(this.details[j].id);
49 var template = table.querySelector("template");
50 for (var i = 0; i < arguments.length; i++)
51 {
52 var item = arguments[i];
53 var text = item.title || item.url || item.text;
54 var listItem = document.createElement("li");
55 listItem.appendChild(document.importNode(template.content, true));
56 listItem.dataset.access = item.url || item.text;
57 listItem.querySelector(".display").textContent = text;
58 if (text)
59 listItem.dataset.search = text.toLowerCase();
60
61 var control = listItem.querySelector(".control");
62 if (control)
63 {
64 control.addEventListener("click", this.details[j].onClick, false);
65 control.checked = item.disabled == false;
66 }
67
68 if (table.hasChildNodes())
69 table.insertBefore(listItem, table.childNodes[this.items.indexOf(item) ]);
70 else
71 table.appendChild(listItem);
72 }
73 }
74 return length;
75 };
76
77 Collection.prototype.removeItem = function(item)
78 {
79 var index = this.items.indexOf(item);
80 if (index == -1)
81 return;
82
83 this.items.splice(index, 1);
84 var access = (item.url || item.text).replace(/'/g, "\\'");
85 for (var i = 0; i < this.details.length; i++)
86 {
87 var table = E(this.details[i].id);
88 var element = table.querySelector("[data-access='" + access + "']");
89 element.parentElement.removeChild(element);
90 }
91 };
92
93 Collection.prototype.clearAll = function()
94 {
95 for (var i = 0; i < this.details.length; i++)
96 {
97 var table = E(this.details[i].id);
98 var template = table.querySelector("template");
99 table.innerHTML = "";
100 table.appendChild(template);
101 }
102 this.items.length = 0;
103 };
104
105 function onToggleSubscriptionClick(e)
106 {
107 e.preventDefault();
108 var subscriptionUrl = e.target.parentNode.dataset.access;
109 if (!e.target.checked)
110 removeSubscription(subscriptionUrl);
111 else
112 addEnableSubscription(subscriptionUrl);
113 }
114
115 function onAddLanguageSubscriptionClick(e)
116 {
117 e.preventDefault();
118 var url = this.parentNode.dataset.access;
119 addEnableSubscription(url);
120 }
121
122 function onRemoveFilterClick()
123 {
124 var filter = this.parentNode.dataset.access;
125 removeFilter(filter);
126 }
127
128 collections.popular = new Collection(
129 [
130 {
131 id: "recommend-list-table",
132 onClick: onToggleSubscriptionClick
133 }
134 ]);
135 collections.langs = new Collection(
136 [
137 {
138 id: "blocking-languages-table",
139 onClick: onToggleSubscriptionClick
140 },
141 {
142 id: "blocking-languages-dialog-table"
143 }
144 ]);
145 collections.allLangs = new Collection(
146 [
147 {
148 id: "all-lang-table",
149 onClick: onAddLanguageSubscriptionClick
150 }
151 ]);
152 collections.acceptableAds = new Collection(
153 [
154 {
155 id: "acceptableads-table",
156 onClick: onToggleSubscriptionClick
157 }
158 ]);
159 collections.custom = new Collection(
160 [
161 {
162 id: "custom-list-table",
163 onClick: onToggleSubscriptionClick
164 }
165 ]);
166 collections.whitelist = new Collection(
167 [
168 {
169 id: "whitelisting-table",
170 onClick: onRemoveFilterClick
171 }
172 ]);
173
174 function updateSubscription(subscription)
175 {
176 var subscriptionUrl = subscription.url;
177 var knownSubscription = subscriptionsMap[subscriptionUrl];
178 if (knownSubscription)
179 knownSubscription.disabled = subscription.disabled;
180 else
181 {
182 getAcceptableAdsURL(function(acceptableAdsUrl)
183 {
184 function onObjectChanged()
185 {
186 var access = (subscriptionUrl || subscription.text).replace(/'/g, "\\' ");
187 var elements = document.querySelectorAll("[data-access='" + access + " ']");
188 for (var i = 0; i < elements.length; i++)
44 { 189 {
45 var object = arguments[i]; 190 var element = elements[i];
46 var text = object.title || object.text; 191 var control = element.querySelector(".control");
47 var access = object.url || object.text; 192 if (control.localName == "input")
48 var index = this.indexOf(object); 193 control.checked = subscription.disabled == false;
49 var table = E(this.table[j].id); 194 if (subscriptionUrl in recommendationsMap)
50 var template = this.table[j].template;
51 var listener = this.table[j].listener;
52
53 var list = document.createElement("li");
54 list.innerHTML = template;
55 list.dataset.access = access;
56 list.getElementsByClassName("display")[0].textContent = text;
57 if (object.isAdsType)
58 list.dataset.value = text.toLowerCase();
59
60 var control = list.getElementsByClassName("control")[0];
61 if (control)
62 { 195 {
63 control.addEventListener("click", listener, false); 196 var recommendation = recommendationsMap[subscriptionUrl];
64 control.checked = !object.disabled; 197 if (recommendation.isAdsType)
65 }
66 if (table.hasChildNodes)
67 table.insertBefore(list, table.childNodes[index]);
68 else
69 table.appendChild(list);
70 }
71 }
72 return length;
73 },
74 remove: function(obj)
75 {
76 var index = this.indexOf(obj);
77 this.splice(index, 1);
78 var access = obj.url || obj.text;
79 for (var i=0; i < this.table.length; i++)
80 {
81 var table = E(this.table[i].id);
82 var element = table.querySelector("[data-access='"+access+"']");
83 element.parentElement.removeChild(element);
84 }
85 }
86 },
87 subscriptions: {
88 getArray: function(subscription)
89 {
90 var collArray = null;
91 if (subscription.isPopular)
92 collArray = collections.popular;
93 else if (subscription.isAdsType && subscription.disabled)
94 collArray = collections.allLangs;
95 else if (subscription.isAdsType && !subscription.disabled)
96 collArray = collections.langs;
97 else if (subscription.url == acceptableAdsUrl)
98 collArray = collections.acceptableAds;
99 else
100 collArray = collections.custom;
101 return collArray;
102 },
103 update: function(subscription)
104 {
105 var optionSubscription = this[subscription.url];
106 if (optionSubscription)
107 optionSubscription.disabled = subscription.disabled;
108 else
109 {
110 var collArray = this.getArray(subscription);
111 optionObj.observe(subscription, ["disabled"]);
112 collArray.push = collections.push;
113 collArray.push(subscription);
114 this[subscription.url] = subscription;
115 }
116 },
117 remove: function(subscription)
118 {
119 var optionSubscription = this[subscription.url];
120
121 if (optionSubscription.isAdsType)
122 {
123 collections.langs.remove(optionSubscription);
124 collections.allLangs.push(optionSubscription);
125 }
126 else if(optionSubscription.isPopular)
127 {
128 optionSubscription.disabled = true;
129 }
130 else
131 {
132 collections.custom.remove(optionSubscription);
133 }
134 },
135 chboxListener: function(e)
136 {
137 e.preventDefault();
138 var target = e.target;
139 var isChecked = target.checked;
140 var url = e.target.parentNode.dataset.access;
141 if (!isChecked)
142 SendMessage.removeSubscription(url);
143 else
144 SendMessage.addSubscription(url);
145 },
146 acceptableAdsListener: function(e)
147 {
148 e.preventDefault();
149 var target = e.target;
150 var isChecked = target.checked;
151 var url = e.target.parentNode.dataset.access;
152
153 if (isChecked)
154 SendMessage.addSubscription(url);
155 else
156 SendMessage.removeSubscription(url);
157 },
158 addBtnListener: function(e)
159 {
160 e.preventDefault();
161 var url = this.parentNode.dataset.access;
162 SendMessage.addSubscription(url);
163 }
164 },
165 filters:
166 {
167 update: function(filter)
168 {
169 var optionFilter = this[filter.text];
170 var match = filter.text.match(/^@@\|\|([^\/:]+)\^\$document$/);
171 if (match && !optionFilter)
172 {
173 filter.title = match[1];
174 collections.whitelist.push(filter);
175 this[filter.text] = filter;
176 }
177 else
178 {
179 // TODO: add `filters[i].text` to list of custom filters
180 }
181 },
182 remove: function(filter)
183 {
184 collections.whitelist.remove(filter);
185 },
186 deleteBtnClick: function()
187 {
188 var filter = this.parentNode.dataset.access;
189 SendMessage.removeFilter(filter);
190 }
191 },
192 observe: function(obj, props)
193 {
194 props.forEach(function(property)
195 {
196 obj["__"+property] = obj[property];
197 Object.defineProperty(obj, property,
198 {
199 get: function()
200 {
201 return this["__"+property];
202 },
203 set: function(value)
204 {
205 this["__"+property] = value;
206 var access = obj.url || obj.text;
207 var elements = document.querySelectorAll("[data-access='" + access + "']");
208 for (var i=0; i < elements.length; i++)
209 {
210 var elem = elements[i];
211 var control = elem.getElementsByClassName("control")[0];
212 if (control.tagName == "INPUT")
213 control.checked = !obj.disabled;
214 if (obj.isAdsType)
215 { 198 {
216 collections.allLangs.remove(obj); 199 if (subscription.disabled == false)
217 collections.langs.push(obj); 200 {
201 collections.allLangs.removeItem(subscription);
202 collections.langs.addItems(subscription);
203 }
204 else
205 {
206 collections.allLangs.addItems(subscription);
207 collections.langs.removeItem(subscription);
208 }
218 } 209 }
219 } 210 }
220 } 211 }
221 }); 212 }
213
214 if (!Object.observe)
215 {
216 // Currently only "disabled" property of subscription used for observa tion
217 // but with Advanced tab implementation we should also add more proper ties.
218 ["disabled"].forEach(function(property)
219 {
220 subscription["$" + property] = subscription[property];
221 Object.defineProperty(subscription, property,
222 {
223 get: function()
224 {
225 return this["$" + property];
226 },
227 set: function(value)
228 {
229 this["$" + property] = value;
230 onObjectChanged();
231 }
232 });
233 });
234 }
235 else
236 {
237 Object.observe(subscription, onObjectChanged);
238 }
239
240 var collection = null;
241 if (subscriptionUrl in recommendationsMap)
242 {
243 var recommendation = recommendationsMap[subscriptionUrl];
244 if (recommendation.isPopular)
245 collection = collections.popular;
246 else if (recommendation.isAdsType && subscription.disabled == false)
247 collection = collections.langs;
248 else
249 collection = collections.allLangs;
250 }
251 else if (subscriptionUrl == acceptableAdsUrl)
252 collection = collections.acceptableAds;
253 else
254 collection = collections.custom;
255
256 collection.addItems(subscription);
257 subscriptionsMap[subscriptionUrl] = subscription;
222 }); 258 });
223 } 259 }
224 }; 260 }
225 261
226 function createCollArray(tables) 262 function updateFilter(filter)
227 { 263 {
228 var array = []; 264 var match = filter.text.match(/^@@\|\|([^\/:]+)\^\$document$/);
229 array.push = optionObj.collections.push; 265 if (match && !filtersMap[filter.text])
230 array.remove = optionObj.collections.remove; 266 {
231 array.table = tables; 267 filter.title = match[1];
232 return array; 268 collections.whitelist.addItems(filter);
233 } 269 filtersMap[filter.text] = filter
234 270 }
235 var collections = optionObj.collections; 271 else
236 collections.popular = createCollArray([ 272 {
237 { 273 // TODO: add `filters[i].text` to list of custom filters
238 id: "recommend-list-table", 274 }
239 template: "<input type='checkbox' class='control' /><span class='display'> </span><span class='popular'>popular</span>", 275 }
240 listener: optionObj.subscriptions.chboxListener 276
241 } 277 function loadRecommendations()
242 ]); 278 {
243 collections.langs = createCollArray([ 279 var request = new XMLHttpRequest();
244 { 280 request.open("GET", "subscriptions.xml", false);
245 id: "blocking-languages-table", 281 request.addEventListener("load", function()
246 template: "<input type='checkbox' class='control' /><span class='display'> </span>", 282 {
247 listener: optionObj.subscriptions.chboxListener 283 var list = document.getElementById("subscriptionSelector");
248 }, 284 var docElem = request.responseXML.documentElement;
249 { 285 var elements = docElem.getElementsByTagName("subscription");
250 id: "blocking-languages-modal-table", 286 for (var i = 0; i < elements.length; i++)
251 template: "<span class='display'></span>" 287 {
252 } 288 var element = elements[i];
253 ]); 289 var subscription = Object.create(null);
254 collections.allLangs = createCollArray([ 290 subscription.title = element.getAttribute("title");
255 { 291 subscription.url = element.getAttribute("url");
256 id: "all-lang-table", 292 subscription.disabled = null;
257 template: "<button class='button-add control'><span>+add</span></button><s pan class='display'></span>", 293 subscription.downloadStatus = null;
258 listener: optionObj.subscriptions.addBtnListener 294 subscription.homepage = null;
259 } 295 subscription.lastSuccess = null;
260 ]); 296 var recommendation = Object.create(null);
261 collections.acceptableAds = createCollArray([ 297 recommendation.isAdsType = false;
262 { 298 recommendation.isPopular = false;
263 id: "acceptableads-table", 299 var prefix = element.getAttribute("prefixes");
264 template: "<input type='checkbox' class='control' /><span class='display'> </span>", 300 if (prefix)
265 listener: optionObj.subscriptions.acceptableAdsListener 301 {
266 } 302 var prefix = element.getAttribute("prefixes").replace(/,/g, "_");
267 ]); 303 subscription.title = ext.i18n.getMessage("options_language_" + prefix) ;
268 collections.custom = createCollArray([ 304 recommendation.isAdsType = true;
269 {
270 id: "custom-list-table",
271 template: "<input type='checkbox' class='control' /><span class='display'> </span>",
272 listener: optionObj.subscriptions.chboxListener
273 }
274 ]);
275 collections.whitelist = createCollArray([
276 {
277 id: "whitelisting-table",
278 template: "<button class='delete control'></button><span class='display'>< /span>",
279 listener: optionObj.filters.deleteBtnClick
280 }
281 ]);
282
283 var Recommendations =
284 {
285 load: function()
286 {
287 var request = new XMLHttpRequest();
288 request.open("GET", "subscriptions.xml", false);
289 request.onload = function()
290 {
291 var list = document.getElementById("subscriptionSelector");
292 var docElem = request.responseXML.documentElement;
293 var elements = docElem.getElementsByTagName("subscription");
294 for (var i = 0; i < elements.length; i++)
295 {
296 var element = elements[i];
297 var subscription = Object.create(null);
298 subscription.title = element.getAttribute("title");
299 subscription.url = element.getAttribute("url");
300 subscription.disabled = true;
301 var prefix = element.getAttribute("prefixes");
302 if (prefix)
303 {
304 subscription.isAdsType = true;
305 var prefix = element.getAttribute("prefixes").replace(/,/g, '_');
306 subscription.title = ext.i18n.getMessage("options_language_" + prefi x);
307 }
308 else
309 subscription.title = element.getAttribute("specialization");
310
311 if (element.getAttribute("popular"))
312 subscription.isPopular = true;
313 optionObj.subscriptions.update(subscription);
314 } 305 }
315 }.bind(this); 306 else
316 request.send(); 307 subscription.title = element.getAttribute("specialization");
317 } 308
318 }; 309 if (element.getAttribute("popular"))
319 310 recommendation.isPopular = true;
311
312 recommendationsMap[subscription.url] = recommendation;
313 updateSubscription(subscription);
314 }
315 }, false);
316 request.send(null);
317 }
318
320 function onDOMLoaded() 319 function onDOMLoaded()
321 { 320 {
321 var recommendationTemplate = document.querySelector("#recommend-list-table t emplate");
322 var popularText = ext.i18n.getMessage("options_popular");
323 recommendationTemplate.content.querySelector(".popular").textContent = popul arText;
324 var languagesTemplate = document.querySelector("#all-lang-table template");
325 var buttonText = ext.i18n.getMessage("options_button_add");
326 languagesTemplate.content.querySelector(".button-add span").textContent = bu ttonText;
327
322 updateShareLink(); 328 updateShareLink();
323 populateLists(); 329 populateLists();
324 330
325 var tabList = document.querySelectorAll("#main-navigation-tabs li"); 331 var tabList = document.querySelectorAll("#main-navigation-tabs li");
326 for (var i = 0; i < tabList.length; ++i) 332 for (var i = 0; i < tabList.length; i++)
327 { 333 {
328 tabList[i].addEventListener("click", function(ev) 334 tabList[i].addEventListener("click", function(e)
329 { 335 {
330 document.body.dataset.tab = this.id.substr(4); 336 document.body.dataset.tab = e.currentTarget.dataset.show;
331 }, false); 337 }, false);
332 } 338 }
333 339
334 var searchLanguage = function() 340 function onFindLanguageKeyUp()
335 { 341 {
336 var searchStyle = document.getElementById('search_style'); 342 var searchStyle = E("search-style");
Thomas Greiner 2015/02/18 17:19:27 You're using `document.getElementById()` here but
337 var searchVal = this.value; 343 if (!this.value)
338 if (!searchVal)
339 searchStyle.innerHTML = ""; 344 searchStyle.innerHTML = "";
340 else 345 else
341 searchStyle.innerHTML = "#all-lang-table li:not([data-value*=\"" + this. value.toLowerCase() + "\"]) { display: none; }"; 346 searchStyle.innerHTML = "#all-lang-table li:not([data-search*=\"" + this .value.toLowerCase() + "\"]) { display: none; }";
342 }; 347 }
343 348
344 // Update version number in navigation sidebar 349 // Update version number in navigation sidebar
345 ext.backgroundPage.sendMessage({ 350 ext.backgroundPage.sendMessage(
351 {
346 method: "app.get", 352 method: "app.get",
347 what: "addonVersion" 353 what: "addonVersion"
348 }, function(addonVersion) 354 },
349 { 355 function(addonVersion)
350 E("abp-version").textContent = addonVersion; 356 {
357 E("abp-version").textContent = addonVersion;
351 }); 358 });
352 359
353 var whitelistDomainBtnClick = function() 360 var placeholderValue = ext.i18n.getMessage("options_dialog_language_find");
354 {
355 var domain = E("whitelisting-textbox").value;
356 if (domain)
357 SendMessage.addWhitelistedDomain(domain);
358 E("whitelisting-textbox").value = "";
359 };
360
361 var placeholderValue = ext.i18n.getMessage("options_modal_language_find");
362 E("find-language").setAttribute("placeholder", placeholderValue); 361 E("find-language").setAttribute("placeholder", placeholderValue);
363 setLinks("block-element-explanation", "#");
364
365 E("add-blocking-list").addEventListener("click", function() 362 E("add-blocking-list").addEventListener("click", function()
366 { 363 {
367 openModal("customlist"); 364 openDialog("customlist");
368 }, false); 365 }, false);
369 E("add-website-language").addEventListener("click", function() 366 E("add-website-language").addEventListener("click", function()
370 { 367 {
371 openModal("language"); 368 openDialog("language");
372 }, false); 369 }, false);
373 E("modal-close").addEventListener("click", function() 370 E("dialog-close").addEventListener("click", function()
374 { 371 {
375 delete document.body.dataset.modal; 372 delete document.body.dataset.dialog;
376 }, false); 373 }, false);
377 E("edit-ownBlockingList-btn").addEventListener("click", editOwnRulsBtnClick, false); 374 E("edit-ownBlockingList-button").addEventListener("click", editCustomFilters , false);
378 E("find-language").addEventListener("keyup", searchLanguage, false); 375 E("find-language").addEventListener("keyup", onFindLanguageKeyUp, false);
379 E("whitelisting-add-icon").addEventListener("click", whitelistDomainBtnClick , false); 376 E("whitelisting").addEventListener("click", function(e)
380 E("whitelisting-add-btn").addEventListener("click", whitelistDomainBtnClick, false); 377 {
381 E("whitelisting-enter-icon").addEventListener("click", whitelistDomainBtnCli ck, false); 378 var id = e.target.id;
379 if (id == "whitelisting-add-icon" || id == "whitelisting-enter-icon")
380 addWhitelistedDomain();
381 else if (id == "whitelisting-cancel-button")
382 E("whitelisting-textbox").value = "";
383 }, false);
384 E("whitelisting-add-button").addEventListener("click", addWhitelistedDomain, false);
382 E("whitelisting-textbox").addEventListener("keypress", function(e) 385 E("whitelisting-textbox").addEventListener("keypress", function(e)
383 { 386 {
384 if (e.keyCode == 13) 387 // e.keyCode has been deprecated so we attempt to use e.key
385 whitelistDomainBtnClick(); 388 // keyCode "13" corresponds to "Enter"
389 if ((e.key && e.key == "Enter") || (!e.key && e.keyCode == 13))
390 addWhitelistedDomain();
386 }, false); 391 }, false);
387 E("whitelisting-cancel-btn").addEventListener("click", function() 392 E("import-blockingList-button").addEventListener("click", function()
388 { 393 {
389 E("whitelisting-textbox").value = ""; 394 var url = E("blockingList-textbox").value;
395 addEnableSubscription(url);
396 delete document.body.dataset.dialog;
390 }, false); 397 }, false);
391 E("import-blockingList-btn").addEventListener("click", function() 398 }
392 { 399
393 var url = E("blockingList-textbox").value; 400 function openDialog(name)
394 SendMessage.addSubscription(url); 401 {
395 delete document.body.dataset.modal; 402 document.body.dataset.dialog = name;
396 }, false); 403 }
397 } 404
398
399 function openModal(name)
400 {
401 document.body.dataset.modal = name;
402 var title = "options_modal_" + name + "_title";
403 E("modal-title").textContent = ext.i18n.getMessage(title);
404 }
405
406 function populateLists() 405 function populateLists()
407 { 406 {
407 subscriptionsMap = Object.create(null);
408 filtersMap = Object.create(null);
409 recommendationsMap = Object.create(null);
410
411 // Empty collections and lists
412 for (var property in collections)
413 collections[property].clearAll();
414
408 ext.backgroundPage.sendMessage( 415 ext.backgroundPage.sendMessage(
409 { 416 {
410 type: "subscriptions.get", 417 type: "subscriptions.get",
411 special: true 418 special: true
412 }, function(subscriptions) 419 },
420 function(subscriptions)
413 { 421 {
414 // Load filters 422 // Load filters
415 for (var i = 0; i < subscriptions.length; i++) 423 for (var i = 0; i < subscriptions.length; i++)
416 { 424 {
417 ext.backgroundPage.sendMessage( 425 ext.backgroundPage.sendMessage(
418 { 426 {
419 type: "filters.get", 427 type: "filters.get",
420 subscriptionUrl: subscriptions[i].url 428 subscriptionUrl: subscriptions[i].url
421 }, function(filters) 429 },
430 function(filters)
422 { 431 {
423 for (var i = 0; i < filters.length; i++) 432 for (var i = 0; i < filters.length; i++)
424 optionObj.filters.update(filters[i]); 433 updateFilter(filters[i]);
425 }); 434 });
426 } 435 }
427 }); 436 });
428 Recommendations.load(); 437 loadRecommendations();
429 SendMessage.getAcceptableAdsURL(function(url) 438 getAcceptableAdsURL(function(acceptableAdsUrl)
430 { 439 {
431 acceptableAdsUrl = url;
432 var subscription = Object.create(null); 440 var subscription = Object.create(null);
433 subscription.url = acceptableAdsUrl; 441 subscription.url = acceptableAdsUrl;
434 subscription.disabled = true; 442 subscription.disabled = true;
435 subscription.title = ext.i18n.getMessage("options_acceptableAds_descriptio n"); 443 subscription.title = ext.i18n.getMessage("options_acceptableAds_descriptio n");
436 optionObj.subscriptions.update(subscription); 444 updateSubscription(subscription);
437 445
438 // Load user subscriptions 446 // Load user subscriptions
439 ext.backgroundPage.sendMessage( 447 ext.backgroundPage.sendMessage(
440 { 448 {
441 type: "subscriptions.get", 449 type: "subscriptions.get",
442 downloadable: true 450 downloadable: true
443 }, function(subscriptions) 451 },
452 function(subscriptions)
444 { 453 {
445 for (var i = 0; i < subscriptions.length; i++) 454 for (var i = 0; i < subscriptions.length; i++)
446 MessageListeners.onSubscriptionMessage("added", subscriptions[i]); 455 onSubscriptionMessage("added", subscriptions[i]);
447 }); 456 });
448 }); 457 });
449 } 458 }
450 459
451 function editOwnRulsBtnClick() 460 function addWhitelistedDomain()
452 { 461 {
453 462 var domain = E("whitelisting-textbox");
454 } 463 if (domain.value)
455
456 var SendMessage =
457 {
458 getAcceptableAdsURL: function(callback)
459 { 464 {
460 ext.backgroundPage.sendMessage( 465 ext.backgroundPage.sendMessage(
461 { 466 {
462 type: "prefs.get", 467 type: "filters.add",
463 key: "subscriptions_exceptionsurl" 468 text: "@@||" + domain.value.toLowerCase() + "^$document"
464 }, function(value)
465 {
466 SendMessage.getAcceptableAdsURL = function(callback)
467 {
468 callback(value);
469 }
470 SendMessage.getAcceptableAdsURL(callback);
471 }); 469 });
470 }
471
472 domain.value = "";
473 }
474
475 function editCustomFilters()
476 {
477 //TODO: NYI
478 }
479
480 function getAcceptableAdsURL(callback)
481 {
482 ext.backgroundPage.sendMessage(
483 {
484 type: "prefs.get",
485 key: "subscriptions_exceptionsurl"
472 }, 486 },
473 addSubscription: function(url, title, homepage) 487 function(value)
474 { 488 {
475 var message = { 489 getAcceptableAdsURL = function(callback)
476 type: "subscriptions.add", 490 {
477 url: url 491 callback(value);
478 };
479 if (title)
480 message.title = title;
481 if (homepage)
482 message.homepage = homepage;
483
484 ext.backgroundPage.sendMessage(message);
485 },
486 removeSubscription: function(url)
487 {
488 ext.backgroundPage.sendMessage(
489 {
490 type: "subscriptions.remove",
491 url: url
492 });
493 },
494 addWhitelistedDomain: function(domain)
495 {
496 ext.backgroundPage.sendMessage(
497 {
498 type: "filters.add",
499 text: "@@||" + domain.toLowerCase() + "^$document"
500 });
501 },
502 removeFilter: function(filter)
503 {
504 ext.backgroundPage.sendMessage(
505 {
506 type: "filters.remove",
507 text: filter
508 });
509 }
510 };
511
512 var MessageListeners =
513 {
514 onFilterMessage: function(action, filter)
515 {
516 switch (action)
517 {
518 case "added":
519 optionObj.filters.update(filter);
520 break;
521 case "loaded":
522 populateLists();
523 break;
524 case "removed":
525 optionObj.filters.remove(filter);
526 break;
527 } 492 }
528 }, 493 getAcceptableAdsURL(callback);
529 onSubscriptionMessage: function(action, subscription) 494 });
530 { 495 }
531 switch (action) 496
532 { 497 function addEnableSubscription(url, title, homepage)
533 case "added": 498 {
534 optionObj.subscriptions.update(subscription); 499 var messageType = null;
535 break; 500 var knownSubscription = subscriptionsMap[url];
536 case "disabled": 501 if (knownSubscription && knownSubscription.disabled == true)
537 break; 502 messageType = "subscriptions.toggle"
538 case "homepage": 503 else
539 // TODO: NYI 504 messageType = "subscriptions.add"
540 break; 505
541 case "removed": 506 var message = {
507 type: messageType,
508 url: url
509 };
510 if (title)
511 message.title = title;
512 if (homepage)
513 message.homepage = homepage;
514
515 ext.backgroundPage.sendMessage(message);
516 }
517
518 function removeSubscription(url)
519 {
520 ext.backgroundPage.sendMessage(
521 {
522 type: "subscriptions.remove",
523 url: url
524 });
525 }
526
527 function removeFilter(filter)
528 {
529 ext.backgroundPage.sendMessage(
530 {
531 type: "filters.remove",
532 text: filter
533 });
534 }
535
536 function onFilterMessage(action, filter)
537 {
538 switch (action)
539 {
540 case "added":
541 updateFilter(filter);
542 updateShareLink();
543 break;
544 case "loaded":
545 populateLists();
546 break;
547 case "removed":
548 var knownFilter = filtersMap[filter.text];
549 collections.whitelist.removeItem(knownFilter);
550 delete filtersMap[filter.text];
551 updateShareLink();
552 break;
553 }
554 }
555
556 function onSubscriptionMessage(action, subscription)
557 {
558 switch (action)
559 {
560 case "added":
561 case "disabled":
562 updateSubscription(subscription);
563 updateShareLink();
564 break;
565 case "homepage":
566 // TODO: NYI
567 break;
568 case "removed":
569 getAcceptableAdsURL(function(acceptableAdsUrl)
570 {
542 if (subscription.url == acceptableAdsUrl) 571 if (subscription.url == acceptableAdsUrl)
543 { 572 {
544 subscription.disabled = true; 573 subscription.disabled = true;
545 optionObj.subscriptions.update(subscription); 574 updateSubscription(subscription);
546 } 575 }
547 else 576 else
548 optionObj.subscriptions.remove(subscription); 577 {
549 break; 578 var knownSubscription = subscriptionsMap[subscription.url];
550 case "title": 579 if (subscription.url in recommendationsMap)
551 // TODO: NYI 580 knownSubscription.disabled = true;
552 break; 581 else
553 } 582 {
554 }, 583 collections.custom.removeItem(knownSubscription);
555 showAddSubscriptionDialog: function(subscription) 584 delete subscriptionsMap[subscription.url];
556 { 585 }
557 E("blockingList-textbox").value = subscription.url; 586 }
558 openModal("customlist"); 587 updateShareLink();
559 } 588 });
560 }; 589 break;
561 590 case "title":
591 // TODO: NYI
592 break;
593 }
594 }
595
596 function showAddSubscriptionDialog(subscription)
597 {
598 E("blockingList-textbox").value = subscription.url;
599 openDialog("customlist");
600 }
601
562 function updateShareLink() 602 function updateShareLink()
563 { 603 {
564 ext.backgroundPage.sendMessage( 604 ext.backgroundPage.sendMessage(
565 { 605 {
566 type: "filters.blocked", 606 type: "filters.blocked",
567 url: "https://platform.twitter.com/widgets/", 607 url: "https://platform.twitter.com/widgets/",
568 requestType: "SCRIPT", 608 requestType: "SCRIPT",
569 docDomain: "adblockplus.org", 609 docDomain: "adblockplus.org",
570 thirdParty: true 610 thirdParty: true
571 }, function(blocked) 611 },
612 function(blocked)
572 { 613 {
573 // TODO: modify "share" link accordingly 614 // TODO: modify "share" link accordingly
574 }); 615 });
575 } 616 }
576 617
577 function getDocLink(link, callback)
578 {
579 ext.backgroundPage.sendMessage(
580 {
581 type: "app.get",
582 what: "doclink",
583 link: link
584 }, callback);
585 }
586
587 function setLinks(id)
588 {
589 var element = E(id);
590 if (!element)
591 {
592 return;
593 }
594
595 var links = element.getElementsByTagName("a");
596
597 for (var i = 0; i < links.length; i++)
598 {
599 if (typeof arguments[i + 1] == "string")
600 {
601 links[i].href = arguments[i + 1];
602 links[i].setAttribute("target", "_blank");
603 }
604 else if (typeof arguments[i + 1] == "function")
605 {
606 links[i].href = "javascript:void(0);";
607 links[i].addEventListener("click", arguments[i + 1], false);
608 }
609 }
610 }
611
612 function E(id) 618 function E(id)
613 { 619 {
614 return document.getElementById(id); 620 return document.getElementById(id);
615 } 621 }
616 622
617 ext.onMessage.addListener(function(message) 623 ext.onMessage.addListener(function(message)
618 { 624 {
619 switch (message.type) 625 switch (message.type)
620 { 626 {
621 case "app.listen": 627 case "app.listen":
622 if (message.action == "addSubscription") 628 if (message.action == "addSubscription")
623 MessageListeners.showAddSubscriptionDialog(message.args[0]); 629 showAddSubscriptionDialog(message.args[0]);
624 break; 630 break;
625 case "filters.listen": 631 case "filters.listen":
626 MessageListeners.onFilterMessage(message.action, message.args[0]); 632 onFilterMessage(message.action, message.args[0]);
627 break; 633 break;
628 case "subscriptions.listen": 634 case "subscriptions.listen":
629 MessageListeners.onSubscriptionMessage(message.action, message.args[0]); 635 onSubscriptionMessage(message.action, message.args[0]);
630 break; 636 break;
631 } 637 }
632 }); 638 });
633 639
634 ext.backgroundPage.sendMessage( 640 ext.backgroundPage.sendMessage(
635 { 641 {
636 type: "app.listen", 642 type: "app.listen",
637 filter: ["addSubscription"] 643 filter: ["addSubscription"]
638 }); 644 });
639 ext.backgroundPage.sendMessage( 645 ext.backgroundPage.sendMessage(
640 { 646 {
641 type: "filters.listen", 647 type: "filters.listen",
642 filter: ["added", "loaded", "removed"] 648 filter: ["added", "loaded", "removed"]
643 }); 649 });
644 ext.backgroundPage.sendMessage( 650 ext.backgroundPage.sendMessage(
645 { 651 {
646 type: "subscriptions.listen", 652 type: "subscriptions.listen",
647 filter: ["added", "disabled", "homepage", "removed", "title"] 653 filter: ["added", "disabled", "homepage", "removed", "title"]
648 }); 654 });
649 655
650 window.addEventListener("DOMContentLoaded", onDOMLoaded, false); 656 window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
651 })(); 657 })();
LEFTRIGHT

Powered by Google App Engine
This is Rietveld