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

Powered by Google App Engine
This is Rietveld