Left: | ||
Right: |
OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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; |
OLD | NEW |