I have a problem:
Every resource I looked for tells me this should work and it does in Chrome, Safari.. but not in Firefox.
System: macOS Catalina 10.15.7, Chrome 90.0.4430.212, Firefox 88.0.1, Edge 90.0.818.66
What I try to achieve / have achieved on Chrome: finding an iFrame, that is hosted on the same domain, and targeting some child nodes there and changing attributes, removing text inputs etc.
A simplified version of my JS code:
// set as null first because the iFrame takes some time to load
let iframeBody = null;
// this function is only run once, while it should be run on every MutationObserver change
function purge (iframe) {
var timer = null;
// only by querying that iFrame again Firefox picked up the purge function, I don't need that for Chrome
let iF = document.querySelector('#chatbot iframe').contentWindow.document.body;
var inputField = iF.querySelector('div > div.frame-content > div.widget-position-right > div.chat > div.input-group');
if(!inputField || typeof inputField === 'undefined') {
if(timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(purge, 50);
return;
}
// remove it
inputField.remove();
}
// this one is never called in FF
function cb (mutationList) {
let chatDiv = iframeBody.querySelector('div > div.frame-content > div.widget-position-right > div.chat')
if (chatDiv) {
mutationList.some(item => {
if (item.type === 'childList' && item.addedNodes && item.addedNodes[0] === chatDiv) {
purge();
return true;
}
})
}
let button = iframeBody.querySelector("div > div.frame-content > div.widget-position-right > #button")
// make button invisible if found, restore if chat is closed
if (button) {
if (button.classList.contains('chat-open')) {
button.style.opacity = 0;
button.style.pointerEvents = "none";
button.style.width = 0;
}
else {
button.style.opacity = 1;
button.style.pointerEvents = "auto";
button.style.width = "auto";
}
}
}
function bind () {
try {
iframeBody = document.querySelector('#chatbot iframe').contentWindow.document.body;
if (!iframeBody) {
return setTimeout(bind, 500) // wait and retry because iFrame is not loaded immediately
}
if(iframeBody){
console.log("iframeBody found");
}
const mutationObservable = new MutationObserver(cb)
// actually don't need characterData, just an attempt to pick up the observed event
const config = { characterData: true, attributes: true, childList: true, subtree: true};
setTimeout(() => {
// this is the initial call that works in FF (and Chrome/Safari naturally)
purge();
mutationObservable.observe(iframeBody, config);
}, 500);
} catch (err) {
// console.log(err);
// try to bind again, can take some time to load
setTimeout(bind, 100)
}
}
// start here
bind();
})();
I verified that I can access the HTML nodes with querySelector in the Developer console and edit them just fine in all browsers, it is just the MutationObserver callback that is not picked up.
I tried to put write it like this
new MutationObserver((mutation) => {
// cb function goes here
})
but to no avail. I have been sitting at this for a few hours now, just to get it to work, and I am tempted to just deactivate it all together for Firefox..
Any hints are very appreciated. If any additional resources are needed, please let me know.
Update: tried suggestion from comments with new frameElem.contentWindow.MutationObserver
by calling MutationObserver like this without any change:
const iframeElmWindow = document.querySelector('#chatbot iframe').contentWindow;
const mutationObservable = new iframeElmWindow.MutationObserver(cb);