Greasy Fork

Greasy Fork is available in English.

yssWaitForNode

Be smart!

当前为 2022-11-22 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/454354/1120016/yssWaitForNode.js

// ==UserScript==
// @name         yssWaitForNode
// @namespace    https://ysslang.com/
// @version      1.1.3
// @description  Be smart!
// @author       ysslang
// @match        *://*/*
// @note         http://greasyfork.icu/scripts/454354
// @grant        none
// ==/UserScript==

class WaitForNode {
  #currentURL;
  #observerList = [];
  #waitList = [];

  constructor() { this.#currentURL = window.location.href; }

  #checkIfUrlMatch(matcher) {
    if (matcher === undefined || matcher === null) return false;
    if (typeof matcher === "string") return new RegExp(matcher.trim()).test(this.#currentURL);
    if (matcher instanceof RegExp) return matcher.test(this.#currentURL);
    return false;
  }

  #determineParentElement(arg) {
    if (typeof arg === "string") return document.querySelector(arg) || document.body;
    else if (arg instanceof Element) return arg;
    else return document.body;
  }

  #mergeOptions(options) {
    options = options || {};
    var parentEl = this.#determineParentElement(options.parent);
    return {
      immediate: [options.immediate, options.imdt].find((e) => e) || true,
      recursive: [options.recursive, options.rcs].find((e) => e) || true,
      once: [options.once].find((e) => e) || false,
      subtree: [options.subtree, options.sbt].find((e) => e) || true,
      childList: [options.childList, options.cld].find((e) => e) || true,
      parentEl: parentEl,
    };
  }

  #extractMatchedElements(mutations, selector, recursive) {
    const matchedElements = [];
    for (const { addedNodes } of mutations) {
      for (const node of addedNodes) {
        if (!node.tagName)  continue;
         else if (node.matches(selector)) matchedElements.push(node);
         else if (recursive && node.firstElementChild) matchedElements.push(...node.querySelectorAll(selector));
         } }
    return matchedElements;
  }
  
  add(name, url, selector, callback, options) {
    var urls = Array.isArray(url) ? url : [url];
    if (!urls.some(this.#checkIfUrlMatch, this)) return;
    this.on(selector, callback, this.#mergeOptions(options));
  }


  on(selector, callback, options) {
    if (options.immediate) {
      [...options.parentEl.querySelectorAll(selector)].forEach(callback);
    }
    const observer = new MutationObserver((mutations) => {
      var elements = this.#extractMatchedElements(mutations, selector, options.recursive);
      elements.forEach(callback);
      if (elements && options.once) this.disconnect();
    });
    observer.observe(options.parentEl, { subtree: options.subtree, childList: options.childList, });
    this.#observerList.push(observer);
  }

  stopAll() {
    while (this.#observerList.length) this.#observerList.pop().disconnect();
  }
}

var WFN = new WaitForNode();