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": |