Skip to content

Commit 0f330c7

Browse files
committed
Add ability to linger for remove-attr scriplet
Related issue: - uBlockOrigin/uBlock-issues#1445 A third (optional) argument has been added to `remove-attr` scriptlet, which can be one or more space-separated tokens dictating the behavior of the scriptlet: `stay`: This tells the scriplet to stay and act on DOM changes, whiĺe the default behavior is to act only once when the document becomes interactive. `complete`: This tells the scriplet to start acting only when the document is complete, i.e. once all secondary resources have been loaded, while the default is to start acting when the document is interactive -- which is earlier than when the document is complete. Example: ...##+js(remove-attr, class, .j-mini-player, stay)
1 parent 0e3071d commit 0f330c7

File tree

1 file changed

+36
-4
lines changed

1 file changed

+36
-4
lines changed

assets/resources/scriptlets.js

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,10 @@
665665
if ( selector === '' || selector === '{{2}}' ) {
666666
selector = `[${tokens.join('],[')}]`;
667667
}
668-
const rmattr = function() {
668+
let behavior = '{{3}}';
669+
let timer;
670+
const rmattr = ( ) => {
671+
timer = undefined;
669672
try {
670673
const nodes = document.querySelectorAll(selector);
671674
for ( const node of nodes ) {
@@ -676,10 +679,39 @@
676679
} catch(ex) {
677680
}
678681
};
679-
if ( document.readyState === 'loading' ) {
680-
window.addEventListener('DOMContentLoaded', rmattr, { once: true });
681-
} else {
682+
const mutationHandler = mutations => {
683+
if ( timer !== undefined ) { return; }
684+
let skip = true;
685+
for ( let i = 0; i < mutations.length && skip; i++ ) {
686+
const { type, addedNodes, removedNodes } = mutations[i];
687+
if ( type === 'attributes' ) { skip = false; }
688+
for ( let j = 0; j < addedNodes.length && skip; j++ ) {
689+
if ( addedNodes[j].nodeType === 1 ) { skip = false; break; }
690+
}
691+
for ( let j = 0; j < removedNodes.length && skip; j++ ) {
692+
if ( removedNodes[j].nodeType === 1 ) { skip = false; break; }
693+
}
694+
}
695+
if ( skip ) { return; }
696+
timer = self.requestIdleCallback(rmattr, { timeout: 67 });
697+
};
698+
const start = ( ) => {
682699
rmattr();
700+
if ( /\bstay\b/.test(behavior) === false ) { return; }
701+
const observer = new MutationObserver(mutationHandler);
702+
observer.observe(document.documentElement, {
703+
attributes: true,
704+
attributeFilter: tokens,
705+
childList: true,
706+
subtree: true,
707+
});
708+
};
709+
if ( document.readyState !== 'complete' && /\bcomplete\b/.test(behavior) ) {
710+
document.addEventListener('load', start, { once: true });
711+
} else if ( document.readyState === 'loading' ) {
712+
document.addEventListener('DOMContentLoaded', start, { once: true });
713+
} else {
714+
start();
683715
}
684716
})();
685717

0 commit comments

Comments
 (0)