OLD | NEW |
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-2016 Eyeo GmbH | 3 * Copyright (C) 2006-2016 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 var backgroundPage = ext.backgroundPage.getWindow(); | 18 "use strict"; |
19 var require = backgroundPage.require; | |
20 | 19 |
21 with(require("filterClasses")) | 20 /** |
| 21 * Creates a wrapping function used to conveniently send a type of message. |
| 22 * |
| 23 * @param {Object} baseMessage The part of the message that's always sent |
| 24 * @param {..string} paramKeys Any message keys that have dynamic values. The |
| 25 * returned function will take the corresponding |
| 26 * values as arguments. |
| 27 * @return The generated messaging function, optionally taking any values as |
| 28 * specified by the paramKeys and finally an optional callback. |
| 29 * (Although the value arguments are optional their index must be |
| 30 * maintained. E.g. if you omit the first value you must omit the |
| 31 * second too.) |
| 32 */ |
| 33 function wrapper(baseMessage /* , [paramKeys] */) |
22 { | 34 { |
23 this.Filter = Filter; | 35 var paramKeys = []; |
24 this.WhitelistFilter = WhitelistFilter; | 36 for (var i = 1; i < arguments.length; i++) |
| 37 paramKeys.push(arguments[i]); |
| 38 |
| 39 return function(/* [paramValues], callback */) |
| 40 { |
| 41 var message = Object.create(null); |
| 42 for (var key in baseMessage) |
| 43 if (baseMessage.hasOwnProperty(key)) |
| 44 message[key] = baseMessage[key]; |
| 45 |
| 46 var paramValues = []; |
| 47 var callback; |
| 48 |
| 49 if (arguments.length > 0) |
| 50 { |
| 51 var lastArg = arguments[arguments.length - 1]; |
| 52 if (typeof lastArg == "function") |
| 53 callback = lastArg; |
| 54 |
| 55 for (var i = 0; i < arguments.length - (callback ? 1 : 0); i++) |
| 56 message[paramKeys[i]] = arguments[i]; |
| 57 } |
| 58 |
| 59 ext.backgroundPage.sendMessage(message, callback); |
| 60 }; |
25 } | 61 } |
26 with(require("subscriptionClasses")) | |
27 { | |
28 this.Subscription = Subscription; | |
29 this.SpecialSubscription = SpecialSubscription; | |
30 this.DownloadableSubscription = DownloadableSubscription; | |
31 } | |
32 with(require("filterValidation")) | |
33 { | |
34 this.parseFilter = parseFilter; | |
35 this.parseFilters = parseFilters; | |
36 } | |
37 var FilterStorage = require("filterStorage").FilterStorage; | |
38 var FilterNotifier = require("filterNotifier").FilterNotifier; | |
39 var Prefs = require("prefs").Prefs; | |
40 var Synchronizer = require("synchronizer").Synchronizer; | |
41 var Utils = require("utils").Utils; | |
42 var NotificationStorage = require("notification").Notification; | |
43 var info = require("info"); | |
44 | 62 |
45 // Loads options from localStorage and sets UI elements accordingly | 63 var getDocLink = wrapper({type: "app.get", what: "doclink"}, "link"); |
| 64 var getInfo = wrapper({type: "app.get"}, "what"); |
| 65 var getPref = wrapper({type: "prefs.get"}, "key"); |
| 66 var togglePref = wrapper({type: "prefs.toggle"}, "key"); |
| 67 var getSubscriptions = wrapper({type: "subscriptions.get"}, |
| 68 "downloadable", "special"); |
| 69 var removeSubscription = wrapper({type: "subscriptions.remove"}, "url"); |
| 70 var addSubscription = wrapper({type: "subscriptions.add"}, |
| 71 "url", "title", "homepage"); |
| 72 var toggleSubscription = wrapper({type: "subscriptions.toggle"}, |
| 73 "url", "keepInstalled"); |
| 74 var updateSubscription = wrapper({type: "subscriptions.update"}, "url"); |
| 75 var isSubscriptionDownloading = wrapper({type: "subscriptions.isDownloading"}, |
| 76 "url"); |
| 77 var importRawFilters = wrapper({type: "filters.importRaw"}, |
| 78 "text", "removeExisting"); |
| 79 var addFilter = wrapper({type: "filters.add"}, "text"); |
| 80 var getFilters = wrapper({type: "filters.get"}, "subscriptionUrl"); |
| 81 var removeFilter = wrapper({type: "filters.remove"}, "text"); |
| 82 |
| 83 var i18n = ext.i18n; |
| 84 var whitelistedDomainRegexp = /^@@\|\|([^\/:]+)\^\$document$/; |
| 85 var delayedSubscriptionSelection = null; |
| 86 |
| 87 // Loads options and sets UI elements accordingly |
46 function loadOptions() | 88 function loadOptions() |
47 { | 89 { |
48 // Set page title to i18n version of "Adblock Plus Options" | 90 // Set page title to i18n version of "Adblock Plus Options" |
49 document.title = i18n.getMessage("options"); | 91 document.title = i18n.getMessage("options"); |
50 | 92 |
51 // Set links | 93 // Set links |
52 $("#acceptableAdsLink").attr("href", Prefs.subscriptions_exceptionsurl); | 94 getPref("subscriptions_exceptionsurl", function(url) |
53 $("#acceptableAdsDocs").attr("href", Utils.getDocLink("acceptable_ads")); | 95 { |
54 setLinks("filter-must-follow-syntax", Utils.getDocLink("filterdoc")); | 96 $("#acceptableAdsLink").attr("href", url); |
55 setLinks("found-a-bug", Utils.getDocLink(info.application + "_support")); | 97 }); |
| 98 getDocLink("acceptable_ads", function(url) |
| 99 { |
| 100 $("#acceptableAdsDocs").attr("href", url); |
| 101 }); |
| 102 getDocLink("filterdoc", function(url) |
| 103 { |
| 104 setLinks("filter-must-follow-syntax", url); |
| 105 }); |
| 106 getInfo("application", function(application) |
| 107 { |
| 108 getInfo("platform", function(platform) |
| 109 { |
| 110 if (platform == "chromium" && application != "opera") |
| 111 application = "chrome"; |
| 112 |
| 113 getDocLink(application + "_support", function(url) |
| 114 { |
| 115 setLinks("found-a-bug", url); |
| 116 }); |
| 117 }); |
| 118 }); |
56 | 119 |
57 // Add event listeners | 120 // Add event listeners |
58 window.addEventListener("unload", unloadOptions, false); | |
59 $("#updateFilterLists").click(updateFilterLists); | 121 $("#updateFilterLists").click(updateFilterLists); |
60 $("#startSubscriptionSelection").click(startSubscriptionSelection); | 122 $("#startSubscriptionSelection").click(startSubscriptionSelection); |
61 $("#subscriptionSelector").change(updateSubscriptionSelection); | 123 $("#subscriptionSelector").change(updateSubscriptionSelection); |
62 $("#addSubscription").click(addSubscription); | 124 $("#addSubscription").click(addSubscriptionClicked); |
63 $("#acceptableAds").click(allowAcceptableAds); | 125 $("#acceptableAds").click(toggleAcceptableAds); |
64 $("#whitelistForm").submit(addWhitelistDomain); | 126 $("#whitelistForm").submit(addWhitelistDomain); |
65 $("#removeWhitelist").click(removeSelectedExcludedDomain); | 127 $("#removeWhitelist").click(removeSelectedExcludedDomain); |
66 $("#customFilterForm").submit(addTypedFilter); | 128 $("#customFilterForm").submit(addTypedFilter); |
67 $("#removeCustomFilter").click(removeSelectedFilters); | 129 $("#removeCustomFilter").click(removeSelectedFilters); |
68 $("#rawFiltersButton").click(toggleFiltersInRawFormat); | 130 $("#rawFiltersButton").click(toggleFiltersInRawFormat); |
69 $("#importRawFilters").click(importRawFiltersText); | 131 $("#importRawFilters").click(importRawFiltersText); |
70 | 132 |
71 FilterNotifier.on("load", reloadFilters); | |
72 FilterNotifier.on("subscription.title", onSubscriptionChange); | |
73 FilterNotifier.on("subscription.disabled", onSubscriptionChange); | |
74 FilterNotifier.on("subscription.homepage", onSubscriptionChange); | |
75 FilterNotifier.on("subscription.lastDownload", onSubscriptionChange); | |
76 FilterNotifier.on("subscription.downloadStatus", onSubscriptionChange); | |
77 FilterNotifier.on("subscription.added", onSubscriptionAdded); | |
78 FilterNotifier.on("subscription.removed", onSubscriptionRemoved); | |
79 FilterNotifier.on("filter.added", onFilterAdded); | |
80 FilterNotifier.on("filter.removed", onFilterRemoved); | |
81 | |
82 // Display jQuery UI elements | 133 // Display jQuery UI elements |
83 $("#tabs").tabs(); | 134 $("#tabs").tabs(); |
84 $("button").button(); | 135 $("button").button(); |
85 $(".refreshButton").button("option", "icons", {primary: "ui-icon-refresh"}); | 136 $(".refreshButton").button("option", "icons", {primary: "ui-icon-refresh"}); |
86 $(".addButton").button("option", "icons", {primary: "ui-icon-plus"}); | 137 $(".addButton").button("option", "icons", {primary: "ui-icon-plus"}); |
87 $(".removeButton").button("option", "icons", {primary: "ui-icon-minus"}); | 138 $(".removeButton").button("option", "icons", {primary: "ui-icon-minus"}); |
88 | 139 |
89 // Popuplate option checkboxes | 140 // Popuplate option checkboxes |
90 initCheckbox("shouldShowBlockElementMenu"); | 141 initCheckbox("shouldShowBlockElementMenu"); |
91 initCheckbox("show_devtools_panel"); | 142 initCheckbox("show_devtools_panel"); |
92 initCheckbox("shouldShowNotifications", { | 143 initCheckbox("shouldShowNotifications", { |
93 get: function() | 144 key: "notifications_ignoredcategories", |
| 145 get: function(ignoredcategories) |
94 { | 146 { |
95 return Prefs.notifications_ignoredcategories.indexOf("*") == -1; | 147 return ignoredcategories.indexOf("*") == -1; |
96 }, | |
97 toggle: function() | |
98 { | |
99 NotificationStorage.toggleIgnoreCategory("*"); | |
100 return this.get(); | |
101 } | 148 } |
102 }); | 149 }); |
103 | 150 |
104 if (info.platform != "chromium") | 151 getInfo("features", function(features) |
105 document.getElementById("showDevtoolsPanelContainer").hidden = true; | 152 { |
106 if (!Prefs.notifications_showui) | 153 if (!features.devToolsPanel) |
107 document.getElementById("shouldShowNotificationsContainer").hidden = true; | 154 document.getElementById("showDevtoolsPanelContainer").hidden = true; |
| 155 }); |
| 156 getPref("notifications_showui", function(notifications_showui) |
| 157 { |
| 158 if (!notifications_showui) |
| 159 document.getElementById("shouldShowNotificationsContainer").hidden = true; |
| 160 }); |
108 | 161 |
109 ext.onMessage.addListener(onMessage); | 162 // Register listeners in the background message responder |
110 ext.backgroundPage.sendMessage({ | 163 ext.backgroundPage.sendMessage({ |
111 type: "app.listen", | 164 type: "app.listen", |
112 filter: ["addSubscription"] | 165 filter: ["addSubscription", "switchToOptionsSection"] |
| 166 }); |
| 167 ext.backgroundPage.sendMessage( |
| 168 { |
| 169 type: "filters.listen", |
| 170 filter: ["added", "loaded", "removed"] |
| 171 }); |
| 172 ext.backgroundPage.sendMessage( |
| 173 { |
| 174 type: "prefs.listen", |
| 175 filter: ["notifications_ignoredcategories", "notifications_showui", |
| 176 "safari_contentblocker", "show_devtools_panel", |
| 177 "shouldShowBlockElementMenu"] |
| 178 }); |
| 179 ext.backgroundPage.sendMessage( |
| 180 { |
| 181 type: "subscriptions.listen", |
| 182 filter: ["added", "disabled", "homepage", "lastDownload", "removed", |
| 183 "title"] |
113 }); | 184 }); |
114 | 185 |
115 // Load recommended subscriptions | 186 // Load recommended subscriptions |
116 loadRecommendations(); | 187 loadRecommendations(); |
117 | 188 |
118 // Show user's filters | 189 // Show user's filters |
119 reloadFilters(); | 190 reloadFilters(); |
120 } | 191 } |
121 $(loadOptions); | 192 $(loadOptions); |
122 | 193 |
123 function onMessage(msg) | |
124 { | |
125 if (msg.type == "app.listen") | |
126 { | |
127 if (msg.action == "addSubscription") | |
128 { | |
129 var subscription = msg.args[0]; | |
130 startSubscriptionSelection(subscription.title, subscription.url); | |
131 } | |
132 } | |
133 else if (msg.type == "focus-section") | |
134 { | |
135 var tabs = document.getElementsByClassName("ui-tabs-panel"); | |
136 for (var i = 0; i < tabs.length; i++) | |
137 { | |
138 var found = tabs[i].querySelector("[data-section='" + msg.section + "']"); | |
139 if (!found) | |
140 continue; | |
141 | |
142 var previous = document.getElementsByClassName("focused"); | |
143 if (previous.length > 0) | |
144 previous[0].classList.remove("focused"); | |
145 | |
146 var tab = $("[href='#" + tabs[i].id + "']"); | |
147 $("#tabs").tabs("select", tab.parent().index()); | |
148 found.classList.add("focused"); | |
149 } | |
150 } | |
151 }; | |
152 | |
153 // Reloads the displayed subscriptions and filters | 194 // Reloads the displayed subscriptions and filters |
154 function reloadFilters() | 195 function reloadFilters() |
155 { | 196 { |
156 // Load user filter URLs | 197 // Load user filter URLs |
157 var container = document.getElementById("filterLists"); | 198 var container = document.getElementById("filterLists"); |
158 while (container.lastChild) | 199 while (container.lastChild) |
159 container.removeChild(container.lastChild); | 200 container.removeChild(container.lastChild); |
160 | 201 |
161 var hasAcceptable = false; | 202 getPref("subscriptions_exceptionsurl", function(acceptableAdsUrl) |
162 for (var i = 0; i < FilterStorage.subscriptions.length; i++) | |
163 { | 203 { |
164 var subscription = FilterStorage.subscriptions[i]; | 204 getSubscriptions(true, false, function(subscriptions) |
165 if (subscription instanceof SpecialSubscription) | |
166 continue; | |
167 | |
168 if (subscription.url == Prefs.subscriptions_exceptionsurl) | |
169 { | 205 { |
170 hasAcceptable = true; | 206 for (var i = 0; i < subscriptions.length; i++) |
171 continue; | 207 { |
172 } | 208 var subscription = subscriptions[i]; |
173 | 209 if (subscription.url == acceptableAdsUrl) |
174 addSubscriptionEntry(subscription); | 210 $("#acceptableAds").prop("checked", !subscription.disabled); |
175 } | 211 else |
176 | 212 addSubscriptionEntry(subscription); |
177 $("#acceptableAds").prop("checked", hasAcceptable); | 213 } |
| 214 }); |
| 215 }); |
178 | 216 |
179 // User-entered filters | 217 // User-entered filters |
180 var userFilters = backgroundPage.getUserFilters(); | 218 getSubscriptions(false, true, function(subscriptions) |
181 populateList("userFiltersBox", userFilters.filters); | 219 { |
182 populateList("excludedDomainsBox", userFilters.exceptions); | 220 clearListBox("userFiltersBox"); |
183 } | 221 clearListBox("excludedDomainsBox"); |
184 | 222 |
185 // Cleans up when the options window is closed | 223 for (var i = 0; i < subscriptions.length; i++) |
186 function unloadOptions() | 224 getFilters(subscriptions[i].url, function(filters) |
187 { | 225 { |
188 FilterNotifier.off("load", reloadFilters); | 226 for (var j = 0; j < filters.length; j++) |
189 FilterNotifier.off("subscription.title", onSubscriptionChange); | 227 { |
190 FilterNotifier.off("subscription.disabled", onSubscriptionChange); | 228 var filter = filters[j].text; |
191 FilterNotifier.off("subscription.homepage", onSubscriptionChange); | 229 if (whitelistedDomainRegexp.test(filter)) |
192 FilterNotifier.off("subscription.lastDownload", onSubscriptionChange); | 230 appendToListBox("excludedDomainsBox", RegExp.$1); |
193 FilterNotifier.off("subscription.downloadStatus", onSubscriptionChange); | 231 else |
194 FilterNotifier.off("subscription.added", onSubscriptionAdded); | 232 appendToListBox("userFiltersBox", filter); |
195 FilterNotifier.off("subscription.removed", onSubscriptionRemoved); | 233 } |
196 FilterNotifier.off("filter.added", onFilterAdded); | 234 }); |
197 FilterNotifier.off("filter.removed", onFilterRemoved); | 235 }); |
198 } | 236 } |
199 | 237 |
200 function initCheckbox(id, descriptor) | 238 function initCheckbox(id, descriptor) |
201 { | 239 { |
202 var checkbox = document.getElementById(id); | 240 var checkbox = document.getElementById(id); |
203 if (descriptor && descriptor.get) | 241 var key = descriptor && descriptor.key || id; |
204 checkbox.checked = descriptor.get(); | 242 getPref(key, function(value) |
205 else | 243 { |
206 checkbox.checked = Prefs[id]; | 244 if (descriptor && descriptor.get) |
| 245 checkbox.checked = descriptor.get(value); |
| 246 else |
| 247 checkbox.checked = value; |
| 248 }); |
207 | 249 |
208 checkbox.addEventListener("click", function() | 250 checkbox.addEventListener("click", function() |
209 { | 251 { |
210 if (descriptor && descriptor.toggle) | 252 if (descriptor && descriptor.toggle) |
211 checkbox.checked = descriptor.toggle(); | 253 checkbox.checked = descriptor.toggle(); |
212 | 254 togglePref(key); |
213 Prefs[id] = checkbox.checked; | |
214 }, false); | 255 }, false); |
215 } | 256 } |
216 | 257 |
217 var delayedSubscriptionSelection = null; | |
218 | |
219 function loadRecommendations() | 258 function loadRecommendations() |
220 { | 259 { |
221 fetch("subscriptions.xml") | 260 fetch("subscriptions.xml") |
222 .then(function(response) | 261 .then(function(response) |
223 { | 262 { |
224 return response.text(); | 263 return response.text(); |
225 }) | 264 }) |
226 .then(function(text) | 265 .then(function(text) |
227 { | 266 { |
228 var selectedIndex = 0; | 267 var selectedIndex = 0; |
229 var selectedPrefix = null; | 268 var selectedPrefix = null; |
230 var matchCount = 0; | 269 var matchCount = 0; |
231 | 270 |
232 var list = document.getElementById("subscriptionSelector"); | 271 var list = document.getElementById("subscriptionSelector"); |
233 var doc = new DOMParser().parseFromString(text, "application/xml"); | 272 var doc = new DOMParser().parseFromString(text, "application/xml"); |
234 var elements = doc.documentElement.getElementsByTagName("subscription"); | 273 var elements = doc.documentElement.getElementsByTagName("subscription"); |
235 | 274 |
236 for (var i = 0; i < elements.length; i++) | 275 for (var i = 0; i < elements.length; i++) |
237 { | 276 { |
238 var element = elements[i]; | 277 var element = elements[i]; |
239 var option = new Option(); | 278 var option = new Option(); |
240 option.text = element.getAttribute("title") + " (" + | 279 option.text = element.getAttribute("title") + " (" + |
241 element.getAttribute("specialization") + ")"; | 280 element.getAttribute("specialization") + ")"; |
242 option._data = { | 281 option._data = { |
243 title: element.getAttribute("title"), | 282 title: element.getAttribute("title"), |
244 url: element.getAttribute("url"), | 283 url: element.getAttribute("url"), |
245 homepage: element.getAttribute("homepage") | 284 homepage: element.getAttribute("homepage") |
246 }; | 285 }; |
247 | 286 |
248 var prefixes = element.getAttribute("prefixes"); | 287 var prefix = element.getAttribute("prefixes"); |
249 var prefix = Utils.checkLocalePrefixMatch(prefixes); | |
250 if (prefix) | 288 if (prefix) |
251 { | 289 { |
| 290 prefix = prefix.replace(/\W/g, "_"); |
252 option.style.fontWeight = "bold"; | 291 option.style.fontWeight = "bold"; |
253 option.style.backgroundColor = "#E0FFE0"; | 292 option.style.backgroundColor = "#E0FFE0"; |
254 option.style.color = "#000000"; | 293 option.style.color = "#000000"; |
255 if (!selectedPrefix || selectedPrefix.length < prefix.length) | 294 if (!selectedPrefix || selectedPrefix.length < prefix.length) |
256 { | 295 { |
257 selectedIndex = i; | 296 selectedIndex = i; |
258 selectedPrefix = prefix; | 297 selectedPrefix = prefix; |
259 matchCount = 1; | 298 matchCount = 1; |
260 } | 299 } |
261 else if (selectedPrefix && selectedPrefix.length == prefix.length) | 300 else if (selectedPrefix && selectedPrefix.length == prefix.length) |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 var data = list.options[list.selectedIndex]._data; | 357 var data = list.options[list.selectedIndex]._data; |
319 if (data) | 358 if (data) |
320 $("#customSubscriptionContainer").hide(); | 359 $("#customSubscriptionContainer").hide(); |
321 else | 360 else |
322 { | 361 { |
323 $("#customSubscriptionContainer").show(); | 362 $("#customSubscriptionContainer").show(); |
324 $("#customSubscriptionTitle").focus(); | 363 $("#customSubscriptionTitle").focus(); |
325 } | 364 } |
326 } | 365 } |
327 | 366 |
328 function addSubscription() | 367 function addSubscriptionClicked() |
329 { | 368 { |
330 var list = document.getElementById("subscriptionSelector"); | 369 var list = document.getElementById("subscriptionSelector"); |
331 var data = list.options[list.selectedIndex]._data; | 370 var data = list.options[list.selectedIndex]._data; |
332 if (data) | 371 if (data) |
333 doAddSubscription(data.url, data.title, data.homepage); | 372 addSubscription(data.url, data.title, data.homepage); |
334 else | 373 else |
335 { | 374 { |
336 var url = document.getElementById("customSubscriptionLocation").value.trim()
; | 375 var url = document.getElementById("customSubscriptionLocation").value.trim()
; |
337 if (!/^https?:/i.test(url)) | 376 if (!/^https?:/i.test(url)) |
338 { | 377 { |
339 alert(i18n.getMessage("global_subscription_invalid_location")); | 378 alert(i18n.getMessage("global_subscription_invalid_location")); |
340 $("#customSubscriptionLocation").focus(); | 379 $("#customSubscriptionLocation").focus(); |
341 return; | 380 return; |
342 } | 381 } |
343 | 382 |
344 var title = document.getElementById("customSubscriptionTitle").value.trim(); | 383 var title = document.getElementById("customSubscriptionTitle").value.trim(); |
345 if (!title) | 384 if (!title) |
346 title = url; | 385 title = url; |
347 | 386 |
348 doAddSubscription(url, title, null); | 387 addSubscription(url, title, null); |
349 } | 388 } |
350 | 389 |
351 $("#addSubscriptionContainer").hide(); | 390 $("#addSubscriptionContainer").hide(); |
352 $("#customSubscriptionContainer").hide(); | 391 $("#customSubscriptionContainer").hide(); |
353 $("#addSubscriptionButton").show(); | 392 $("#addSubscriptionButton").show(); |
354 } | 393 } |
355 | 394 |
356 function doAddSubscription(url, title, homepage) | 395 function toggleAcceptableAds() |
357 { | 396 { |
358 if (url in FilterStorage.knownSubscriptions) | 397 getPref("subscriptions_exceptionsurl", function(url) |
359 return; | |
360 | |
361 var subscription = Subscription.fromURL(url); | |
362 if (!subscription) | |
363 return; | |
364 | |
365 subscription.title = title; | |
366 if (homepage) | |
367 subscription.homepage = homepage; | |
368 FilterStorage.addSubscription(subscription); | |
369 | |
370 if (subscription instanceof DownloadableSubscription && !subscription.lastDown
load) | |
371 Synchronizer.execute(subscription); | |
372 } | |
373 | |
374 function allowAcceptableAds(event) | |
375 { | |
376 var subscription = Subscription.fromURL(Prefs.subscriptions_exceptionsurl); | |
377 if (!subscription) | |
378 return; | |
379 | |
380 subscription.disabled = false; | |
381 subscription.title = "Allow non-intrusive advertising"; | |
382 if ($("#acceptableAds").prop("checked")) | |
383 { | 398 { |
384 FilterStorage.addSubscription(subscription); | 399 toggleSubscription(url, true); |
385 if (subscription instanceof DownloadableSubscription && !subscription.lastDo
wnload) | 400 }); |
386 Synchronizer.execute(subscription); | |
387 } | |
388 else | |
389 FilterStorage.removeSubscription(subscription); | |
390 } | 401 } |
391 | 402 |
392 function findSubscriptionElement(subscription) | 403 function findSubscriptionElement(subscription) |
393 { | 404 { |
394 var children = document.getElementById("filterLists").childNodes; | 405 var children = document.getElementById("filterLists").childNodes; |
395 for (var i = 0; i < children.length; i++) | 406 for (var i = 0; i < children.length; i++) |
396 if (children[i]._subscription == subscription) | 407 if (children[i]._subscription.url == subscription.url) |
397 return children[i]; | 408 return children[i]; |
398 return null; | 409 return null; |
399 } | 410 } |
400 | 411 |
401 function updateSubscriptionInfo(element) | 412 function updateSubscriptionInfo(element, subscription) |
402 { | 413 { |
403 var subscription = element._subscription; | 414 if (subscription) |
| 415 element._subscription = subscription; |
| 416 else |
| 417 subscription = element._subscription; |
404 | 418 |
405 var title = element.getElementsByClassName("subscriptionTitle")[0]; | 419 var title = element.getElementsByClassName("subscriptionTitle")[0]; |
406 title.textContent = subscription.title; | 420 title.textContent = subscription.title; |
407 title.setAttribute("title", subscription.url); | 421 title.setAttribute("title", subscription.url); |
408 if (subscription.homepage) | 422 if (subscription.homepage) |
409 title.href = subscription.homepage; | 423 title.href = subscription.homepage; |
410 else | 424 else |
411 title.href = subscription.url; | 425 title.href = subscription.url; |
412 | 426 |
413 var enabled = element.getElementsByClassName("subscriptionEnabled")[0]; | 427 var enabled = element.getElementsByClassName("subscriptionEnabled")[0]; |
414 enabled.checked = !subscription.disabled; | 428 enabled.checked = !subscription.disabled; |
415 | 429 |
416 var lastUpdate = element.getElementsByClassName("subscriptionUpdate")[0]; | 430 var lastUpdate = element.getElementsByClassName("subscriptionUpdate")[0]; |
417 lastUpdate.classList.remove("error"); | 431 lastUpdate.classList.remove("error"); |
418 if (Synchronizer.isExecuting(subscription.url)) | 432 |
419 lastUpdate.textContent = i18n.getMessage("filters_subscription_lastDownload_
inProgress"); | 433 if (subscription.downloadStatus && |
420 else if (subscription.downloadStatus && subscription.downloadStatus != "synchr
onize_ok") | 434 subscription.downloadStatus != "synchronize_ok") |
421 { | 435 { |
422 var map = | 436 var map = |
423 { | 437 { |
424 "synchronize_invalid_url": "filters_subscription_lastDownload_invalidURL", | 438 "synchronize_invalid_url": "filters_subscription_lastDownload_invalidURL"
, |
425 "synchronize_connection_error": "filters_subscription_lastDownload_connect
ionError", | 439 "synchronize_connection_error": "filters_subscription_lastDownload_connec
tionError", |
426 "synchronize_invalid_data": "filters_subscription_lastDownload_invalidData
", | 440 "synchronize_invalid_data": "filters_subscription_lastDownload_invalidDat
a", |
427 "synchronize_checksum_mismatch": "filters_subscription_lastDownload_checks
umMismatch" | 441 "synchronize_checksum_mismatch": "filters_subscription_lastDownload_check
sumMismatch" |
428 }; | 442 }; |
429 if (subscription.downloadStatus in map) | 443 if (subscription.downloadStatus in map) |
430 lastUpdate.textContent = i18n.getMessage(map[subscription.downloadStatus])
; | 444 lastUpdate.textContent = i18n.getMessage(map[subscription.downloadStatus]
); |
431 else | 445 else |
432 lastUpdate.textContent = subscription.downloadStatus; | 446 lastUpdate.textContent = subscription.downloadStatus; |
433 lastUpdate.classList.add("error"); | 447 lastUpdate.classList.add("error"); |
434 } | 448 } |
435 else if (subscription.lastDownload > 0) | 449 else if (subscription.lastDownload > 0) |
436 { | 450 { |
437 var timeDate = i18n_timeDateStrings(subscription.lastDownload * 1000); | 451 var timeDate = i18n_timeDateStrings(subscription.lastDownload * 1000); |
438 var messageID = (timeDate[1] ? "last_updated_at" : "last_updated_at_today"); | 452 var messageID = (timeDate[1] ? "last_updated_at" : "last_updated_at_today"); |
439 lastUpdate.textContent = i18n.getMessage(messageID, timeDate); | 453 lastUpdate.textContent = i18n.getMessage(messageID, timeDate); |
440 } | 454 } |
441 } | 455 } |
442 | 456 |
443 function onSubscriptionChange(subscription) | 457 function onSubscriptionMessage(action, subscription) |
444 { | 458 { |
445 var element = findSubscriptionElement(subscription); | 459 switch (action) |
446 if (element) | |
447 updateSubscriptionInfo(element); | |
448 } | |
449 | |
450 function onSubscriptionAdded(subscription) | |
451 { | |
452 if (subscription instanceof SpecialSubscription) | |
453 { | 460 { |
454 for (var i = 0; i < subscription.filters.length; i++) | 461 case "title": |
455 onFilterAdded(subscription.filters[i]); | 462 case "disabled": |
456 } | 463 case "homepage": |
457 else if (subscription.url == Prefs.subscriptions_exceptionsurl) | 464 case "lastDownload": |
458 $("#acceptableAds").prop("checked", true); | 465 case "downloadStatus": |
459 else if (!findSubscriptionElement(subscription)) | 466 var element = findSubscriptionElement(subscription); |
460 addSubscriptionEntry(subscription); | 467 if (element) |
461 } | 468 updateSubscriptionInfo(element, subscription); |
462 | 469 break; |
463 function onSubscriptionRemoved(subscription) | 470 case "added": |
464 { | 471 getPref("subscriptions_exceptionsurl", function(acceptableAdsUrl) |
465 if (subscription instanceof SpecialSubscription) | 472 { |
466 { | 473 if (subscription.url == acceptableAdsUrl) |
467 for (var i = 0; i < subscription.filters.length; i++) | 474 $("#acceptableAds").prop("checked", true); |
468 onFilterRemoved(subscription.filters[i]); | 475 else if (!findSubscriptionElement(subscription)) |
469 } | 476 addSubscriptionEntry(subscription); |
470 else if (subscription.url == Prefs.subscriptions_exceptionsurl) | 477 }); |
471 $("#acceptableAds").prop("checked", false); | 478 break; |
472 else | 479 case "removed": |
473 { | 480 getPref("subscriptions_exceptionsurl", function(acceptableAdsUrl) |
474 var element = findSubscriptionElement(subscription); | 481 { |
475 if (element) | 482 if (subscription.url == acceptableAdsUrl) |
476 element.parentNode.removeChild(element); | 483 { |
| 484 $("#acceptableAds").prop("checked", false); |
| 485 } |
| 486 else |
| 487 { |
| 488 var element = findSubscriptionElement(subscription); |
| 489 if (element) |
| 490 element.parentNode.removeChild(element); |
| 491 } |
| 492 }); |
| 493 break; |
477 } | 494 } |
478 } | 495 } |
479 | 496 |
480 function onFilterAdded(filter) | 497 function onPrefMessage(key, value) |
481 { | 498 { |
482 if (filter instanceof WhitelistFilter && | 499 switch (key) |
483 /^@@\|\|([^\/:]+)\^\$document$/.test(filter.text)) | 500 { |
484 appendToListBox("excludedDomainsBox", RegExp.$1); | 501 case "notifications_showui": |
485 else | 502 document.getElementById("shouldShowNotificationsContainer").hidden = !valu
e; |
486 appendToListBox("userFiltersBox", filter.text); | 503 return; |
| 504 case "notifications_ignoredcategories": |
| 505 key = "shouldShowNotifications"; |
| 506 value = value.indexOf("*") == -1; |
| 507 break; |
| 508 } |
| 509 |
| 510 var checkbox = document.getElementById(key); |
| 511 if (checkbox) |
| 512 checkbox.checked = value; |
487 } | 513 } |
488 | 514 |
489 function onFilterRemoved(filter) | 515 function onFilterMessage(action, filter) |
490 { | 516 { |
491 if (filter instanceof WhitelistFilter && | 517 switch (action) |
492 /^@@\|\|([^\/:]+)\^\$document$/.test(filter.text)) | 518 { |
493 removeFromListBox("excludedDomainsBox", RegExp.$1); | 519 case "loaded": |
494 else | 520 reloadFilters(); |
495 removeFromListBox("userFiltersBox", filter.text); | 521 break; |
| 522 case "added": |
| 523 if (whitelistedDomainRegexp.test(filter.text)) |
| 524 appendToListBox("excludedDomainsBox", RegExp.$1); |
| 525 else |
| 526 appendToListBox("userFiltersBox", filter.text); |
| 527 break; |
| 528 case "removed": |
| 529 if (whitelistedDomainRegexp.test(filter.text)) |
| 530 removeFromListBox("excludedDomainsBox", RegExp.$1); |
| 531 else |
| 532 removeFromListBox("userFiltersBox", filter.text); |
| 533 break; |
| 534 } |
496 } | 535 } |
497 | 536 |
498 // Populates a list box with a number of entries | 537 function clearListBox(id) |
499 function populateList(id, entries) | |
500 { | 538 { |
501 var list = document.getElementById(id); | 539 var list = document.getElementById(id); |
502 while (list.lastChild) | 540 while (list.lastChild) |
503 list.removeChild(list.lastChild); | 541 list.removeChild(list.lastChild); |
504 | |
505 entries.sort(); | |
506 for (var i = 0; i < entries.length; i++) | |
507 { | |
508 var option = new Option(); | |
509 option.text = entries[i]; | |
510 option.value = entries[i]; | |
511 list.appendChild(option); | |
512 } | |
513 } | 542 } |
514 | 543 |
515 // Add a filter string to the list box. | 544 // Add a filter string to the list box. |
516 function appendToListBox(boxId, text) | 545 function appendToListBox(boxId, text) |
517 { | 546 { |
518 var elt = new Option(); /* Note: document.createElement("option") is unreliab
le in Opera */ | 547 // Note: document.createElement("option") is unreliable in Opera |
| 548 var elt = new Option(); |
519 elt.text = text; | 549 elt.text = text; |
520 elt.value = text; | 550 elt.value = text; |
521 document.getElementById(boxId).appendChild(elt); | 551 document.getElementById(boxId).appendChild(elt); |
522 } | 552 } |
523 | 553 |
524 // Remove a filter string from a list box. | 554 // Remove a filter string from a list box. |
525 function removeFromListBox(boxId, text) | 555 function removeFromListBox(boxId, text) |
526 { | 556 { |
527 var list = document.getElementById(boxId); | 557 var list = document.getElementById(boxId); |
528 for (var i = 0; i < list.length; i++) | 558 for (var i = 0; i < list.length; i++) |
529 if (list.options[i].value == text) | 559 if (list.options[i].value == text) |
530 list.remove(i--); | 560 list.remove(i--); |
531 } | 561 } |
532 | 562 |
533 function addWhitelistDomain(event) | 563 function addWhitelistDomain(event) |
534 { | 564 { |
535 event.preventDefault(); | 565 event.preventDefault(); |
536 | 566 |
537 var domain = document.getElementById("newWhitelistDomain").value.replace(/\s/g
, ""); | 567 var domain = document.getElementById("newWhitelistDomain").value.replace(/\s/g
, ""); |
538 document.getElementById("newWhitelistDomain").value = ""; | 568 document.getElementById("newWhitelistDomain").value = ""; |
539 if (!domain) | 569 if (!domain) |
540 return; | 570 return; |
541 | 571 |
542 var filterText = "@@||" + domain + "^$document"; | 572 var filterText = "@@||" + domain + "^$document"; |
543 FilterStorage.addFilter(Filter.fromText(filterText)); | 573 addFilter(filterText); |
544 } | 574 } |
545 | 575 |
546 // Adds filter text that user typed to the selection box | 576 // Adds filter text that user typed to the selection box |
547 function addTypedFilter(event) | 577 function addTypedFilter(event) |
548 { | 578 { |
549 event.preventDefault(); | 579 event.preventDefault(); |
550 | 580 |
551 var element = document.getElementById("newFilter"); | 581 var element = document.getElementById("newFilter"); |
552 var result = parseFilter(element.value); | 582 addFilter(element.value, function(errors) |
553 | |
554 if (result.error) | |
555 { | 583 { |
556 alert(result.error); | 584 if (errors.length > 0) |
557 return; | 585 alert(errors.join("\n")); |
558 } | 586 else |
559 | 587 element.value = ""; |
560 if (result.filter) | 588 }); |
561 FilterStorage.addFilter(result.filter); | |
562 | |
563 element.value = ""; | |
564 } | 589 } |
565 | 590 |
566 // Removes currently selected whitelisted domains | 591 // Removes currently selected whitelisted domains |
567 function removeSelectedExcludedDomain(event) | 592 function removeSelectedExcludedDomain(event) |
568 { | 593 { |
569 event.preventDefault(); | 594 event.preventDefault(); |
570 var excludedDomainsBox = document.getElementById("excludedDomainsBox"); | 595 var excludedDomainsBox = document.getElementById("excludedDomainsBox"); |
571 var remove = []; | 596 var remove = []; |
572 for (var i = 0; i < excludedDomainsBox.length; i++) | 597 for (var i = 0; i < excludedDomainsBox.length; i++) |
573 if (excludedDomainsBox.options[i].selected) | 598 if (excludedDomainsBox.options[i].selected) |
574 remove.push(excludedDomainsBox.options[i].value); | 599 remove.push(excludedDomainsBox.options[i].value); |
575 if (!remove.length) | 600 if (!remove.length) |
576 return; | 601 return; |
577 | 602 |
578 for (var i = 0; i < remove.length; i++) | 603 for (var i = 0; i < remove.length; i++) |
579 FilterStorage.removeFilter(Filter.fromText("@@||" + remove[i] + "^$document"
)); | 604 removeFilter("@@||" + remove[i] + "^$document"); |
580 } | 605 } |
581 | 606 |
582 // Removes all currently selected filters | 607 // Removes all currently selected filters |
583 function removeSelectedFilters(event) | 608 function removeSelectedFilters(event) |
584 { | 609 { |
585 event.preventDefault(); | 610 event.preventDefault(); |
586 var userFiltersBox = document.getElementById("userFiltersBox"); | 611 var userFiltersBox = document.getElementById("userFiltersBox"); |
587 var remove = []; | 612 var remove = []; |
588 for (var i = 0; i < userFiltersBox.length; i++) | 613 for (var i = 0; i < userFiltersBox.length; i++) |
589 if (userFiltersBox.options[i].selected) | 614 if (userFiltersBox.options[i].selected) |
590 remove.push(userFiltersBox.options[i].value); | 615 remove.push(userFiltersBox.options[i].value); |
591 if (!remove.length) | 616 if (!remove.length) |
592 return; | 617 return; |
593 | 618 |
594 for (var i = 0; i < remove.length; i++) | 619 for (var i = 0; i < remove.length; i++) |
595 FilterStorage.removeFilter(Filter.fromText(remove[i])); | 620 removeFilter(remove[i]); |
596 } | 621 } |
597 | 622 |
598 // Shows raw filters box and fills it with the current user filters | 623 // Shows raw filters box and fills it with the current user filters |
599 function toggleFiltersInRawFormat(event) | 624 function toggleFiltersInRawFormat(event) |
600 { | 625 { |
601 event.preventDefault(); | 626 event.preventDefault(); |
602 | 627 |
603 $("#rawFilters").toggle(); | 628 $("#rawFilters").toggle(); |
604 if ($("#rawFilters").is(":visible")) | 629 if ($("#rawFilters").is(":visible")) |
605 { | 630 { |
606 var userFiltersBox = document.getElementById("userFiltersBox"); | 631 var userFiltersBox = document.getElementById("userFiltersBox"); |
607 var text = ""; | 632 var text = ""; |
608 for (var i = 0; i < userFiltersBox.length; i++) | 633 for (var i = 0; i < userFiltersBox.length; i++) |
609 text += userFiltersBox.options[i].value + "\n"; | 634 text += userFiltersBox.options[i].value + "\n"; |
610 document.getElementById("rawFiltersText").value = text; | 635 document.getElementById("rawFiltersText").value = text; |
611 } | 636 } |
612 } | 637 } |
613 | 638 |
614 // Imports filters in the raw text box | 639 // Imports filters in the raw text box |
615 function importRawFiltersText() | 640 function importRawFiltersText() |
616 { | 641 { |
617 var text = document.getElementById("rawFiltersText").value; | 642 var text = document.getElementById("rawFiltersText").value; |
618 var result = parseFilters(text); | |
619 | 643 |
620 var errors = result.errors.filter(function(e) | 644 importRawFilters(text, true, function(errors) |
621 { | 645 { |
622 return e.type != "unexpected-filter-list-header"; | 646 if (errors.length > 0) |
| 647 alert(errors.join("\n")); |
| 648 else |
| 649 $("#rawFilters").hide(); |
623 }); | 650 }); |
624 | |
625 if (errors.length > 0) | |
626 { | |
627 alert(errors.join("\n")); | |
628 return; | |
629 } | |
630 | |
631 var seenFilter = Object.create(null); | |
632 for (var i = 0; i < result.filters.length; i++) | |
633 { | |
634 var filter = result.filters[i]; | |
635 FilterStorage.addFilter(filter); | |
636 seenFilter[filter.text] = null; | |
637 } | |
638 | |
639 var remove = []; | |
640 for (var i = 0; i < FilterStorage.subscriptions.length; i++) | |
641 { | |
642 var subscription = FilterStorage.subscriptions[i]; | |
643 if (!(subscription instanceof SpecialSubscription)) | |
644 continue; | |
645 | |
646 for (var j = 0; j < subscription.filters.length; j++) | |
647 { | |
648 var filter = subscription.filters[j]; | |
649 if (filter instanceof WhitelistFilter && /^@@\|\|([^\/:]+)\^\$document$/.t
est(filter.text)) | |
650 continue; | |
651 | |
652 if (!(filter.text in seenFilter)) | |
653 remove.push(filter); | |
654 } | |
655 } | |
656 | |
657 for (var i = 0; i < remove.length; i++) | |
658 FilterStorage.removeFilter(remove[i]); | |
659 | |
660 $("#rawFilters").hide(); | |
661 } | 651 } |
662 | 652 |
663 // Called when user explicitly requests filter list updates | 653 // Called when user explicitly requests filter list updates |
664 function updateFilterLists() | 654 function updateFilterLists() |
665 { | 655 { |
666 for (var i = 0; i < FilterStorage.subscriptions.length; i++) | 656 // Without the URL parameter this will update all subscriptions |
| 657 updateSubscription(); |
| 658 |
| 659 // Display a message for any subscriptions that are currently being downloaded |
| 660 getSubscriptions(true, false, function(subscriptions) |
667 { | 661 { |
668 var subscription = FilterStorage.subscriptions[i]; | 662 var inProgressMessage = i18n.getMessage( |
669 if (subscription instanceof DownloadableSubscription) | 663 "filters_subscription_lastDownload_inProgress" |
670 Synchronizer.execute(subscription, true, true); | 664 ); |
671 } | 665 |
| 666 for (var i = 0; i < subscriptions.length; i += 1) |
| 667 { |
| 668 var element = findSubscriptionElement(subscriptions[i]); |
| 669 if (element) |
| 670 { |
| 671 var label = element.getElementsByClassName("subscriptionUpdate")[0]; |
| 672 isSubscriptionDownloading(subscriptions[i].url, |
| 673 function(label, isDownloading) |
| 674 { |
| 675 if (isDownloading) |
| 676 label.textContent = inProgressMessage; |
| 677 }.bind(undefined, label) |
| 678 ); |
| 679 } |
| 680 } |
| 681 }); |
672 } | 682 } |
673 | 683 |
674 // Adds a subscription entry to the UI. | 684 // Adds a subscription entry to the UI. |
675 function addSubscriptionEntry(subscription) | 685 function addSubscriptionEntry(subscription) |
676 { | 686 { |
677 var template = document.getElementById("subscriptionTemplate"); | 687 var template = document.getElementById("subscriptionTemplate"); |
678 var element = template.cloneNode(true); | 688 var element = template.cloneNode(true); |
679 element.removeAttribute("id"); | 689 element.removeAttribute("id"); |
680 element._subscription = subscription; | 690 element._subscription = subscription; |
681 | 691 |
682 var removeButton = element.getElementsByClassName("subscriptionRemoveButton")[
0]; | 692 var removeButton = element.getElementsByClassName("subscriptionRemoveButton")[
0]; |
683 removeButton.setAttribute("title", removeButton.textContent); | 693 removeButton.setAttribute("title", removeButton.textContent); |
684 removeButton.textContent = "\xD7"; | 694 removeButton.textContent = "\xD7"; |
685 removeButton.addEventListener("click", function() | 695 removeButton.addEventListener("click", function() |
686 { | 696 { |
687 if (!confirm(i18n.getMessage("global_remove_subscription_warning"))) | 697 if (!confirm(i18n.getMessage("global_remove_subscription_warning"))) |
688 return; | 698 return; |
689 | 699 |
690 FilterStorage.removeSubscription(subscription); | 700 removeSubscription(subscription.url); |
691 }, false); | 701 }, false); |
692 if (Prefs.additional_subscriptions.indexOf(subscription.url) != -1) | 702 |
693 removeButton.style.visibility = "hidden"; | 703 getPref("additional_subscriptions", function(additionalSubscriptions) |
| 704 { |
| 705 if (additionalSubscriptions.indexOf(subscription.url) != -1) |
| 706 removeButton.style.visibility = "hidden"; |
| 707 }); |
694 | 708 |
695 var enabled = element.getElementsByClassName("subscriptionEnabled")[0]; | 709 var enabled = element.getElementsByClassName("subscriptionEnabled")[0]; |
696 enabled.addEventListener("click", function() | 710 enabled.addEventListener("click", function() |
697 { | 711 { |
698 if (subscription.disabled == !enabled.checked) | 712 subscription.disabled = !subscription.disabled; |
699 return; | 713 toggleSubscription(subscription.url, true); |
700 | |
701 subscription.disabled = !enabled.checked; | |
702 }, false); | 714 }, false); |
703 | 715 |
704 updateSubscriptionInfo(element); | 716 updateSubscriptionInfo(element); |
705 | 717 |
706 document.getElementById("filterLists").appendChild(element); | 718 document.getElementById("filterLists").appendChild(element); |
707 } | 719 } |
708 | 720 |
709 function setLinks(id) | 721 function setLinks(id) |
710 { | 722 { |
711 var element = document.getElementById(id); | 723 var element = document.getElementById(id); |
712 if (!element) | 724 if (!element) |
713 return; | 725 return; |
714 | 726 |
715 var links = element.getElementsByTagName("a"); | 727 var links = element.getElementsByTagName("a"); |
716 for (var i = 0; i < links.length; i++) | 728 for (var i = 0; i < links.length; i++) |
717 { | 729 { |
718 if (typeof arguments[i + 1] == "string") | 730 if (typeof arguments[i + 1] == "string") |
719 { | 731 { |
720 links[i].href = arguments[i + 1]; | 732 links[i].href = arguments[i + 1]; |
721 links[i].setAttribute("target", "_blank"); | 733 links[i].setAttribute("target", "_blank"); |
722 } | 734 } |
723 else if (typeof arguments[i + 1] == "function") | 735 else if (typeof arguments[i + 1] == "function") |
724 { | 736 { |
725 links[i].href = "javascript:void(0);"; | 737 links[i].href = "javascript:void(0);"; |
726 links[i].addEventListener("click", arguments[i + 1], false); | 738 links[i].addEventListener("click", arguments[i + 1], false); |
727 } | 739 } |
728 } | 740 } |
729 } | 741 } |
| 742 |
| 743 ext.onMessage.addListener(function(message) |
| 744 { |
| 745 switch (message.type) |
| 746 { |
| 747 case "app.respond": |
| 748 switch (message.action) |
| 749 { |
| 750 case "addSubscription": |
| 751 var subscription = message.args[0]; |
| 752 startSubscriptionSelection(subscription.title, subscription.url); |
| 753 break; |
| 754 case "switchToOptionsSection": |
| 755 var tabs = document.getElementsByClassName("ui-tabs-panel"); |
| 756 for (var i = 0; i < tabs.length; i++) |
| 757 { |
| 758 var found = tabs[i].querySelector( |
| 759 "[data-section='" + message.args[0] + "']" |
| 760 ); |
| 761 if (!found) |
| 762 continue; |
| 763 |
| 764 var previous = document.getElementsByClassName("focused"); |
| 765 if (previous.length > 0) |
| 766 previous[0].classList.remove("focused"); |
| 767 |
| 768 var tab = $("[href='#" + tabs[i].id + "']"); |
| 769 $("#tabs").tabs("select", tab.parent().index()); |
| 770 found.classList.add("focused"); |
| 771 } |
| 772 break; |
| 773 } |
| 774 break; |
| 775 case "filters.respond": |
| 776 onFilterMessage(message.action, message.args[0]); |
| 777 break; |
| 778 case "prefs.respond": |
| 779 onPrefMessage(message.action, message.args[0]); |
| 780 break; |
| 781 case "subscriptions.respond": |
| 782 onSubscriptionMessage(message.action, message.args[0]); |
| 783 break; |
| 784 } |
| 785 }); |
OLD | NEW |