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

Unified Diff: lib/content/snippets.js

Issue 30024560: Issue 7450 - Implement hide-if-contains-visible-text snippet (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Minor documentation tweak Created April 17, 2019, 5:24 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | test/browser/_utils.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/content/snippets.js
===================================================================
--- a/lib/content/snippets.js
+++ b/lib/content/snippets.js
@@ -403,50 +403,149 @@
}
exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains,
toRegExp, regexEscape,
hideElement);
/**
* Hides any HTML element or one of its ancestors matching a CSS selector if
+ * it matches the provided condition.
+ *
+ * @param {function} match The function that provides the matching condition.
+ * @param {string} selector The CSS selector that an HTML element must match
+ * for it to be hidden.
+ * @param {string?} [searchSelector] The CSS selector that an HTML element
Manish Jethani 2019/04/17 18:52:35 Nit: Maybe a good opportunity to fix the JSDoc: `?
hub 2019/04/17 21:38:06 Done.
+ * containing the given string must match. Defaults to the value of the
+ * <code>selector</code> argument.
+ */
+function hideIfMatch(match, selector, searchSelector)
Manish Jethani 2019/04/17 18:52:34 Nit: Suggestion: `hideIfMatches()`
hub 2019/04/17 21:38:06 Done.
+{
+ if (searchSelector == null)
+ searchSelector = selector;
+
+ new MutationObserver(() =>
+ {
+ for (let element of document.querySelectorAll(searchSelector))
+ {
+ if (match(element))
+ {
+ let closest = element.closest(selector);
+ if (closest)
+ hideElement(closest);
+ }
+ }
+ })
+ .observe(document, {childList: true, characterData: true, subtree: true});
+}
+
+/**
+ * Hides any HTML element or one of its ancestors matching a CSS selector if
* the text content of the element contains a given string.
*
* @param {string} search The string to look for in HTML elements. If the
* string begins and ends with a slash (<code>/</code>), the text in between
* is treated as a regular expression.
* @param {string} selector The CSS selector that an HTML element must match
* for it to be hidden.
* @param {string?} [searchSelector] The CSS selector that an HTML element
* containing the given string must match. Defaults to the value of the
* <code>selector</code> argument.
*/
function hideIfContains(search, selector = "*", searchSelector = null)
{
- if (searchSelector == null)
- searchSelector = selector;
+ let re = toRegExp(search);
+
+ hideIfMatch(element => re.test(element.textContent),
+ selector, searchSelector);
+}
+
+exports["hide-if-contains"] = hideIfContains;
+
+/**
+ * Hides any HTML element matching a CSS selector if the visible text content
+ * of the element contains a given string.
+ *
+ * @param {string} search The text to match to the visible text. Is considered
Manish Jethani 2019/04/17 18:52:35 Nit: s/The text to match/The string to match/ Nit
hub 2019/04/17 21:38:06 Done.
+ * visible text that isn't hidden by CSS properties or other means.
+ * If the string begins and ends with a slash (<code>/</code>), the
+ * text in between is treated as a regular expression.
+ * @param {string} selector The CSS selector that an HTML element must match
+ * for it to be hidden.
+ * @param {string?} [searchSelector] The CSS selector that an HTML element
+ * containing the given string must match. Defaults to the value of the
+ * <code>selector</code> argument.
+ */
+function hideIfContainsVisibleText(search, selector, searchSelector = null)
+{
+ /**
+ * Determines if the text inside the element is visible.
+ * @param {Element} element The leaf element we are checking.
Manish Jethani 2019/04/17 18:52:35 Nit: Shouldn't this just be "The element", since w
hub 2019/04/17 21:38:06 Done.
+ * @param {?CSSStyleDeclaration} [style] The computed style of element. If
+ * falsey it will be queried.
+ * @returns {bool} Whether the text is visible.
+ */
+ function isTextVisible(element, style)
+ {
+ if (!style)
+ style = window.getComputedStyle(element);
Manish Jethani 2019/04/17 18:52:34 Nit: `window.` is kinda redundant here, but maybe
hub 2019/04/17 21:38:06 Acknowledged.
+
+ if (style.getPropertyValue("opacity") == "0")
+ return false;
+ if (style.getPropertyValue("font-size") == "0px")
+ return false;
+ if (style.getPropertyValue("color") ==
+ style.getPropertyValue("background-color"))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns the visible text content from an element and its children.
Manish Jethani 2019/04/17 18:52:35 Nit: "and its children" is kinda redundant, but if
hub 2019/04/17 21:38:06 Done.
+ * @param {Element} element The element whose visible text we want.
+ * @returns {string} The text that is visible.
+ */
+ function getVisibleContent(element)
+ {
+ let style = window.getComputedStyle(element);
+ if (style.getPropertyValue("display") == "none")
+ return "";
+ let visibility = style.getPropertyValue("visibility");
+ if (visibility == "hidden" || visibility == "collapse")
+ return "";
+
+ let text = "";
+ for (let node of element.childNodes)
+ {
+ switch (node.nodeType)
+ {
+ case Node.ELEMENT_NODE:
+ text += getVisibleContent(node);
+ break;
+ case Node.TEXT_NODE:
+ if (isTextVisible(element, style))
+ text += node.nodeValue;
+ break;
+ }
+ }
+ return text;
+ }
let re = toRegExp(search);
- new MutationObserver(() =>
+ hideIfMatch(element =>
Manish Jethani 2019/04/17 18:52:35 Wondering if we can shorten this to: hideIfMatc
hub 2019/04/17 21:38:06 No exactly. But ok.
Manish Jethani 2019/04/18 08:40:43 Ah, sorry I got that wrong. Thanks.
{
- for (let element of document.querySelectorAll(searchSelector))
- {
- if (re.test(element.textContent))
- {
- let closest = element.closest(selector);
- if (closest)
- hideElement(closest);
- }
- }
- })
- .observe(document, {childList: true, characterData: true, subtree: true});
+ let content = getVisibleContent(element);
+ return re.test(content);
+ }, selector, searchSelector);
}
-exports["hide-if-contains"] = hideIfContains;
+exports["hide-if-contains-visible-text"] =
+ makeInjector(hideIfContainsVisibleText, hideIfMatch, hideElement);
hub 2019/04/17 17:27:02 It doesn't need to be a type 2. I need to fix the
/**
* Hides any HTML element or one of its ancestors matching a CSS selector if
* the text content of the element contains a given string and, optionally, if
* the element's computed style contains a given string.
*
* @param {string} search The string to look for in HTML elements. If the
* string begins and ends with a slash (<code>/</code>), the text in between
« no previous file with comments | « no previous file | test/browser/_utils.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld