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

Side by Side Diff: include.postload.js

Issue 4998212691689472: Some click-hide improvements (Closed)
Patch Set: Also fixed key handler Created Dec. 18, 2013, 10:58 a.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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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("keydown", clickHide_keyDown, 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() {
167 clickHide_activated = false; 167 clickHide_activated = false;
168 document.removeEventListener("mouseover", clickHide_mouseOver, false); 168 document.removeEventListener("mouseover", clickHide_mouseOver, false);
169 document.removeEventListener("mouseout", clickHide_mouseOut, false); 169 document.removeEventListener("mouseout", clickHide_mouseOut, false);
170 document.removeEventListener("click", clickHide_mouseClick, false); 170 document.removeEventListener("click", clickHide_mouseClick, false);
171 document.removeEventListener("keyup", clickHide_keyUp, false); 171 document.removeEventListener("keydown", clickHide_keyDown, false);
172 } 172 }
173 173
174 // Turn off click-to-hide 174 // Turn off click-to-hide
175 function clickHide_deactivate() 175 function clickHide_deactivate()
176 { 176 {
177 if (clickHideFiltersDialog) 177 if (clickHideFiltersDialog)
178 { 178 {
179 document.body.removeChild(clickHideFiltersDialog); 179 document.body.removeChild(clickHideFiltersDialog);
180 clickHideFiltersDialog = null; 180 clickHideFiltersDialog = null;
181 } 181 }
182 182
183 if(currentElement) { 183 if(currentElement) {
184 currentElement.removeEventListener("contextmenu", clickHide_elementClickHand ler, false); 184 currentElement.removeEventListener("contextmenu", clickHide_elementClickHand ler, false);
185 unhighlightElements(); 185 unhighlightElements();
186 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxSha dow); 186 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxSha dow);
187 currentElement.style.backgroundColor = currentElement_backgroundColor; 187 currentElement.style.backgroundColor = currentElement_backgroundColor;
188 currentElement = null; 188 currentElement = null;
189 clickHideFilters = null; 189 clickHideFilters = null;
190 } 190 }
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("keydown", clickHide_keyDown, 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 if (target == document.documentElement || target == document.body)
224 e.target.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #d6d84b" ); 225 target = null;
225 e.target.style.backgroundColor = "#f8fa47";
226 226
227 // TODO: save old context menu 227 if (target && target instanceof HTMLElement)
228 e.target.addEventListener("contextmenu", clickHide_elementClickHandler, fals e); 228 {
229 currentElement = target;
230 currentElement_boxShadow = target.style.getPropertyValue("-webkit-box-shadow ");
231 currentElement_backgroundColor = target.style.backgroundColor;
232 target.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #d6d84b");
233 target.style.backgroundColor = "#f8fa47";
234
235 target.addEventListener("contextmenu", clickHide_elementClickHandler, false) ;
229 } 236 }
230 } 237 }
231 238
232 // No longer hovering over this element so unhighlight it 239 // No longer hovering over this element so unhighlight it
233 function clickHide_mouseOut(e) { 240 function clickHide_mouseOut(e)
234 if(!clickHide_activated || !currentElement) 241 {
242 if (!clickHide_activated || !currentElement)
235 return; 243 return;
236 244
237 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado w); 245 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado w);
238 currentElement.style.backgroundColor = currentElement_backgroundColor; 246 currentElement.style.backgroundColor = currentElement_backgroundColor;
239 247
240 // TODO: restore old context menu
241 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle r, false); 248 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle r, false);
242 } 249 }
243 250
244 // Selects the currently hovered-over filter 251 // Selects the currently hovered-over filter or cancels selection
245 function clickHide_keyUp(e) { 252 function clickHide_keyDown(e)
246 // Ctrl+Shift+E 253 {
247 if(e.ctrlKey && e.shiftKey && e.keyCode == 69) 254 if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 13 /*DOM_VK_ENTER*/ )
Thomas Greiner 2013/12/18 11:17:12 Different sources mention different codes. Does it
Wladimir Palant 2013/12/18 11:39:57 Sure. The comment is wrong however, I meant VK_RET
248 clickHide_mouseClick(e); 255 clickHide_mouseClick(e);
256 else if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 27 /*DOM_VK_ES CAPE*/)
257 {
258 clickHide_deactivate();
259 e.preventDefault();
260 e.stopPropagation();
261 }
249 } 262 }
250 263
251 // When the user clicks, the currentElement is the one we want. 264 // When the user clicks, the currentElement is the one we want.
252 // We should have ABP rules ready for when the 265 // We should have ABP rules ready for when the
253 // popup asks for them. 266 // popup asks for them.
254 function clickHide_mouseClick(e) { 267 function clickHide_mouseClick(e)
255 if(!currentElement || !clickHide_activated) 268 {
269 if (!currentElement || !clickHide_activated)
256 return; 270 return;
257 271
258 var elt = currentElement; 272 var elt = currentElement;
259 var url = null; 273 var url = null;
260 if(currentElement.className && currentElement.className == "__adblockplus__ove rlay") { 274 if (currentElement.className && currentElement.className == "__adblockplus__ov erlay")
275 {
261 elt = currentElement.prisoner; 276 elt = currentElement.prisoner;
262 url = currentElement.prisonerURL; 277 url = currentElement.prisonerURL;
263 } else if(elt.src) { 278 }
279 else if (elt.src)
264 url = elt.src; 280 url = elt.src;
265 }
266 281
267 // Only normalize when the element contains a URL (issue 328.) 282 // Only normalize when the element contains a URL (issue 328.)
268 // The URL is not always normalized, so do it here 283 // The URL is not always normalized, so do it here
269 if(url) 284 if (url)
270 url = normalizeURL(relativeToAbsoluteUrl(url)); 285 url = normalizeURL(relativeToAbsoluteUrl(url));
271 286
272 // Construct filters. The popup will retrieve these. 287 // Construct filters. The popup will retrieve these.
273 // Only one ID 288 // Only one ID
274 var elementId = elt.id ? elt.id.split(' ').join('') : null; 289 var elementId = elt.id ? elt.id.split(' ').join('') : null;
275 // Can have multiple classes, and there might be extraneous whitespace 290 // Can have multiple classes, and there might be extraneous whitespace
276 var elementClasses = null; 291 var elementClasses = null;
277 if(elt.className) { 292 if (elt.className)
278 elementClasses = elt.className.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '' ).split(' '); 293 elementClasses = elt.className.replace(/\s+/g, ' ').replace(/^\s+|\s+$/g, '' ).split(' ');
279 } 294
280 clickHideFilters = new Array(); 295 clickHideFilters = new Array();
281 selectorList = new Array(); 296 selectorList = new Array();
282 if(elementId) { 297 if (elementId)
298 {
283 clickHideFilters.push(document.domain + "###" + elementId); 299 clickHideFilters.push(document.domain + "###" + elementId);
284 selectorList.push("#" + elementId); 300 selectorList.push("#" + elementId);
285 } 301 }
286 if(elementClasses) { 302 if (elementClasses)
287 for(var i = 0; i < elementClasses.length; i++) { 303 {
304 for(var i = 0; i < elementClasses.length; i++)
305 {
288 clickHideFilters.push(document.domain + "##." + elementClasses[i]); 306 clickHideFilters.push(document.domain + "##." + elementClasses[i]);
289 selectorList.push("." + elementClasses[i]); 307 selectorList.push("." + elementClasses[i]);
290 } 308 }
291 } 309 }
292 if(url) { 310 if (url)
311 {
293 clickHideFilters.push(relativeToAbsoluteUrl(url)); 312 clickHideFilters.push(relativeToAbsoluteUrl(url));
294 selectorList.push(elt.localName + '[src="' + url + '"]'); 313 selectorList.push(elt.localName + '[src="' + url + '"]');
295 } 314 }
296 315
297 // Show popup 316 // Show popup
298 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); 317 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters);
299 318
300 // Set background color in case it got selected using context menu 319 // Set background color in case it got selected using context menu
301 if (typeof currentElement_backgroundColor == "undefined") 320 if (typeof currentElement_backgroundColor == "undefined")
302 currentElement_backgroundColor = currentElement.style.backgroundColor; 321 currentElement_backgroundColor = currentElement.style.backgroundColor;
303 322
304 // Highlight the unlucky elements 323 // Highlight the unlucky elements
305 // Restore currentElement's box-shadow and bgcolor so that highlightElements w on't save those 324 // 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); 325 currentElement.style.setProperty("-webkit-box-shadow", currentElement_boxShado w);
307 currentElement.style.backgroundColor = currentElement_backgroundColor; 326 currentElement.style.backgroundColor = currentElement_backgroundColor;
308 // Highlight the elements specified by selector in yellow 327 // Highlight the elements specified by selector in yellow
309 highlightElements(selectorList.join(",")); 328 highlightElements(selectorList.join(","));
310 // Now, actually highlight the element the user clicked on in red 329 // Now, actually highlight the element the user clicked on in red
311 currentElement.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #fd1 708"); 330 currentElement.style.setProperty("-webkit-box-shadow", "inset 0px 0px 5px #fd1 708");
312 currentElement.style.backgroundColor = "#f6a1b5"; 331 currentElement.style.backgroundColor = "#f6a1b5";
332
333 // Make sure the browser doesn't handle this click
334 e.preventDefault();
335 e.stopPropagation();
313 } 336 }
314 337
315 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME 338 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME
316 function getElementURL(elt) { 339 function getElementURL(elt) {
317 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL 340 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL
318 // in value attribute 341 // in value attribute
319 var url; 342 var url;
320 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data") )) { 343 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 344 // No data attribute, look in PARAM child tags for a URL for the swf file
322 var params = elt.querySelectorAll("param[name=\"movie\"]"); 345 var params = elt.querySelectorAll("param[name=\"movie\"]");
323 // This OBJECT could contain an EMBED we already nuked, in which case there' s no URL 346 // This OBJECT could contain an EMBED we already nuked, in which case there' s no URL
324 if(params[0]) 347 if(params[0])
325 url = params[0].getAttribute("value"); 348 url = params[0].getAttribute("value");
326 else { 349 else {
327 params = elt.querySelectorAll("param[name=\"src\"]"); 350 params = elt.querySelectorAll("param[name=\"src\"]");
328 if(params[0]) 351 if(params[0])
329 url = params[0].getAttribute("value"); 352 url = params[0].getAttribute("value");
330 } 353 }
331 } else if(!url) { 354 } else if(!url) {
332 url = elt.getAttribute("src") || elt.getAttribute("href"); 355 url = elt.getAttribute("src") || elt.getAttribute("href");
333 } 356 }
334 return url; 357 return url;
335 } 358 }
336 359
337 // Converts relative to absolute URL 360 // Converts relative to absolute URL
338 // e.g.: foo.swf on http://example.com/whatever/bar.html 361 // e.g.: foo.swf on http://example.com/whatever/bar.html
339 // -> http://example.com/whatever/foo.swf 362 // -> http://example.com/whatever/foo.swf
340 function relativeToAbsoluteUrl(url) 363 function relativeToAbsoluteUrl(url)
341 { 364 {
342 // If URL is already absolute, don't mess with it 365 // If URL is already absolute, don't mess with it
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 url = url.replace(/^\s+/, "").replace(/\s+$/, ""); 493 url = url.replace(/^\s+/, "").replace(/\s+$/, "");
471 if (!/^(https?|ftp):/.test(url)) 494 if (!/^(https?|ftp):/.test(url))
472 return; 495 return;
473 496
474 ext.backgroundPage.sendMessage({ 497 ext.backgroundPage.sendMessage({
475 type: "add-subscription", 498 type: "add-subscription",
476 title: title, 499 title: title,
477 url: url 500 url: url
478 }); 501 });
479 }, true); 502 }, true);
480 503
481 ext.onMessage.addListener(function(msg, sender, sendResponse) 504 ext.onMessage.addListener(function(msg, sender, sendResponse)
482 { 505 {
483 switch (msg.type) 506 switch (msg.type)
484 { 507 {
485 case "get-clickhide-state": 508 case "get-clickhide-state":
486 sendResponse({active: clickHide_activated}); 509 sendResponse({active: clickHide_activated});
487 break; 510 break;
488 case "clickhide-activate": 511 case "clickhide-activate":
489 clickHide_activate(); 512 clickHide_activate();
490 break; 513 break;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 586
564 clickHide_deactivate(); 587 clickHide_deactivate();
565 } 588 }
566 break; 589 break;
567 default: 590 default:
568 sendResponse({}); 591 sendResponse({});
569 break; 592 break;
570 } 593 }
571 }); 594 });
572 } 595 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld