Skip to content

Instantly share code, notes, and snippets.

@paraparata
Created December 9, 2022 09:43
Show Gist options
  • Select an option

  • Save paraparata/14b5cc504c0bc99355bca4eca733c04f to your computer and use it in GitHub Desktop.

Select an option

Save paraparata/14b5cc504c0bc99355bca4eca733c04f to your computer and use it in GitHub Desktop.

Revisions

  1. paraparata created this gist Dec 9, 2022.
    63 changes: 63 additions & 0 deletions waitForEl.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    /**
    * Async to monitor changing state on element (e.g. <button> based on disable attribute)
    */
    export const waitForElState = async <T extends Element | null>(
    selector: string,
    parent: Element | Document,
    validator: (mutations: MutationRecord[]) => boolean,
    callback: () => void,
    options?: Partial<MutationObserverInit>
    ): Promise<T> => {
    const element = await waitForEl<T>(selector, parent);

    return new Promise((resolve) => {
    if (!element) return resolve(null as T);

    const observer = new MutationObserver((mutations) => {
    if (validator(mutations)) {
    if (callback) callback();
    resolve(element as T);
    observer.disconnect();
    }
    });

    observer.observe(element, {
    attributes: true,
    childList: false,
    characterData: false,
    ...options,
    });
    });
    };

    /**
    * Query element until exist.
    * Based on [Yon Wang snippet code](https://stackoverflow.com/a/61511955)
    */
    export const waitForEl = <T extends Element | null>(
    selector: string,
    parent: Element | Document,
    timeOut?: number
    ): Promise<T> =>
    new Promise((resolve) => {
    if (parent.querySelector(selector)) {
    return resolve(parent.querySelector(selector) as T);
    }

    const observer = new MutationObserver(() => {
    if (parent.querySelector(selector)) {
    resolve(document.querySelector(selector) as T);
    observer.disconnect();
    clearTimeout(waitForElTO);
    }
    });

    const waitForElTO = setTimeout(() => {
    if (!parent.querySelector(selector)) observer.disconnect();
    }, timeOut ?? 10000);

    observer.observe(parent === document ? document.body : parent, {
    childList: true,
    subtree: true,
    });
    });