| Index: include.postload.js |
| =================================================================== |
| --- a/include.postload.js |
| +++ b/include.postload.js |
| @@ -267,24 +267,6 @@ |
| return getURLsFromAttributes(element); |
| } |
| -function isBlockable(element) |
| -{ |
| - if (element.id) |
| - return true; |
| - if (element.classList.length > 0) |
| - return true; |
| - if (getURLsFromElement(element).length > 0) |
| - return true; |
| - |
| - // We only generate filters based on the "style" attribute, |
| - // if this is the only way we can generate a filter, and |
| - // only if there are at least two CSS properties defined. |
| - if (/:.+:/.test(getOriginalStyle(element))) |
| - return true; |
| - |
| - return false; |
| -} |
| - |
| // Gets the absolute position of an element by walking up the DOM tree, |
| // adding up offsets. |
| // I hope there's a better way because it just seems absolutely stupid |
| @@ -301,14 +283,9 @@ |
| } |
| // Adds an overlay to an element, which is probably a Flash object |
| -function addElementOverlay(elt) { |
| +function addElementOverlay(elt, callback) { |
| // If this element is enclosed in an object tag, we prefer to block that instead |
| if(!elt) |
| - return null; |
| - |
| - // If element doesn't have at least one of class name, ID or URL, give up |
| - // because we don't know how to construct a filter rule for it |
| - if(!isBlockable(elt)) |
| return; |
| // If the element isn't rendered (since its or one of its ancestor's |
| @@ -316,23 +293,30 @@ |
| if (!elt.offsetParent) |
| return; |
| - var thisStyle = getComputedStyle(elt, null); |
| - var overlay = document.createElement('div'); |
| - overlay.prisoner = elt; |
| - overlay.className = "__adblockplus__overlay"; |
| - overlay.setAttribute('style', 'opacity:0.4; background-color:#ffffff; display:inline-box; ' + 'width:' + thisStyle.width + '; height:' + thisStyle.height + '; position:absolute; overflow:hidden; -webkit-box-sizing:border-box;'); |
| - var pos = getAbsolutePosition(elt); |
| - overlay.style.left = pos[0] + "px"; |
| - overlay.style.top = pos[1] + "px"; |
| + generateFilters(elt, function(filters) |
| + { |
| + if (filters.length == 0) |
| + return; |
| - if (thisStyle.position != "static") |
| - overlay.style.zIndex = thisStyle.zIndex; |
| - else |
| - overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; |
| + var thisStyle = getComputedStyle(elt, null); |
| + var overlay = document.createElement('div'); |
| + overlay.prisoner = elt; |
| + overlay.className = "__adblockplus__overlay"; |
| + overlay.setAttribute('style', 'opacity:0.4; background-color:#ffffff; display:inline-box; ' + 'width:' + thisStyle.width + '; height:' + thisStyle.height + '; position:absolute; overflow:hidden; -webkit-box-sizing:border-box;'); |
| + var pos = getAbsolutePosition(elt); |
| + overlay.style.left = pos[0] + "px"; |
| + overlay.style.top = pos[1] + "px"; |
| - // elt.parentNode.appendChild(overlay, elt); |
| - document.body.appendChild(overlay); |
| - return overlay; |
| + if (thisStyle.position != "static") |
| + overlay.style.zIndex = thisStyle.zIndex; |
| + else |
| + overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; |
| + |
| + document.body.appendChild(overlay); |
| + |
| + if (callback) |
| + callback(overlay); |
| + }); |
| } |
| // Show dialog asking user whether she wants to add the proposed filters derived |
| @@ -443,31 +427,50 @@ |
| clickHide_mouseClick(ev); |
| } |
| +function getBlockableElementOrAncestor(element, callback) |
| +{ |
| + if (element && element != document.documentElement |
| + && element != document.body) |
| + { |
| + generateFilters(element, function(filters) |
| + { |
| + if (filters.length > 0) |
| + callback(element); |
| + else |
| + getBlockableElementOrAncestor(element.parentElement, callback); |
| + }); |
| + } |
| + else |
| + { |
| + callback(null); |
| + } |
| +} |
| + |
| // Hovering over an element so highlight it |
| function clickHide_mouseOver(e) |
| { |
| if (clickHide_activated == false) |
| return; |
| - var target = e.target; |
| - while (target.parentNode && !isBlockable(target)) |
| - target = target.parentNode; |
| - if (target == document.documentElement || target == document.body) |
| - target = null; |
| + getBlockableElementOrAncestor(e.target, function(element) |
| + { |
| + if (currentElement) |
| + unhighlightElement(currentElement); |
| - if (target && target instanceof HTMLElement) |
| - { |
| - currentElement = target; |
| + if (element) |
| + { |
| + highlightElement(element, "#d6d84b", "#f8fa47"); |
| + element.addEventListener("contextmenu", clickHide_elementClickHandler, true); |
| + } |
| - highlightElement(target, "#d6d84b", "#f8fa47"); |
| - target.addEventListener("contextmenu", clickHide_elementClickHandler, true); |
| - } |
| + currentElement = element; |
| + }); |
| } |
| // No longer hovering over this element so unhighlight it |
| function clickHide_mouseOut(e) |
| { |
| - if (!clickHide_activated || !currentElement) |
| + if (!clickHide_activated || currentElement != e.target) |
| return; |
| unhighlightElement(currentElement); |
| @@ -494,6 +497,108 @@ |
| } |
| } |
| +function generateFilters(element, callback) |
| +{ |
| + function addStyleAttributeFilter(filters, selectors) |
| + { |
| + var style = getOriginalStyle(element); |
| + if (style && filters.length == 0) |
| + { |
| + ext.backgroundPage.sendMessage( |
| + { |
| + type: "get-filters-from-selectors", |
| + selectors: [escapeCSS(element.localName) + '[style=' + quote(style) + ']'] |
| + }, |
| + |
| + function(response) |
| + { |
| + callback(filters.concat(response.filters), selectors.concat(response.selectors)); |
| + } |
| + ); |
| + } |
| + else |
| + callback(filters, selectors); |
| + } |
| + |
| + function addElemHideFilter(filters, selectors) |
| + { |
| + if (selectors.length > 0) |
| + { |
| + ext.backgroundPage.sendMessage( |
| + { |
| + type: "get-filters-from-selectors", |
| + selectors: selectors |
| + }, |
| + |
| + function(response) |
| + { |
| + addStyleAttributeFilter(filters.concat(response.filters), response.selectors); |
| + } |
| + ); |
| + } |
| + else |
| + addStyleAttributeFilter(filters, selectors); |
| + } |
| + |
| + var filters = []; |
| + var selectors = []; |
| + |
| + if (element.id) |
| + selectors.push("#" + escapeCSS(element.id)); |
| + |
| + if (element.classList.length > 0) |
| + { |
| + var selector = ""; |
| + |
| + for (var i = 0; i < element.classList.length; i++) |
| + selector += "." + escapeCSS(element.classList[i]); |
| + |
| + selectors.push(selector); |
| + } |
| + |
| + var urls = getURLsFromElement(element); |
| + if (urls.length > 0) |
| + { |
| + ext.backgroundPage.sendMessage( |
| + { |
| + type: "check-whitelisted-urls", |
| + mediatype: typeMap[element.localName], |
| + urls: urls |
| + }, |
| + |
| + function(whitelisted) |
| + { |
| + for (var i = 0; i < urls.length; i++) |
| + { |
| + var url = urls[i]; |
| + |
| + if (!whitelisted[url] && /^https?:/i.test(url)) |
| + { |
| + var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); |
| + |
| + if (filters.indexOf(filter) == -1) |
| + filters.push(filter); |
| + |
| + continue; |
| + } |
| + |
| + if (url == element.src) |
| + { |
| + var selector = escapeCSS(element.localName) + '[src=' + quote(element.getAttribute("src")) + ']'; |
| + |
| + if (selectors.indexOf(selector) == -1) |
| + selectors.push(selector); |
| + } |
| + } |
| + |
| + addElemHideFilter(filters, selectors); |
| + } |
| + ); |
| + } |
| + else |
| + addElemHideFilter(filters, selectors); |
| +} |
| + |
| // When the user clicks, the currentElement is the one we want. |
| // We should have ABP rules ready for when the |
| // popup asks for them. |
| @@ -506,66 +611,17 @@ |
| if (currentElement.classList.contains("__adblockplus__overlay")) |
| elt = currentElement.prisoner; |
| - clickHideFilters = new Array(); |
| - selectorList = new Array(); |
| + generateFilters(elt, function(filters, selectors) |
| + { |
| + clickHide_showDialog(e.clientX, e.clientY, filters); |
| - var addSelector = function(selector) |
| - { |
| - if (selectorList.indexOf(selector) != -1) |
| - return; |
| + // Highlight the elements specified by selector in yellow |
| + if (selectors.length > 0) |
| + highlightElements(selectors.join(",")); |
| - clickHideFilters.push(document.domain + "##" + selector); |
| - selectorList.push(selector); |
| - }; |
| - |
| - if (elt.id) |
| - addSelector("#" + escapeCSS(elt.id)); |
| - |
| - if (elt.classList.length > 0) |
| - { |
| - var selector = ""; |
| - |
| - for (var i = 0; i < elt.classList.length; i++) |
| - selector += "." + escapeCSS(elt.classList[i]); |
| - |
| - addSelector(selector); |
| - } |
| - |
| - var urls = getURLsFromElement(elt); |
| - for (var i = 0; i < urls.length; i++) |
| - { |
| - var url = urls[i]; |
| - |
| - if (/^https?:/i.test(url)) |
| - { |
| - var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); |
| - |
| - if (clickHideFilters.indexOf(filter) == -1) |
| - clickHideFilters.push(filter); |
| - |
| - continue; |
| - } |
| - |
| - if (url == elt.src) |
| - addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("src")) + ']'); |
| - } |
| - |
| - // as last resort, create a filter based on inline styles |
| - if (clickHideFilters.length == 0) |
| - { |
| - var style = getOriginalStyle(elt); |
| - if (style) |
| - addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); |
| - } |
| - |
| - // Show popup |
| - clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); |
| - |
| - // Highlight the elements specified by selector in yellow |
| - if (selectorList.length > 0) |
| - highlightElements(selectorList.join(",")); |
| - // Now, actually highlight the element the user clicked on in red |
| - highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
| + // Now, actually highlight the element the user clicked on in red |
| + highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
| + }); |
| // Make sure the browser doesn't handle this click |
| e.preventDefault(); |
| @@ -692,9 +748,14 @@ |
| case "clickhide-new-filter": |
| if(lastRightClickEvent) |
| { |
| - clickHide_activated = true; |
| - currentElement = addElementOverlay(lastRightClickEvent.target); |
| - clickHide_mouseClick(lastRightClickEvent); |
| + var event = lastRightClickEvent; |
| + |
| + addElementOverlay(event.target, function(overlay) |
| + { |
| + clickHide_activated = true; |
| + currentElement = overlay; |
| + clickHide_mouseClick(event); |
| + }); |
| } |
| break; |
| case "clickhide-init": |