Skip to content

Instantly share code, notes, and snippets.

@endymion1818
Last active December 16, 2024 10:41
Show Gist options
  • Save endymion1818/ffc282bcd9eed4859796711452c19f1d to your computer and use it in GitHub Desktop.
Save endymion1818/ffc282bcd9eed4859796711452c19f1d to your computer and use it in GitHub Desktop.
Wait for an element to appear in the DOM
/**
* Wait for an element to be added to the DOM or shadow DOM.
* @param {ShadowRoot | Document} root - The root to observe.
* @param {string} selector - The selector of the element to wait for.
* @param {number} [timeout] - The time in milliseconds to wait before rejecting the promise.
* @return {Promise<HTMLElement | Node>} - A promise that resolves with the element when it is added to the DOM or shadow DOM.
*/
function waitForElement(root, selector, timeout = 1000) {
let timeoutId;
return new Promise((resolve, reject) => {
let element = root.querySelector(selector);
if (element) {
resolve(element);
return;
}
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type !== "childList") {
return;
}
mutation.addedNodes.forEach((node) => {
if (node.nodeType !== Node.ELEMENT_NODE) {
return;
}
if (node.matches(selector)) {
observer.disconnect();
clearTimeout(timeoutId);
resolve(node);
return;
}
const shadowElement = node?.shadowRoot?.querySelector(selector);
if (shadowElement) {
observer.disconnect();
clearTimeout(timeoutId);
resolve(shadowElement);
return;
}
if (node.shadowRoot) {
observer.observe(node.shadowRoot, {
childList: true,
subtree: true,
});
}
element = root.querySelector(selector);
if (element) {
observer.disconnect();
clearTimeout(timeoutId);
resolve(element);
}
});
});
});
observer.observe(root, { childList: true, subtree: true });
timeoutId = setTimeout(() => {
observer.disconnect();
reject(new Error(`Element not found: ${selector}`));
}, timeout);
});
}
export default waitForElement;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment