I have a chat button created by a script (zendesk chat). It generate an iframe in the page with the ID "launcher". I'm using Nextjs and Im trying to get this element but I cannot attach a ref since I've not the code. I am digging the web for a solution and I have tried something like this (in the footer component because it is on all pages and I am able to figure out which page I am on):
React.useLayoutEffect(() => {
function checkElExist() {
if (typeof document !== 'undefined') {
const el = document.querySelector('#launcher');
if (!isSingleVehiclePage) {
console.log('NOT VEHICLE', el);
if (el) {
el.classList.remove('inVehicle');
el.classList.add('notInVehiclePage');
}
} else {
console.log('IN VEHICLE', el);
if (el) {
el.classList.remove('notInVehiclePage');
el.classList.add('inVehicle');
}
}
}
}
window.addEventListener('load', checkElExist);
return () => window.removeEventListener('load', checkElExist);
}, [isSingleVehiclePage]);
I don't know if is the right solution. It kinda works but sometimes the element is null especially when I land on that specific page from an external link (not when I navigate the site). Is it possibile to get this element? My goal is to add/remove a class to it according to specific pages.
Thanks
EDIT: I dont know if it is relevant, but in the html the iframe is out of my "__next" div. In the pic below, I circled the __next div, the footer div (where my useLayoutEffect code is executed) and the iframe I want to get.
SOLVED: I use a function that runs recursively every 1000ms. If it can't find the element in 9000ms, it stops.
React.useEffect(() => {
waitForElementToDisplay(
'#launcher',
function (el: any) {
checkElExist(el);
},
1000,
9000
);
function checkElExist(el: any) {
if (!isSingleVehiclePage) {
console.log('NOT VEHICLE', el);
el.classList.remove('inVehicle');
el.classList.add('notInVehiclePage');
} else {
console.log('IN VEHICLE', el);
el.classList.remove('notInVehiclePage');
el.classList.add('inVehicle');
}
}
}, [isSingleVehiclePage]);
function waitForElementToDisplay(
selector: string,
callback: any,
checkFrequencyInMs: number,
timeoutInMs: number
) {
const startTimeInMs = Date.now();
(function loopSearch() {
if (document && document.querySelector(selector) != null) {
console.log('found');
const element = document.querySelector(selector);
callback(element);
return;
} else {
setTimeout(function () {
if (timeoutInMs && Date.now() - startTimeInMs > timeoutInMs) return;
loopSearch();
}, checkFrequencyInMs);
}
})();
}