| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 /** | |
| 146 * Observes changes to a DOM node using a <code>MutationObserver</code>. | 123 * Observes changes to a DOM node using a <code>MutationObserver</code>. |
| 147 * | 124 * |
| 148 * @param {Node} target The DOM node to observe for changes. | 125 * @param {Node} target The DOM node to observe for changes. |
| 149 * @param {MutationObserverInit?} [options] Options that describe what DOM | 126 * @param {MutationObserverInit?} [options] Options that describe what DOM |
| 150 * mutations should be reported to the callback. | 127 * mutations should be reported to the callback. |
| 151 * @param {function} callback A function that will be called on each DOM | 128 * @param {function} callback A function that will be called on each DOM |
| 152 * mutation, taking a <code>MutationRecord</code> as its parameter. | 129 * mutation, taking a <code>MutationRecord</code> as its parameter. |
| 153 */ | 130 */ |
| 154 function observe(target, options, callback) | 131 function observe(target, options, callback) |
| 155 { | 132 { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 | 209 |
| 233 // Since it's a weak map, it's possible that either the element or its | 210 // Since it's a weak map, it's possible that either the element or its |
| 234 // shadow has been removed. | 211 // shadow has been removed. |
| 235 if (!host || !root) | 212 if (!host || !root) |
| 236 return; | 213 return; |
| 237 | 214 |
| 238 // If the shadow contains the given text, check if the host or one of its | 215 // If the shadow contains the given text, check if the host or one of its |
| 239 // ancestors matches the selector; if a matching element is found, hide | 216 // ancestors matches the selector; if a matching element is found, hide |
| 240 // it. | 217 // it. |
| 241 if (root.textContent.includes(search)) | 218 if (root.textContent.includes(search)) |
| 242 hideAncestor(host, selector); | 219 { |
| 220 let closest = host.closest(selector); | |
| 221 if (closest) | |
| 222 hideElement(closest); | |
| 223 } | |
| 243 } | 224 } |
| 244 | 225 |
| 245 Object.defineProperty(Element.prototype, "attachShadow", { | 226 Object.defineProperty(Element.prototype, "attachShadow", { |
| 246 value(...args) | 227 value(...args) |
| 247 { | 228 { |
| 248 // Create the shadow root first. It doesn't matter if it's a closed | 229 // Create the shadow root first. It doesn't matter if it's a closed |
| 249 // shadow root, we keep the reference in a weak map. | 230 // shadow root, we keep the reference in a weak map. |
| 250 let root = originalAttachShadow.apply(this, args); | 231 let root = originalAttachShadow.apply(this, args); |
| 251 | 232 |
| 252 // Listen for relevant DOM mutations in the shadow. | 233 // Listen for relevant DOM mutations in the shadow. |
| 253 let observer = new MutationObserver(observeShadow); | 234 let observer = new MutationObserver(observeShadow); |
| 254 observer.observe(root, { | 235 observer.observe(root, { |
| 255 childList: true, | 236 childList: true, |
| 256 characterData: true, | 237 characterData: true, |
| 257 subtree: true | 238 subtree: true |
| 258 }); | 239 }); |
| 259 | 240 |
| 260 // Keep references to the shadow root and its host in a weak map. If | 241 // Keep references to the shadow root and its host in a weak map. If |
| 261 // either the shadow is detached or the host itself is removed from the | 242 // either the shadow is detached or the host itself is removed from the |
| 262 // DOM, the mutation observer too will be freed eventually and the entry | 243 // DOM, the mutation observer too will be freed eventually and the entry |
| 263 // will be removed. | 244 // will be removed. |
| 264 shadows.set(observer, {host: this, root}); | 245 shadows.set(observer, {host: this, root}); |
| 265 | 246 |
| 266 return root; | 247 return root; |
| 267 } | 248 } |
| 268 }); | 249 }); |
| 269 } | 250 } |
| 270 | 251 |
| 271 exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains, | 252 exports["hide-if-shadow-contains"] = makeInjector(hideIfShadowContains, |
| 272 hideAncestor, hideElement); | 253 hideElement); |
| 273 | 254 |
| 274 /** | 255 /** |
| 275 * Hides any HTML element or one of its ancestors matching a CSS selector if | 256 * Hides any HTML element or one of its ancestors matching a CSS selector if |
| 276 * the text content of the element contains a given string. | 257 * the text content of the element contains a given string. |
| 277 * | 258 * |
| 278 * @param {string} search The string to look for in HTML elements. | 259 * @param {string} search The string to look for in HTML elements. |
| 279 * @param {string} selector The CSS selector that an HTML element must match | 260 * @param {string} selector The CSS selector that an HTML element must match |
| 280 * for it to be hidden. | 261 * for it to be hidden. |
| 281 * @param {string?} [searchSelector] The CSS selector that an HTML element | 262 * @param {string?} [searchSelector] The CSS selector that an HTML element |
| 282 * containing the given string must match. Defaults to the value of the | 263 * containing the given string must match. Defaults to the value of the |
| 283 * <code>selector</code> argument. | 264 * <code>selector</code> argument. |
| 284 */ | 265 */ |
| 285 function hideIfContains(search, selector = "*", searchSelector = null) | 266 function hideIfContains(search, selector = "*", searchSelector = null) |
| 286 { | 267 { |
| 287 if (searchSelector == null) | 268 if (searchSelector == null) |
| 288 searchSelector = selector; | 269 searchSelector = selector; |
| 289 | 270 |
| 290 new MutationObserver(() => | 271 new MutationObserver(() => |
| 291 { | 272 { |
| 292 for (let element of document.querySelectorAll(searchSelector)) | 273 for (let element of document.querySelectorAll(searchSelector)) |
| 293 { | 274 { |
| 294 if (element.textContent.includes(search)) | 275 if (element.textContent.includes(search)) |
| 295 hideAncestor(element, selector); | 276 { |
| 277 let closest = element.closest(selector); | |
| 278 if (closest) | |
| 279 hideElement(closest); | |
| 280 } | |
| 296 } | 281 } |
| 297 }) | 282 }) |
| 298 .observe(document, {childList: true, characterData: true, subtree: true}); | 283 .observe(document, {childList: true, characterData: true, subtree: true}); |
| 299 } | 284 } |
| 300 | 285 |
| 301 exports["hide-if-contains"] = hideIfContains; | 286 exports["hide-if-contains"] = hideIfContains; |
| 302 | 287 |
| 303 /** | 288 /** |
| 304 * Readds to the document any removed HTML elements that match a CSS selector. | 289 * Readds to the document any removed HTML elements that match a CSS selector. |
| 305 * | 290 * |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 323 // We don't have the location of the element in its former parent, | 308 // We don't have the location of the element in its former parent, |
| 324 // but it's usually OK to just add it at the end. | 309 // but it's usually OK to just add it at the end. |
| 325 mutation.target.appendChild(node); | 310 mutation.target.appendChild(node); |
| 326 } | 311 } |
| 327 } | 312 } |
| 328 } | 313 } |
| 329 }); | 314 }); |
| 330 } | 315 } |
| 331 | 316 |
| 332 exports.readd = readd; | 317 exports.readd = readd; |
| LEFT | RIGHT |