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

Side by Side Diff: lib/content/snippets.js

Issue 29851644: Issue 6848 - Add searchSelector parameter to hide-if-contains snippet (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Created Aug. 9, 2018, 3:40 p.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 <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present 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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 * 90 *
91 * @returns {function} The generated injector. 91 * @returns {function} The generated injector.
92 */ 92 */
93 function makeInjector(injectable, ...dependencies) 93 function makeInjector(injectable, ...dependencies)
94 { 94 {
95 return (...args) => injectCode(stringifyFunctionCall(injectable, ...args), 95 return (...args) => injectCode(stringifyFunctionCall(injectable, ...args),
96 dependencies); 96 dependencies);
97 } 97 }
98 98
99 /** 99 /**
100 * Hides an HTML element by settings its <code>style</code> attribute to 100 * Hides an HTML element by setting its <code>style</code> attribute to
101 * <code>display: none !important</code>. 101 * <code>display: none !important</code>.
102 * 102 *
103 * @param {HTMLElement} element The HTML element to hide. 103 * @param {HTMLElement} element The HTML element to hide.
104 */ 104 */
105 function hideElement(element) 105 function hideElement(element)
106 { 106 {
107 element.style.setProperty("display", "none", "important"); 107 element.style.setProperty("display", "none", "important");
108 108
109 // Listen for changes to the style property and if our values are unset 109 // Listen for changes to the style property and if our values are unset
110 // then reset them. 110 // then reset them.
111 new MutationObserver(() => 111 new MutationObserver(() =>
112 { 112 {
113 if (element.style.getPropertyValue("display") != "none" || 113 if (element.style.getPropertyValue("display") != "none" ||
114 element.style.getPropertyPriority("display") != "important") 114 element.style.getPropertyPriority("display") != "important")
115 { 115 {
116 element.style.setProperty("display", "none", "important"); 116 element.style.setProperty("display", "none", "important");
117 } 117 }
118 }) 118 })
119 .observe(element, {attributes: true, attributeFilter: ["style"]}); 119 .observe(element, {attributes: true, attributeFilter: ["style"]});
120 } 120 }
121 121
122 /** 122 /**
123 * Hides an HTML element or one of its ancestors matching a CSS selector by
124 * setting its <code>style</code> attribute to
125 * <code>display: none !important</code>.
126 *
127 * @param {HTMLElement} element The HTML element or a descendant of the HTML
128 * element to hide.
129 * @param {string} [selector] The CSS selector that the HTML element or one of
130 * its ancestors must match for it to be hidden.
131 */
132 function hideAncestor(element, selector = "*")
133 {
134 do
135 {
136 if (element.matches(selector))
hub 2018/08/10 12:30:41 Wouldn't https://developer.mozilla.org/en-US/docs/
Manish Jethani 2018/08/10 14:57:02 Ah, you're right. Element.closest is perfect. It'
hub 2018/08/10 19:54:57 We support EdgeHTML 16 and up if I read things cor
137 {
138 hideElement(element);
139 break;
140 }
141 }
142 while (element = element.parentElement);
143 }
144
145 /**
123 * Observes changes to a DOM node using a <code>MutationObserver</code>. 146 * Observes changes to a DOM node using a <code>MutationObserver</code>.
124 * 147 *
125 * @param {Node} target The DOM node to observe for changes. 148 * @param {Node} target The DOM node to observe for changes.
126 * @param {MutationObserverInit?} [options] Options that describe what DOM 149 * @param {MutationObserverInit?} [options] Options that describe what DOM
127 * mutations should be reported to the callback. 150 * mutations should be reported to the callback.
128 * @param {function} callback A function that will be called on each DOM 151 * @param {function} callback A function that will be called on each DOM
129 * mutation, taking a <code>MutationRecord</code> as its parameter. 152 * mutation, taking a <code>MutationRecord</code> as its parameter.
130 */ 153 */
131 function observe(target, options, callback) 154 function observe(target, options, callback)
132 { 155 {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 232
210 // Since it's a weak map, it's possible that either the element or its 233 // Since it's a weak map, it's possible that either the element or its
211 // shadow has been removed. 234 // shadow has been removed.
212 if (!host || !root) 235 if (!host || !root)
213 return; 236 return;
214 237
215 // If the shadow contains the given text, check if the host or one of its 238 // If the shadow contains the given text, check if the host or one of its
216 // ancestors matches the selector; if a matching element is found, hide 239 // ancestors matches the selector; if a matching element is found, hide
217 // it. 240 // it.
218 if (root.textContent.includes(search)) 241 if (root.textContent.includes(search))
219 { 242 hideAncestor(host, selector);
220 let element = host;
221
222 do
223 {
224 if (element.matches(selector))
225 {
226 hideElement(element);
227 break;
228 }
229 }
230 while (element = element.parentElement);
231 }
232 } 243 }
233 244
234 Object.defineProperty(Element.prototype, "attachShadow", { 245 Object.defineProperty(Element.prototype, "attachShadow", {
235 value(...args) 246 value(...args)
236 { 247 {
237 // Create the shadow root first. It doesn't matter if it's a closed 248 // Create the shadow root first. It doesn't matter if it's a closed
238 // shadow root, we keep the reference in a weak map. 249 // shadow root, we keep the reference in a weak map.
239 let root = originalAttachShadow.apply(this, args); 250 let root = originalAttachShadow.apply(this, args);
240 251
241 // Listen for relevant DOM mutations in the shadow. 252 // Listen for relevant DOM mutations in the shadow.
242 let observer = new MutationObserver(observeShadow); 253 let observer = new MutationObserver(observeShadow);
243 observer.observe(root, { 254 observer.observe(root, {
244 childList: true, 255 childList: true,
245 characterData: true, 256 characterData: true,
246 subtree: true 257 subtree: true
247 }); 258 });
248 259
249 // Keep references to the shadow root and its host in a weak map. If 260 // Keep references to the shadow root and its host in a weak map. If
250 // either the shadow is detached or the host itself is removed from the 261 // either the shadow is detached or the host itself is removed from the
251 // DOM, the mutation observer too will be freed eventually and the entry 262 // DOM, the mutation observer too will be freed eventually and the entry
252 // will be removed. 263 // will be removed.
253 shadows.set(observer, {host: this, root}); 264 shadows.set(observer, {host: this, root});
254 265
255 return root; 266 return root;
256 } 267 }
257 }); 268 });
258 } 269 }
259 270
260 exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains, 271 exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains,
261 hideElement); 272 hideAncestor, hideElement);
262 273
263 /** 274 /**
264 * Hides any HTML element if the text content of the element contains a given 275 * Hides any HTML element or one of its ancestors matching a CSS selector if
265 * string. 276 * the text content of the element contains a given string.
266 * 277 *
267 * @param {string} search The string to look for in every HTML element. 278 * @param {string} search The string to look for in HTML elements.
268 * @param {string} selector The CSS selector that an HTML element must match 279 * @param {string} selector The CSS selector that an HTML element must match
269 * for it to be hidden. 280 * for it to be hidden.
281 * @param {string?} [searchSelector] The CSS selector that an HTML element
282 * containing the given string must match. Defaults to the value of the
283 * <code>selector</code> argument.
270 */ 284 */
271 function hideIfContains(search, selector = "*") 285 function hideIfContains(search, selector = "*", searchSelector = null)
272 { 286 {
287 if (searchSelector == null)
288 searchSelector = selector;
289
273 new MutationObserver(() => 290 new MutationObserver(() =>
274 { 291 {
275 for (let element of document.querySelectorAll(selector)) 292 for (let element of document.querySelectorAll(searchSelector))
276 { 293 {
277 if (element.textContent.includes(search)) 294 if (element.textContent.includes(search))
278 hideElement(element); 295 hideAncestor(element, selector);
279 } 296 }
280 }) 297 })
281 .observe(document, {childList: true, characterData: true, subtree: true}); 298 .observe(document, {childList: true, characterData: true, subtree: true});
282 } 299 }
283 300
284 exports["hide-if-contains"] = hideIfContains; 301 exports["hide-if-contains"] = hideIfContains;
285 302
286 /** 303 /**
287 * Readds to the document any removed HTML elements that match a CSS selector. 304 * Readds to the document any removed HTML elements that match a CSS selector.
288 * 305 *
(...skipping 17 matching lines...) Expand all
306 // We don't have the location of the element in its former parent, 323 // We don't have the location of the element in its former parent,
307 // but it's usually OK to just add it at the end. 324 // but it's usually OK to just add it at the end.
308 mutation.target.appendChild(node); 325 mutation.target.appendChild(node);
309 } 326 }
310 } 327 }
311 } 328 }
312 }); 329 });
313 } 330 }
314 331
315 exports.readd = readd; 332 exports.readd = readd;
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