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

Unified Diff: lib/content/snippets.js

Issue 29835561: Issue 6803 - Implement readd snippet (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Add complementary remove-if-contains snippet Created July 23, 2018, 10:28 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 | no next file » | 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
@@ -115,16 +115,35 @@
{
element.style.setProperty("display", "none", "important");
}
})
.observe(element, {attributes: true, attributeFilter: ["style"]});
}
/**
+ * Observes changes to a DOM node using a <code>MutationObserver</code>.
+ *
+ * @param {Node} target The DOM node to observe for changes.
+ * @param {MutationObserverInit?} [options] Options that describe what DOM
+ * mutations should be reported to the callback.
+ * @param {function} callback A function that will be called on each DOM
+ * mutation, taking a <code>MutationRecord</code> as its parameter.
+ */
+function observe(target, options, callback)
+{
+ new MutationObserver(mutations =>
+ {
+ for (let mutation of mutations)
+ callback(mutation);
+ })
+ .observe(target, options);
+}
+
+/**
* Logs its arguments to the console. This may be used for testing and
* debugging.
*
* @param {...*} [args] The arguments to log.
*/
function log(...args)
{
console.log(...args);
@@ -222,8 +241,71 @@
return root;
}
});
}
exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains,
hideElement);
+
+/**
+ * Untrashes a document by readding removed elements that match a CSS selector.
+ *
+ * @param {string} selector The CSS selector that a removed element should
+ * match for it to be added back.
+ * @param {string?} [parentSelector] The CSS selector that a removed element's
+ * former parent should match for it to be added back.
+ * @param {string?} [ifContains] The string that should be found in the text
+ * content of the removed element for it to be added back.
+ * @param {string?} [unlessContains] The string that should not be found in the
+ * text content of the removed element for it to be added back.
+ */
+function untrash(selector, parentSelector = null, ifContains = null,
+ unlessContains = null)
+{
+ observe(document, {childList: true, subtree: true}, mutation =>
+ {
+ if (mutation.removedNodes &&
+ (!parentSelector || (mutation.target instanceof Element &&
+ mutation.target.matches(parentSelector))))
+ {
+ for (let node of mutation.removedNodes)
+ {
+ if (node instanceof HTMLElement && node.matches(selector) &&
+ (!ifContains || node.textContent.includes(ifContains)) &&
+ (!unlessContains || !node.textContent.includes(unlessContains)))
+ {
+ // We don't have the location of the element in its former parent,
+ // but it's usually OK to just add it at the end.
+ mutation.target.appendChild(node);
+ }
+ }
+ }
+ });
+}
+
+exports.untrash = untrash;
+
+/**
+ * Removes any HTML element from the document if the element's text content
+ * contains a given string.
+ *
+ * @param {string} search The string to look for in every HTML element.
+ * @param {string} [selector] The CSS selector that an HTML element must match
+ * for it to be removed from the document.
+ */
+function removeIfContains(search, selector = "*")
+{
+ observe(document, {childList: true, subtree: true}, mutation =>
+ {
+ for (let node of mutation.addedNodes || [])
+ {
+ if (node instanceof HTMLElement && node.matches(selector) &&
+ node.textContent.includes(search))
+ {
+ mutation.target.removeChild(node);
+ }
+ }
+ });
+}
+
+exports["remove-if-contains"] = removeIfContains;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld