OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2013 Eyeo GmbH | 3 * Copyright (C) 2006-2013 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 |
(...skipping 15 matching lines...) Expand all Loading... |
26 var highlightedElementsBoxShadows = null; | 26 var highlightedElementsBoxShadows = null; |
27 var highlightedElementsBGColors = null; | 27 var highlightedElementsBGColors = null; |
28 var clickHideFiltersDialog = null; | 28 var clickHideFiltersDialog = null; |
29 var lastRightClickEvent = null; | 29 var lastRightClickEvent = null; |
30 | 30 |
31 // Highlight elements according to selector string. This would include | 31 // Highlight elements according to selector string. This would include |
32 // all elements that would be affected by proposed filters. | 32 // all elements that would be affected by proposed filters. |
33 function highlightElements(selectorString) { | 33 function highlightElements(selectorString) { |
34 if(highlightedElementsSelector) | 34 if(highlightedElementsSelector) |
35 unhighlightElements(); | 35 unhighlightElements(); |
36 | 36 |
37 var highlightedElements = document.querySelectorAll(selectorString); | 37 var highlightedElements = document.querySelectorAll(selectorString); |
38 highlightedElementsSelector = selectorString; | 38 highlightedElementsSelector = selectorString; |
39 highlightedElementsBoxShadows = new Array(); | 39 highlightedElementsBoxShadows = new Array(); |
40 highlightedElementsBGColors = new Array(); | 40 highlightedElementsBGColors = new Array(); |
41 | 41 |
42 for(var i = 0; i < highlightedElements.length; i++) { | 42 for(var i = 0; i < highlightedElements.length; i++) { |
43 highlightedElementsBoxShadows[i] = highlightedElements[i].style.getPropertyV
alue("-webkit-box-shadow"); | 43 highlightedElementsBoxShadows[i] = highlightedElements[i].style.getPropertyV
alue("-webkit-box-shadow"); |
44 highlightedElementsBGColors[i] = highlightedElements[i].style.backgroundColo
r; | 44 highlightedElementsBGColors[i] = highlightedElements[i].style.backgroundColo
r; |
45 highlightedElements[i].style.setProperty("-webkit-box-shadow", "inset 0px 0p
x 5px #fd6738"); | 45 highlightedElements[i].style.setProperty("-webkit-box-shadow", "inset 0px 0p
x 5px #fd6738"); |
46 highlightedElements[i].style.backgroundColor = "#f6e1e5"; | 46 highlightedElements[i].style.backgroundColor = "#f6e1e5"; |
(...skipping 26 matching lines...) Expand all Loading... |
73 t += elt.offsetTop; | 73 t += elt.offsetTop; |
74 } | 74 } |
75 return [l, t]; | 75 return [l, t]; |
76 } | 76 } |
77 | 77 |
78 // Adds an overlay to an element, which is probably a Flash object | 78 // Adds an overlay to an element, which is probably a Flash object |
79 function addElementOverlay(elt) { | 79 function addElementOverlay(elt) { |
80 // If this element is enclosed in an object tag, we prefer to block that inste
ad | 80 // If this element is enclosed in an object tag, we prefer to block that inste
ad |
81 if(!elt) | 81 if(!elt) |
82 return null; | 82 return null; |
83 | 83 |
84 // If element doesn't have at least one of class name, ID or URL, give up | 84 // If element doesn't have at least one of class name, ID or URL, give up |
85 // because we don't know how to construct a filter rule for it | 85 // because we don't know how to construct a filter rule for it |
86 var url = getElementURL(elt); | 86 var url = getElementURL(elt); |
87 if(!elt.className && !elt.id && !url) | 87 if(!elt.className && !elt.id && !url) |
88 return; | 88 return; |
89 var thisStyle = getComputedStyle(elt, null); | 89 var thisStyle = getComputedStyle(elt, null); |
90 var overlay = document.createElement('div'); | 90 var overlay = document.createElement('div'); |
91 overlay.prisoner = elt; | 91 overlay.prisoner = elt; |
92 overlay.prisonerURL = url; | 92 overlay.prisonerURL = url; |
93 overlay.className = "__adblockplus__overlay"; | 93 overlay.className = "__adblockplus__overlay"; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 // view of what's going to be blocked | 128 // view of what's going to be blocked |
129 clickHideFiltersDialog.onmouseout = function() | 129 clickHideFiltersDialog.onmouseout = function() |
130 { | 130 { |
131 if (clickHideFiltersDialog) | 131 if (clickHideFiltersDialog) |
132 clickHideFiltersDialog.style.setProperty("opacity", "0.7"); | 132 clickHideFiltersDialog.style.setProperty("opacity", "0.7"); |
133 } | 133 } |
134 clickHideFiltersDialog.onmouseover = function() | 134 clickHideFiltersDialog.onmouseover = function() |
135 { | 135 { |
136 if (clickHideFiltersDialog) | 136 if (clickHideFiltersDialog) |
137 clickHideFiltersDialog.style.setProperty("opacity", "1.0"); | 137 clickHideFiltersDialog.style.setProperty("opacity", "1.0"); |
138 } | 138 } |
139 | 139 |
140 document.body.appendChild(clickHideFiltersDialog); | 140 document.body.appendChild(clickHideFiltersDialog); |
141 } | 141 } |
142 | 142 |
143 // Turn on the choose element to create filter thing | 143 // Turn on the choose element to create filter thing |
144 function clickHide_activate() { | 144 function clickHide_activate() { |
145 if(document == null) | 145 if(document == null) |
146 return; | 146 return; |
147 | 147 |
148 // If we are already selecting, abort now | 148 // If we are already selecting, abort now |
149 if (clickHide_activated || clickHideFiltersDialog) | 149 if (clickHide_activated || clickHideFiltersDialog) |
150 clickHide_deactivate(); | 150 clickHide_deactivate(); |
151 | 151 |
152 // Add overlays for elements with URLs so user can easily click them | 152 // Add overlays for elements with URLs so user can easily click them |
153 var elts = document.querySelectorAll('object,embed,img,iframe'); | 153 var elts = document.querySelectorAll('object,embed,img,iframe'); |
154 for(var i=0; i<elts.length; i++) | 154 for(var i=0; i<elts.length; i++) |
155 addElementOverlay(elts[i]); | 155 addElementOverlay(elts[i]); |
156 | 156 |
157 clickHide_activated = true; | 157 clickHide_activated = true; |
158 document.addEventListener("mouseover", clickHide_mouseOver, false); | 158 document.addEventListener("mouseover", clickHide_mouseOver, false); |
159 document.addEventListener("mouseout", clickHide_mouseOut, false); | 159 document.addEventListener("mouseout", clickHide_mouseOut, false); |
160 document.addEventListener("click", clickHide_mouseClick, false); | 160 document.addEventListener("click", clickHide_mouseClick, false); |
161 document.addEventListener("keyup", clickHide_keyUp, false); | 161 document.addEventListener("keyup", clickHide_keyUp, false); |
162 } | 162 } |
163 | 163 |
164 // Called when user has clicked on something and we are waiting for confirmation | 164 // Called when user has clicked on something and we are waiting for confirmation |
165 // on whether the user actually wants these filters | 165 // on whether the user actually wants these filters |
166 function clickHide_rulesPending() { | 166 function clickHide_rulesPending() { |
(...skipping 24 matching lines...) Expand all Loading... |
191 unhighlightElements(); | 191 unhighlightElements(); |
192 | 192 |
193 clickHide_activated = false; | 193 clickHide_activated = false; |
194 clickHide_filters = null; | 194 clickHide_filters = null; |
195 if(!document) | 195 if(!document) |
196 return; // This can happen inside a nuked iframe...I think | 196 return; // This can happen inside a nuked iframe...I think |
197 document.removeEventListener("mouseover", clickHide_mouseOver, false); | 197 document.removeEventListener("mouseover", clickHide_mouseOver, false); |
198 document.removeEventListener("mouseout", clickHide_mouseOut, false); | 198 document.removeEventListener("mouseout", clickHide_mouseOut, false); |
199 document.removeEventListener("click", clickHide_mouseClick, false); | 199 document.removeEventListener("click", clickHide_mouseClick, false); |
200 document.removeEventListener("keyup", clickHide_keyUp, false); | 200 document.removeEventListener("keyup", clickHide_keyUp, false); |
201 | 201 |
202 // Remove overlays | 202 // Remove overlays |
203 // For some reason iterating over the array returend by getElementsByClassName
() doesn't work | 203 // For some reason iterating over the array returend by getElementsByClassName
() doesn't work |
204 var elt; | 204 var elt; |
205 while(elt = document.querySelector('.__adblockplus__overlay')) | 205 while(elt = document.querySelector('.__adblockplus__overlay')) |
206 elt.parentNode.removeChild(elt); | 206 elt.parentNode.removeChild(elt); |
207 } | 207 } |
208 | 208 |
209 function clickHide_elementClickHandler(ev) { | 209 function clickHide_elementClickHandler(ev) { |
210 ev.preventDefault(); | 210 ev.preventDefault(); |
211 ev.stopPropagation(); | 211 ev.stopPropagation(); |
212 clickHide_mouseClick(ev); | 212 clickHide_mouseClick(ev); |
213 } | 213 } |
214 | 214 |
215 // Hovering over an element so highlight it | 215 // Hovering over an element so highlight it |
216 function clickHide_mouseOver(e) { | 216 function clickHide_mouseOver(e) |
217 if(clickHide_activated == false) | 217 { |
| 218 if (clickHide_activated == false) |
218 return; | 219 return; |
219 | 220 |
220 if(e.target.id || e.target.className || e.target.src) { | 221 var target = e.target; |
221 currentElement = e.target; | 222 while (target.parentNode && !(target.id || target.className || target.src)) |
222 currentElement_boxShadow = e.target.style.getPropertyValue("-webkit-box-shad
ow"); | 223 target = target.parentNode; |
223 currentElement_backgroundColor = e.target.style.backgroundColor; | |
224 e.target.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #d6d84b"
); | |
225 e.target.style.backgroundColor = "#f8fa47"; | |
226 | 224 |
227 // TODO: save old context menu | 225 if (target && target instanceof HTMLElement) |
228 e.target.addEventListener("contextmenu", clickHide_elementClickHandler, fals
e); | 226 { |
| 227 currentElement = target; |
| 228 currentElement_boxShadow = target.style.getPropertyValue("-webkit-box-shadow
"); |
| 229 currentElement_backgroundColor = target.style.backgroundColor; |
| 230 target.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #d6d84b"); |
| 231 target.style.backgroundColor = "#f8fa47"; |
| 232 |
| 233 target.addEventListener("contextmenu", clickHide_elementClickHandler, false)
; |
229 } | 234 } |
230 } | 235 } |
231 | 236 |
232 // No longer hovering over this element so unhighlight it | 237 // No longer hovering over this element so unhighlight it |
233 function clickHide_mouseOut(e) { | 238 function clickHide_mouseOut(e) |
234 if(!clickHide_activated || !currentElement) | 239 { |
| 240 if (!clickHide_activated || !currentElement) |
235 return; | 241 return; |
236 | 242 |
237 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado
w); | 243 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado
w); |
238 currentElement.style.backgroundColor = currentElement_backgroundColor; | 244 currentElement.style.backgroundColor = currentElement_backgroundColor; |
239 | 245 |
240 // TODO: restore old context menu | |
241 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle
r, false); | 246 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle
r, false); |
242 } | 247 } |
243 | 248 |
244 // Selects the currently hovered-over filter | 249 // Selects the currently hovered-over filter |
245 function clickHide_keyUp(e) { | 250 function clickHide_keyUp(e) { |
246 // Ctrl+Shift+E | 251 // Ctrl+Shift+E |
247 if(e.ctrlKey && e.shiftKey && e.keyCode == 69) | 252 if(e.ctrlKey && e.shiftKey && e.keyCode == 69) |
248 clickHide_mouseClick(e); | 253 clickHide_mouseClick(e); |
249 } | 254 } |
250 | 255 |
251 // When the user clicks, the currentElement is the one we want. | 256 // When the user clicks, the currentElement is the one we want. |
252 // We should have ABP rules ready for when the | 257 // We should have ABP rules ready for when the |
253 // popup asks for them. | 258 // popup asks for them. |
254 function clickHide_mouseClick(e) { | 259 function clickHide_mouseClick(e) |
255 if(!currentElement || !clickHide_activated) | 260 { |
| 261 if (!currentElement || !clickHide_activated) |
256 return; | 262 return; |
257 | 263 |
258 var elt = currentElement; | 264 var elt = currentElement; |
259 var url = null; | 265 var url = null; |
260 if(currentElement.className && currentElement.className == "__adblockplus__ove
rlay") { | 266 if (currentElement.className && currentElement.className == "__adblockplus__ov
erlay") |
| 267 { |
261 elt = currentElement.prisoner; | 268 elt = currentElement.prisoner; |
262 url = currentElement.prisonerURL; | 269 url = currentElement.prisonerURL; |
263 } else if(elt.src) { | 270 } |
| 271 else if (elt.src) |
264 url = elt.src; | 272 url = elt.src; |
265 } | |
266 | 273 |
267 // Only normalize when the element contains a URL (issue 328.) | 274 // Only normalize when the element contains a URL (issue 328.) |
268 // The URL is not always normalized, so do it here | 275 // The URL is not always normalized, so do it here |
269 if(url) | 276 if (url) |
270 url = normalizeURL(relativeToAbsoluteUrl(url)); | 277 url = normalizeURL(relativeToAbsoluteUrl(url)); |
271 | 278 |
272 // Construct filters. The popup will retrieve these. | 279 // Construct filters. The popup will retrieve these. |
273 // Only one ID | 280 // Only one ID |
274 var elementId = elt.id ? elt.id.split(' ').join('') : null; | 281 var elementId = elt.id ? elt.id.split(' ').join('') : null; |
275 // Can have multiple classes, and there might be extraneous whitespace | 282 // Can have multiple classes, and there might be extraneous whitespace |
276 var elementClasses = null; | 283 var elementClasses = null; |
277 if(elt.className) { | 284 if (elt.className) |
278 elementClasses = elt.className.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, ''
).split(' '); | 285 elementClasses = elt.className.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, ''
).split(' '); |
279 } | 286 |
280 clickHideFilters = new Array(); | 287 clickHideFilters = new Array(); |
281 selectorList = new Array(); | 288 selectorList = new Array(); |
282 if(elementId) { | 289 if (elementId) |
| 290 { |
283 clickHideFilters.push(document.domain + "###" + elementId); | 291 clickHideFilters.push(document.domain + "###" + elementId); |
284 selectorList.push("#" + elementId); | 292 selectorList.push("#" + elementId); |
285 } | 293 } |
286 if(elementClasses) { | 294 if (elementClasses) |
287 for(var i = 0; i < elementClasses.length; i++) { | 295 { |
| 296 for(var i = 0; i < elementClasses.length; i++) |
| 297 { |
288 clickHideFilters.push(document.domain + "##." + elementClasses[i]); | 298 clickHideFilters.push(document.domain + "##." + elementClasses[i]); |
289 selectorList.push("." + elementClasses[i]); | 299 selectorList.push("." + elementClasses[i]); |
290 } | 300 } |
291 } | 301 } |
292 if(url) { | 302 if (url) |
| 303 { |
293 clickHideFilters.push(relativeToAbsoluteUrl(url)); | 304 clickHideFilters.push(relativeToAbsoluteUrl(url)); |
294 selectorList.push(elt.localName + '[src="' + url + '"]'); | 305 selectorList.push(elt.localName + '[src="' + url + '"]'); |
295 } | 306 } |
296 | 307 |
297 // Show popup | 308 // Show popup |
298 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 309 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); |
299 | 310 |
300 // Set background color in case it got selected using context menu | 311 // Set background color in case it got selected using context menu |
301 if (typeof currentElement_backgroundColor == "undefined") | 312 if (typeof currentElement_backgroundColor == "undefined") |
302 currentElement_backgroundColor = currentElement.style.backgroundColor; | 313 currentElement_backgroundColor = currentElement.style.backgroundColor; |
303 | 314 |
304 // Highlight the unlucky elements | 315 // Highlight the unlucky elements |
305 // Restore currentElement's box-shadow and bgcolor so that highlightElements w
on't save those | 316 // Restore currentElement's box-shadow and bgcolor so that highlightElements w
on't save those |
306 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado
w); | 317 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado
w); |
307 currentElement.style.backgroundColor = currentElement_backgroundColor; | 318 currentElement.style.backgroundColor = currentElement_backgroundColor; |
308 // Highlight the elements specified by selector in yellow | 319 // Highlight the elements specified by selector in yellow |
309 highlightElements(selectorList.join(",")); | 320 highlightElements(selectorList.join(",")); |
310 // Now, actually highlight the element the user clicked on in red | 321 // Now, actually highlight the element the user clicked on in red |
311 currentElement.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #fd1
708"); | 322 currentElement.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #fd1
708"); |
312 currentElement.style.backgroundColor = "#f6a1b5"; | 323 currentElement.style.backgroundColor = "#f6a1b5"; |
| 324 |
| 325 // Make sure the browser doesn't handle this click |
| 326 e.preventDefault(); |
| 327 e.stopPropagation(); |
313 } | 328 } |
314 | 329 |
315 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME | 330 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME |
316 function getElementURL(elt) { | 331 function getElementURL(elt) { |
317 // Check children of object nodes for "param" nodes with name="movie" that spe
cify a URL | 332 // Check children of object nodes for "param" nodes with name="movie" that spe
cify a URL |
318 // in value attribute | 333 // in value attribute |
319 var url; | 334 var url; |
320 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data")
)) { | 335 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data")
)) { |
321 // No data attribute, look in PARAM child tags for a URL for the swf file | 336 // No data attribute, look in PARAM child tags for a URL for the swf file |
322 var params = elt.querySelectorAll("param[name=\"movie\"]"); | 337 var params = elt.querySelectorAll("param[name=\"movie\"]"); |
323 // This OBJECT could contain an EMBED we already nuked, in which case there'
s no URL | 338 // This OBJECT could contain an EMBED we already nuked, in which case there'
s no URL |
324 if(params[0]) | 339 if(params[0]) |
325 url = params[0].getAttribute("value"); | 340 url = params[0].getAttribute("value"); |
326 else { | 341 else { |
327 params = elt.querySelectorAll("param[name=\"src\"]"); | 342 params = elt.querySelectorAll("param[name=\"src\"]"); |
328 if(params[0]) | 343 if(params[0]) |
329 url = params[0].getAttribute("value"); | 344 url = params[0].getAttribute("value"); |
330 } | 345 } |
331 } else if(!url) { | 346 } else if(!url) { |
332 url = elt.getAttribute("src") || elt.getAttribute("href"); | 347 url = elt.getAttribute("src") || elt.getAttribute("href"); |
333 } | 348 } |
334 return url; | 349 return url; |
335 } | 350 } |
336 | 351 |
337 // Converts relative to absolute URL | 352 // Converts relative to absolute URL |
338 // e.g.: foo.swf on http://example.com/whatever/bar.html | 353 // e.g.: foo.swf on http://example.com/whatever/bar.html |
339 // -> http://example.com/whatever/foo.swf | 354 // -> http://example.com/whatever/foo.swf |
340 function relativeToAbsoluteUrl(url) | 355 function relativeToAbsoluteUrl(url) |
341 { | 356 { |
342 // If URL is already absolute, don't mess with it | 357 // If URL is already absolute, don't mess with it |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 url = url.replace(/^\s+/, "").replace(/\s+$/, ""); | 485 url = url.replace(/^\s+/, "").replace(/\s+$/, ""); |
471 if (!/^(https?|ftp):/.test(url)) | 486 if (!/^(https?|ftp):/.test(url)) |
472 return; | 487 return; |
473 | 488 |
474 ext.backgroundPage.sendMessage({ | 489 ext.backgroundPage.sendMessage({ |
475 type: "add-subscription", | 490 type: "add-subscription", |
476 title: title, | 491 title: title, |
477 url: url | 492 url: url |
478 }); | 493 }); |
479 }, true); | 494 }, true); |
480 | 495 |
481 ext.onMessage.addListener(function(msg, sender, sendResponse) | 496 ext.onMessage.addListener(function(msg, sender, sendResponse) |
482 { | 497 { |
483 switch (msg.type) | 498 switch (msg.type) |
484 { | 499 { |
485 case "get-clickhide-state": | 500 case "get-clickhide-state": |
486 sendResponse({active: clickHide_activated}); | 501 sendResponse({active: clickHide_activated}); |
487 break; | 502 break; |
488 case "clickhide-activate": | 503 case "clickhide-activate": |
489 clickHide_activate(); | 504 clickHide_activate(); |
490 break; | 505 break; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 | 578 |
564 clickHide_deactivate(); | 579 clickHide_deactivate(); |
565 } | 580 } |
566 break; | 581 break; |
567 default: | 582 default: |
568 sendResponse({}); | 583 sendResponse({}); |
569 break; | 584 break; |
570 } | 585 } |
571 }); | 586 }); |
572 } | 587 } |
OLD | NEW |