Observe

Observe and wait for elements

当前为 2025-10-11 提交的版本,查看 最新版本

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

// ==UserScript==
// @name         Observe
// @license      MIT
// @version      1.2
// @description  Observe and wait for elements
// @author       tukars
// @match        *://*/*
// ==/UserScript==

(function () {
  // Define the namespace structure
  const NAMESPACE_ROOT = "userscript";
  const NAMESPACE_DOMAIN = "com";
  const NAMESPACE_AUTHOR = "tukars";
  const NAMESPACE_LIB_NAME = "Observe";

  window[NAMESPACE_ROOT] = window[NAMESPACE_ROOT] || {};
  window[NAMESPACE_ROOT][NAMESPACE_DOMAIN] =
    window[NAMESPACE_ROOT][NAMESPACE_DOMAIN] || {};
  window[NAMESPACE_ROOT][NAMESPACE_DOMAIN][NAMESPACE_AUTHOR] =
    window[NAMESPACE_ROOT][NAMESPACE_DOMAIN][NAMESPACE_AUTHOR] || {};

  if (
    window[NAMESPACE_ROOT][NAMESPACE_DOMAIN][NAMESPACE_AUTHOR][
      NAMESPACE_LIB_NAME
    ]
  ) {
    return;
  }

  const timeStamp = function () {
    const now = new Date();
    const pad = (num, size) => String(num).padStart(size, "0");

    const hours = pad(now.getHours(), 2);
    const minutes = pad(now.getMinutes(), 2);
    const seconds = pad(now.getSeconds(), 2);
    const milliseconds = pad(now.getMilliseconds(), 3);

    return `${hours}:${minutes}:${seconds}.${milliseconds}`;
  };

  const contextPrint = function (message, ENABLE_DEBUG_LOGGING) {
    const messageTime = () => `[${message}] ${timeStamp()} -`;

    const log = function (...args) {
      console.log(messageTime(), ...args);
    };
    const warn = function (...args) {
      console.warn(messageTime(), ...args);
    };
    const error = function (...args) {
      console.error(messageTime(), ...args);
    };
    const info = function (...args) {
      console.info(messageTime(), ...args);
    };
    var debug = function (...args) {
      console.debug(messageTime(), ...args);
    };
    if (!ENABLE_DEBUG_LOGGING) {
      debug = function () {};
    }

    return { log, warn, error, info, debug };
  };

  const observeChildren = function (element, config, callback) {
    const observer = new MutationObserver((mutationsList) => {
      for (const mutation of mutationsList) {
        if (mutation.type === "childList") {
          callback(Array.from(mutation.addedNodes));
        }
      }
    });
    const use_config = config || { childList: true, subtree: false };
    observer.observe(element, use_config);
    return observer;
  };

  const observeChildrenWithFilter = function (element, config, filter, callback) {
    return observeChildren(element, config, (addedNodes) =>
      callback(addedNodes.filter(filter))
    );
  };

  const observeChildrenWithTags = function (element, config, filterTags, callback) {
    return observeChildrenWithFilter(
      element,
      config,
      (node) =>
        node.nodeType === Node.ELEMENT_NODE &&
        filterTags.includes(node.tagName.toLowerCase()),
      callback
    );
  };

  const observeAndHandle = function (element, tags, fun, config) {
    const use_config = config || { childList: true, subtree: true };
    observeChildrenWithTags(element, use_config, tags, (nodes) =>
      nodes.forEach((node) => fun(node))
    );
  };

  function waitForElement(selector, callback) {
    const element = document.querySelector(selector);
    if (element) {
      callback(element);
    } else {
      const observer = new MutationObserver((_, obs) => {
        const el = document.querySelector(selector);
        if (el) {
          obs.disconnect();
          callback(el);
        }
      });
      observer.observe(document.body, { childList: true, subtree: true });
    }
  }

  window[NAMESPACE_ROOT][NAMESPACE_DOMAIN][NAMESPACE_AUTHOR][NAMESPACE_LIB_NAME] =
    {
      timeStamp,
      contextPrint,
      observeChildren,
      observeChildrenWithFilter,
      observeChildrenWithTags,
      observeAndHandle,
      waitForElement,
    };
})();