I'm developing chrome extension MV3 which hide article.
MutationObserver hide article without flickering at main frame.
For example, below code hides odd's article at Reddit when there's new article by scrolling down.
function eraseDealer(){
console.log("erase Function Call");
let ls = document.querySelectorAll('#SHORTCUT_FOCUSABLE_DIV > div:nth-child(4) > div > div > div > div._3ozFtOe6WpJEMUtxDOIvtU > div._31N0dvxfpsO6Ur5AKx4O5d > div._1OVBBWLtHoSPfGCRaPzpTf._2OVNlZuUd8L9v0yVECZ2iA > div.rpBJOHq2PR60pnwJlUyP0 > div');
let idx;
for(idx=ls.length-1; idx>=0; idx--){
if(idx%2===0) continue
ls[idx].setAttribute('style', 'display: none;');
}
}
eraseDealer();
var config = { childList: true, characterData: false };
var htmlBody = document.getElementsByClassName('rpBJOHq2PR60pnwJlUyP0')[0];
var observerErase = new MutationObserver(function(mutations, observer) {
mutations.forEach(function(mutation) {
console.log("Mutation call - erase");
eraseDealer();
});
});
observerErase.observe(htmlBody, config);
But if MutationObserver(in main frame) observe article(in iframe), there's flickering(first show article, then hide article)
Below code works at Korea community site and what code does is similar to the code above.
See how it works at loom
function eraseDealer(){
let inner_iframe = document.getElementById('cafe_main').contentWindow;
let post_table = inner_iframe.document.querySelectorAll('#main-area > div.article-board.m-tcol-c')[1];
if(post_table !== undefined){
let ls = post_table.querySelectorAll('div.article-board.m-tcol-c > table > tbody > tr');
let idx;
let dealer_link = 'https://cafe.pstatic.net/levelicon/1/1_150.gif';
for(idx=ls.length-1; idx>=0; idx--){
let src = ls[idx].querySelector('td.td_name > div > table > tbody > tr > td > span > img').getAttribute('src');
let nickName = ls[idx].querySelector('td.td_name > div > table > tbody > tr > td > a').textContent;
if(src === dealer_link){
ls[idx].setAttribute('style', 'display: none;');
}
}
}
}
eraseDealer();
var config = { attributes: true, childList: true, subtree: true, characterData: false };
var target = document.querySelector('#main-area');
var observerErase = new MutationObserver(function(mutations, observer) {
mutations.forEach(function(mutation) {
console.log("Mutation call - erase");
eraseDealer();
});
});
observerErase.observe(target, config);
Why I insert mutationObserver not in iframe but in main frame is that mutationObserver is deleted when iframe url is changed
See my before question concerned about this
Is there any MutationObserver property need to stop flickering concerned with iframe?
I searched a lot with stackoverflow and chrome documentation, but I can't find solution
Instead of MutationObserver in the main document you can detect the moment the iframe is navigated inside, then add a MutationObserver for the iframe's contents.
checkFrameReady
listener will run after iframe's URL changes, but before its navigation is complete.var SEL = '.td_name img[src="https://cafe.pstatic.net/levelicon/1/1_150.gif"]';
var fw = document.querySelector('#cafe_main').contentWindow;
fw.addEventListener('unload', checkFrameReady);
function checkFrameReady(e) {
if (!e.type) {
try {
startObserver(new fw.MutationObserver(eraseDealer));
fw.addEventListener('unload', checkFrameReady);
return;
} catch (e) {}
}
requestAnimationFrame(checkFrameReady);
}
function eraseDealer(mutations, observer) {
let stopped;
for (const { addedNodes } of mutations) {
for (const n of addedNodes) {
if (!n.tagName) continue;
const elems = n.matches(SEL) && [n] ||
n.firstElementChild && n.querySelectorAll(SEL);
if (!elems || !elems.length) continue;
if (!stopped) { stopped = true; observer.disconnect(); }
elems.forEach(el => el.closest('.td_name').closest('tr').remove());
}
}
if (stopped) startObserver(observer);
}
function startObserver(observer) {
observer.observe(fw.document.body || fw.document.documentElement,
{childList: true, subtree: true});
}