onElementReady

detect when an element is ready

Этот скрипт недоступен для установки пользователем. Он является библиотекой, которая подключается к другим скриптам мета-ключом // @require https://update.greasyfork.org/scripts/419640/1776135/onElementReady.js

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==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)