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

Powered by Google App Engine
This is Rietveld