Skip to content

Instantly share code, notes, and snippets.

@jwilson8767
Last active April 22, 2024 20:28
Show Gist options
  • Save jwilson8767/db379026efcbd932f64382db4b02853e to your computer and use it in GitHub Desktop.
Save jwilson8767/db379026efcbd932f64382db4b02853e to your computer and use it in GitHub Desktop.
Wait for an element to exist. ES6, Promise, MutationObserver
// MIT Licensed
// Author: jwilson8767
/**
* Waits for an element satisfying selector to exist, then resolves promise with the element.
* Useful for resolving race conditions.
*
* @param selector
* @returns {Promise}
*/
export function elementReady(selector) {
return new Promise((resolve, reject) => {
let el = document.querySelector(selector);
if (el) {
resolve(el);
return
}
new MutationObserver((mutationRecords, observer) => {
// Query for elements matching the specified selector
Array.from(document.querySelectorAll(selector)).forEach((element) => {
resolve(element);
//Once we have resolved we don't need the observer anymore.
observer.disconnect();
});
})
.observe(document.documentElement, {
childList: true,
subtree: true
});
});
}
import { elementReady } from "es6-element-ready";
// Simple usage to delete an element if/when it exists:
elementReady('#someWidget').then((someWidget)=>{someWidget.remove();});
@bezborodow
Copy link

bezborodow commented May 29, 2023

@acropup, an alternative solution is to match on the unique ID only, and not use selectors. This would be intuitive, since the promise resolves after the first match is found.

However, if there was a way to reliably tokenise a selector, it could be found through introspection what kind combinators are present and adjust the match/query algorithm accordingly. There is a css-selector-tokenizer package, but that seems overkill for something that should be easily achievable.

@bezborodow
Copy link

bezborodow commented May 29, 2023

section:has(div > strong) example using closest(). Adjacent and sibling combinators can also be implemented, but the important aspect in terms of performance is having a tokeniser to introspect and recognise which algorithm to pick based on the complexity of the selector. Although even without that, this should represent a substantial improvement.

const element = (addedNode.matches(selector) && addedNode)
  || addedNode.querySelector(selector)
  || addedNode.closest(selector);

@mdovn
Copy link

mdovn commented Feb 17, 2024

ok boo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment