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

Powered by Google App Engine
This is Rietveld