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

Side by Side Diff: options.js

Issue 6088024630755328: issue 1526 - Implement new options page design for Chrome/Opera/Safari (Closed)
Patch Set: Created Jan. 21, 2015, 6:52 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
(Empty)
1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>,
Thomas Greiner 2015/01/22 17:56:30 Nit: Change to "https"
saroyanm 2015/01/23 18:18:39 Done.
3 * Copyright (C) 2006-2015 Eyeo GmbH
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
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/>.
16 */
17
18 "use strict";
19
20 (function()
21 {
22 var optionSubscriptions = {};
23 var acceptableAdsUrl = null;
24
25 function onDOMLoaded()
26 {
27 initTabs();
28 updateShareLink();
29 populateLists();
30
31 E("add-blocking-list").addEventListener("click", Modal.open, false);
32 E("add-website-language").addEventListener("click", Modal.open, false);
33 E("modal-close").addEventListener("click", Modal.close, false);
34 E("whitelisting-add-icon").addEventListener("click", whitelistDomainBtnClick , false);
35 E("whitelisting-add-btn").addEventListener("click", whitelistDomainBtnClick, false);
36 E("whitelisting-enter-icon").addEventListener("click", whitelistDomainBtnCli ck, false);
37 E("whitelisting-textbox").addEventListener("keypress", function(e) {
38 if (e.keyCode == 13)
39 whitelistDomainBtnClick();
40 }, false);
41 E("whitelisting-cancel-btn").addEventListener("click", function(){
42 E("whitelisting-textbox").value = "";
43 }, false);
44 E("allow-whitelist-cb").addEventListener("click", toggleAcceptableAds, false );
45 E("import-blockingList-btn").addEventListener("click", importListBtnCLick, f alse);
46 E("edit-ownBlockingList-btn").addEventListener("click", editOwnRulsBtnClick, false);
47 E("find-language").addEventListener("keyup", searchLanguage, false);
48 }
49
50 function initTabs()
51 {
52 var showContent = function(tab)
53 {
54 var tab = tab.querySelector(".tabs li.active");
55 if (tab.dataset.show)
56 E(tab.dataset.show).style.display = "block";
57 };
58 var optionList = document.querySelectorAll('.tabs li[data-show]');
59 for (var i = 0; i < optionList.length; ++i)
60 {
61 optionList[i].addEventListener("click", function(ev)
62 {
63 var tab = this.parentNode.querySelector(".active");
64 tab.classList.remove("active");
65 this.classList.add("active");
66 E(tab.dataset.show).style.display = "none";;
67 showContent(this.parentNode);
68 }, false);
69 }
70 showContent(E("main-navigation-tabs"));
71 showContent(E("blocking-list-tabs"));
72 }
73
74 var Modal =
75 {
76 open: function (content)
77 {
78 var modal = E("modal");
79 var content = E(this && this.dataset ? this.dataset.show : content);
80 content.style.display = "block";
81 modal.style.visibility = "visible";
82 E("modal-background").style.display = "block";
83 if (content.dataset.title)
84 E("modal-title").innerHTML = ext.i18n.getMessage(content.dataset.title);
85 modal.style.marginTop = -(modal.clientHeight/2)+"px";
86 },
87 close: function ()
88 {
89 var contents = E("modal-content").childNodes;
90 for (var i = 0; i < contents.length; ++i)
91 {
92 if (contents[i].style)
93 contents[i].style.display = "none";
94 }
95 E("modal-background").style.display = "none";
96 E("modal").style.visibility = "hidden";
97 }
98 }
99
100 function populateLists()
101 {
102 ext.backgroundPage.sendMessage({
103 type: "subscriptions.get",
104 special: true
105 }, function(subscriptions)
106 {
107 for (var i = 0; i < subscriptions.length; i++)
108 {
109 ext.backgroundPage.sendMessage({
110 type: "filters.get",
111 subscriptionUrl: subscriptions[i].url
112 }, function(filters)
113 {
114 var whitelistArray = [];
115 for (var i = 0; i < filters.length; i++)
116 {
117 var match = filters[i].text.match(/^@@\|\|([^\/:]+)\^\$document$/);
118 if (match[1])
119 {
120 whitelistArray.push(match[1]);
121 }
122 else
123 {
124 // TODO: add `filters[i].text` to list of custom filters
125 }
126 }
127
128 if (whitelistArray.length > 0)
129 {
130 whitelistArray.sort();
131 for (var i = 0; i < whitelistArray.length; i++)
132 {
133 var domain = whitelistArray[i];
134 E("whitelisting-table").appendChild(createWhitelistElem(domain));
135 }
136 }
137 });
138 }
139 });
140
141 loadRecommendations(function(recommends)
142 {
143 ext.backgroundPage.sendMessage({
144 type: "subscriptions.get",
145 downloadable: true
146 }, function(subscriptions)
147 {
148 getAcceptableAdsURL(function(url)
149 {
150 acceptableAdsUrl = url;
151 for (var i = 0; i < subscriptions.length; i++)
152 {
153 if (subscriptions[i].url == acceptableAdsUrl)
154 {
155 E("allow-whitelist-cb").previousSibling.checked = !subscriptions[i ].disabled;
156 continue;
157 }
158
159 var subscription = recommends[subscriptions[i].url];
160 if (!subscription)
161 recommends[subscriptions[i].url] = subscriptions[i];
162 else
163 {
164 subscription.disabled = subscriptions[i].disabled;
165 if (subscription.type == "ads")
166 subscription.isAdded = true;
167 }
168 }
169 for (var key in recommends)
170 addOptionItem(recommends[key]);
171 });
172 });
173 });
174 }
175
176 function loadRecommendations(callback)
177 {
178 var recommendations = {};
179 var request = new XMLHttpRequest();
180 request.open("GET", "subscriptions.xml");
181 request.onload = function()
182 {
183 var list = document.getElementById("subscriptionSelector");
184 var elements = request.responseXML.documentElement.getElementsByTagName("s ubscription");
185 for (var i = 0; i < elements.length; i++)
186 {
187 var element = elements[i];
188 var subscription = {};
189 subscription.title = element.getAttribute("title");
190 subscription.url = element.getAttribute("url");
191 subscription.disabled = true;
192 var prefix = element.getAttribute("prefixes");
193 if (prefix)
194 {
195 subscription.prefixes = element.getAttribute("prefixes");
196 subscription.type = "ads";
197 subscription.display = ext.i18n.getMessage("options_language_"+subscri ption.prefixes.replace(/,/g, '_'));
198 }
199 else
200 subscription.display = element.getAttribute("specialization");
201
202 var popular = element.getAttribute("popular");
203 if (popular)
204 subscription.popular = element.getAttribute("popular");
205
206 recommendations[subscription.url] = subscription;
207 }
208 optionSubscriptions = recommendations;
209 callback(recommendations);
210 }
211 request.send();
212 }
213
214 function searchLanguage()
215 {
216 var searchVal = this.value;
217 var items = E("all-lang-table").childNodes;
218 for (var i = 0; i < items.length; ++i)
219 {
220 var item = items[i];
221 var language = item.getElementsByTagName("span")[1].innerHTML;
222 if (language.toLowerCase().indexOf(searchVal.toLowerCase()) > -1)
223 item.style.display = "block";
224 else
225 item.style.display = "none";
226 }
227 }
228
229 function addOptionItem(subscription)
230 {
231 var display = subscription.display ? subscription.display : subscription.tit le;
232 var getPossition = function(elements, subscription)
233 {
234 var localArray = [];
235 for (var i = 0; i < elements.length; i++)
236 {
237 var elem = elements[i];
238 localArray.push(elem);
239 }
240
241 localArray.push(subscription);
242 return localArray.sort(function(a, b) {
243 var aPopular = a.getElementsByClassName("popular").length > 0;
244 var bPopular = b.getElementsByClassName("popular").length > 0;
245 if(aPopular == bPopular)
246 {
247 var aValue = a.getElementsByClassName("display")[0].innerHTML.toLowerC ase();
248 var bValue = b.getElementsByClassName("display")[0].innerHTML.toLowerC ase();
249 if (aValue < bValue)
250 return -1;
251 if (aValue > bValue)
252 return 1;
253 return 0;
254 }
255 if (aPopular == "true")
256 return 1;
257 else
258 return -1;
259 }).indexOf(subscription);
260 };
261
262 var checkBoxClick = function()
263 {
264 toggleSubscription(subscription);
265 };
266
267 var appendToTable = function(table, elem)
268 {
269 var elements = table.getElementsByTagName("li");
270 if (elements.length == 0)
271 table.appendChild(elem);
272 else
273 {
274 var possition = getPossition(elements, elem);
275 table.insertBefore(elem, table.childNodes[possition]);
276 }
277 };
278
279 if (subscription.type && subscription.type == "ads")
280 {
281 if (!subscription.isAdded)
282 {
283 var listElem = generateListElement(subscription, subscription.display, " add");
284 listElem.dataset.url = subscription.url;
285 listElem._subscription = subscription;
286 listElem.getElementsByTagName("button")[0].addEventListener("click", fun ction()
287 {
288 addSubscription(this.dataset.url);
289 }.bind(listElem), false);
290 appendToTable(E("all-lang-table"), listElem);
291 }
292 else
293 {
294 var listElem = generateListElement(subscription, display, "checkbox");
295 listElem.dataset.url = subscription.url;
296 listElem._subscription = subscription;
297 listElem.getElementsByTagName("label")[0].addEventListener("click", chec kBoxClick, false);
298 appendToTable(E("blocking-languages-table"), listElem);
299 var listElem = generateListElement(subscription, display);
300 listElem.dataset.url = subscription.url;
301 listElem._subscription = subscription;
302 appendToTable(E("blocking-languages-modal-table"), listElem);
303 }
304 }
305 else
306 {
307 var listElem = generateListElement(subscription, display, "checkbox");
308 listElem.dataset.url = subscription.url;
309 listElem._subscription = subscription;
310 listElem.getElementsByTagName("label")[0].addEventListener("click", checkB oxClick, false);
311 appendToTable(E("further-list-table"), listElem);
312 }
313 }
314
315 function addLanguageSubscription(subscription)
316 {
317 var optionSubscription = getOptionSubscription(subscription.url);
318 var elems = getElementsByUrl(subscription.url);
319 for (var i = 0; i < elems.length; i++)
320 elems[i].parentNode.removeChild(elems[i]);
321 optionSubscription.isAdded = true;
322 optionSubscription.disabled = false;
323 addOptionItem(optionSubscription);
324 }
325
326 function createWhitelistElem(domain)
327 {
328 var listElem = generateListElement(null, domain, "delete");
329 listElem.dataset.domain = domain;
330 listElem.getElementsByTagName("button")[0].addEventListener("click", removeW hitelistBtnClick.bind(listElem), false);
331 return listElem;
332 }
333
334 function addFurtherList(subscription)
335 {
336 var optionSubscription = getOptionSubscription(subscription.url);
337 if (optionSubscription)
338 {
339 optionSubscription.disabled = false;
340 addOptionItem(optionSubscription);
341 }
342 else
343 {
344 optionSubscriptions[subscription.url] = subscription;
345 addOptionItem(subscription);
346 }
347 }
348
349 function updateSubscriptionState(subscription, state)
350 {
351 var elem = getElementsByUrl(subscription.url);
352 if (elem.length > 0)
353 {
354 for (var i = 0; i < elem.length; i++)
355 {
356 var checkbox = elem[i].getElementsByTagName("input")[0];
357 if (checkbox)
358 checkbox.checked = state;
359 }
360 }
361 else
362 {
363 if (subscription.url == acceptableAdsUrl)
364 E("allow-whitelist-cb").previousSibling.checked = state;
365 else
366 addFurtherList(subscription);
367 }
368 }
369
370 function getElementsByUrl(url)
371 {
372 return document.querySelectorAll("[data-url='"+url+"']");
373 }
374
375 function generateListElement(subscription, text, type)
376 {
377 var list = document.createElement("li");
378 if (type == "checkbox")
379 {
380 var input = document.createElement("input");
381 input.setAttribute("type", "checkbox");
382 if (subscription.disabled == false)
383 input.checked = true;
384 list.appendChild(input);
385 var label = document.createElement("label");
386 list.appendChild(label);
387 }
388 else if (type == "delete")
389 {
390 var button = document.createElement("button");
391 button.setAttribute("class", "delete");
392 list.appendChild(button);
393 }
394 else if (type == "add")
395 {
396 var button = document.createElement("button");
397 button.setAttribute("class", "addbtn");
398 var span = document.createElement("span");
399 span.innerHTML = "+" + ext.i18n.getMessage("options_btn_add");
400 button.appendChild(span);
401 list.appendChild(button);
402 }
403 var span = document.createElement("span");
404 span.setAttribute("class", "display");
405 span.innerHTML = text;
406 list.appendChild(span);
407
408 if (subscription && subscription.popular == "true")
409 {
410 var popular = document.createElement("span");
411 popular.setAttribute("class", "popular");
412 popular.innerHTML = "popular";
413 list.appendChild(popular);
414 }
415
416 return list;
417 }
418
419 function getOptionSubscription(url)
420 {
421 return optionSubscriptions[url];
422 }
423
424 function importListBtnCLick()
425 {
426 var url = E("blockingList-textbox").value;
427 addSubscription(url);
428 Modal.close();
429 }
430
431 function whitelistDomainBtnClick()
432 {
433 var domain = E("whitelisting-textbox").value;
434 if (domain)
435 addWhitelistedDomain(domain);
436 }
437
438 function removeWhitelistBtnClick()
439 {
440 removeWhitelistedDomain(this.dataset.domain);
441 }
442
443 function editOwnRulsBtnClick()
444 {
445
446 }
447
448 function showAddSubscriptionDialog(action, subscription)
449 {
450 E("blockingList-textbox").value = subscription.url;
451 Modal.open("further-blocking-modal");
452 }
453
454 function getAcceptableAdsURL(callback)
455 {
456 ext.backgroundPage.sendMessage({
457 type: "prefs.get",
458 key: "subscriptions_exceptionsurl"
459 }, function(value)
460 {
461 getAcceptableAdsURL = function(callback)
462 {
463 callback(value);
464 }
465 getAcceptableAdsURL(callback);
466 });
467 }
468
469 function toggleSubscription(subscription)
470 {
471 ext.backgroundPage.sendMessage({
472 type: "subscriptions.toggle",
473 url: subscription.url,
474 title: subscription.title,
475 homepage: subscription.homepage
476 });
477 }
478
479 function toggleAcceptableAds()
480 {
481 var acceptableCheckbox = this.previousSibling;
482 getAcceptableAdsURL(function(url)
483 {
484 var isChecked = acceptableCheckbox.checked;
485 var title = "Allow non-intrusive advertising";
486 if (isChecked)
487 removeSubscription(url);
488 else
489 addSubscription(url, title);
490 });
491 }
492
493 function addSubscription(url, title, homepage)
494 {
495 var message = {
496 type: "subscriptions.add",
497 url: url
498 };
499 if (title)
500 message.title = title;
501 if (homepage)
502 message.homepage = homepage;
503
504 ext.backgroundPage.sendMessage(message);
505 }
506
507 function removeSubscription(url)
508 {
509 ext.backgroundPage.sendMessage({
510 type: "subscriptions.remove",
511 url: url
512 });
513 }
514
515 function addWhitelistedDomain(domain)
516 {
517 ext.backgroundPage.sendMessage({
518 type: "filters.add",
519 text: "@@||" + domain.toLowerCase() + "^$document"
520 });
521 }
522
523 function removeWhitelistedDomain(domain)
524 {
525 ext.backgroundPage.sendMessage({
526 type: "filters.remove",
527 text: "@@||" + domain.toLowerCase() + "^$document"
528 });
529 }
530
531 function onFilterMessage(action, filter)
532 {
533 switch (action)
534 {
535 case "added":
536 var match = filter.text.match(/^@@\|\|([^\/:]+)\^\$document$/);
537 if (match[1])
538 {
539 var whitelistTbl = E("whitelisting-table");
540 var items = whitelistTbl.getElementsByClassName("display");
541 var domains = [];
542 for (var i = 0; i < items.length; i++)
543 {
544 domains.push(items[i].innerHTML);
545 }
546 var domain = match[1];
547 domains.push(domain);
548 domains.sort();
549
550 whitelistTbl.insertBefore(createWhitelistElem(domain), whitelistTbl.ch ildNodes[domains.indexOf(domain)]);
551 E("whitelisting-textbox").value = "";
552 }
553 else
554 {
555 // TODO: add `filters[i].text` to list of custom filters
556 }
557 break;
558 case "loaded":
559 populateLists();
560 break;
561 case "removed":
562 var match = filter.text.match(/^@@\|\|([^\/:]+)\^\$document$/);
563 if (match[1])
564 {
565 var elem = document.querySelector("[data-domain='"+match[1]+"']");
566 elem.parentNode.removeChild(elem);
567 }
568 break;
569 }
570 }
571
572 function onSubscriptionMessage(action, subscription)
573 {
574 switch (action)
575 {
576 case "added":
577 var optionSubscription = getOptionSubscription(subscription.url);
578 if (optionSubscription)
579 {
580 var isAdsType = optionSubscription.type && optionSubscription.type == "ads";
581 if (isAdsType && !optionSubscription.isAdded)
582 addLanguageSubscription(subscription);
583 else
584 updateSubscriptionState(subscription, true);
585 }
586 else if (subscription.url == acceptableAdsUrl)
587 updateSubscriptionState(subscription, true);
588 else
589 addFurtherList(subscription);
590 break;
591 case "disabled":
592 updateSubscriptionState(subscription, false);
593 break;
594 case "homepage":
595 // TODO: NYI
596 break;
597 case "removed":
598 updateSubscriptionState(subscription, false);
599 break;
600 case "title":
601 // TODO: NYI
602 break;
603 }
604 }
605
606 function updateShareLink()
607 {
608 ext.backgroundPage.sendMessage({
609 type: "filters.blocked",
610 url: "https://platform.twitter.com/widgets/",
611 requestType: "SCRIPT",
612 docDomain: "adblockplus.org",
613 thirdParty: true
614 }, function(blocked)
615 {
616 // TODO: modify "share" link accordingly
617 });
618 }
619
620 function getDocLink(link, callback)
621 {
622 ext.backgroundPage.sendMessage({
623 type: "app.get",
624 what: "doclink",
625 link: link
626 }, callback);
627 }
628
629 function E(id)
630 {
631 return document.getElementById(id);
632 }
633
634 ext.onMessage.addListener(function(message)
635 {
636 switch (message.type)
637 {
638 case "app.listen":
639 if (message.action == "addSubscription")
640 {
641 message.args.unshift(message.action);
642 showAddSubscriptionDialog.apply(null, message.args);
643 }
644 break;
645 case "filters.listen":
646 message.args.unshift(message.action);
647 onFilterMessage.apply(null, message.args);
648 break;
649 case "subscriptions.listen":
650 message.args.unshift(message.action);
651 onSubscriptionMessage.apply(null, message.args);
652 break;
653 }
654 });
655
656 ext.backgroundPage.sendMessage({
657 type: "app.listen",
658 filter: ["addSubscription"]
659 });
660 ext.backgroundPage.sendMessage({
661 type: "filters.listen",
662 filter: ["added", "loaded", "removed"]
663 });
664 ext.backgroundPage.sendMessage({
665 type: "subscriptions.listen",
666 filter: ["added", "disabled", "homepage", "removed", "title"]
667 });
668
669 window.addEventListener("DOMContentLoaded", onDOMLoaded, false);
670 })();
OLDNEW

Powered by Google App Engine
This is Rietveld