onElementReady

detect when an element is ready

Αυτός ο κώδικας δεν πρέπει να εγκατασταθεί άμεσα. Είναι μια βιβλιοθήκη για άλλους κώδικες που περιλαμβάνεται μέσω της οδηγίας meta // @require https://update.greasyfork.org/scripts/419640/1776135/onElementReady.js

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         onElementReady
// @namespace    https://zachhardesty.com
// @exclude      *
// @homepage     https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/utils/onElementReady.js
// @homepageURL  https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/utils/onElementReady.js
// @license      GPL-3.0-only; http://www.gnu.org/licenses/gpl-3.0.txt
// @copyright    2026, Zach Hardesty (https://zachhardesty.com/)
// @version      0.10.2

// @description  Detect any new DOM Element by its CSS Selector, then trigger a function. Includes Promise & Callback interface. Based on ES6 MutationObserver. Ships legacy waitForKeyElements interface, too.
// @author       Zach Hardesty <[email protected]> (https://github.com/zachhardesty7)
// ==/UserScript==

// ORIGINAL CODE BY sidneys: https://gist.github.com/sidneys/ee7a6b80315148ad1fb6847e72a22313

// Remember already found elements via this attribute
const QUERIED_ATTRIBUTE_NAME = "was-queried"

const DEFAULT_OPTIONS = /** @type {const} @satisfies {OnElementReadyOptions} */ ({
  findFirst: false,
  findOnce: true,
  root: document,
})

/**
 * Internal function used by {@link onElementReady} to query for new DOM nodes matching a
 * specified selector.
 *
 * @private
 * @param {string} selector
 * @param {OnElementReadyOptions} options
 * @param {OnElementReadyCallback} callback
 */
// eslint-disable-next-line prefer-const
let queryForElements = (selector, options, callback) => {
  const finalOptions = { ...DEFAULT_OPTIONS, ...options }

  // Search for elements by selector
  const elementList = finalOptions.root?.querySelectorAll(selector) || []
  for (const element of elementList) {
    if (element.hasAttribute(QUERIED_ATTRIBUTE_NAME)) {
      continue
    }

    element.setAttribute(QUERIED_ATTRIBUTE_NAME, "true")
    callback(element)

    // run reset after 2 seconds
    if (!finalOptions.findOnce) {
      setTimeout(() => {
        element.removeAttribute(QUERIED_ATTRIBUTE_NAME)
      }, 2000)
    }
  }
}

/**
 * Wait for elements with a given CSS selector to enter the DOM. Returns a `Promise`
 * resolving with found/changed element and triggers a callback for every found/changed
 * element.
 *
 * @param {string} selector
 * @param {OnElementReadyOptions} [options]
 * @param {OnElementReadyCallback} [callback]
 * @returns {OnElementReadyReturn}
 * @public
 */
// eslint-disable-next-line prefer-const
let onElementReady = (selector, options = DEFAULT_OPTIONS, callback = () => {}) => {
  const finalOptions = { ...DEFAULT_OPTIONS, ...options }

  return new Promise((resolve) => {
    // Initial Query
    queryForElements(selector, finalOptions, (element) => {
      resolve(element)
      callback(element)
    })

    // Continuous Query
    const observer = new MutationObserver(() => {
      // DOM Changes detected
      queryForElements(selector, finalOptions, (element) => {
        resolve(element)
        callback(element)

        // stop querying after first successful pass and remove mutation observer,
        // calling multiple times (when mutliple matching elements) seems to work fine
        if (finalOptions.findFirst) {
          observer.disconnect()
        }
      })
    })

    // Observe DOM Changes
    observer.observe(document.documentElement, {
      attributes: false,
      childList: true,
      subtree: true,
    })
  })
}

/**
 * @deprecated
 * @param {string} selector
 * @param {OnElementReadyCallback} [callback]
 * @param {OnElementReadyOptions} [options]
 * @returns {OnElementReadyReturn}
 * @public
 */
// eslint-disable-next-line no-unused-vars, prefer-const
let waitForKeyElements = (selector, callback, options) =>
  onElementReady(selector, options, callback)