您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Be smart!
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/454354/1145153/yssWaitForNode.js
// ==UserScript== // @name yssWaitForNode // @namespace https://ysslang.com/ // @version 1.2.4.1 // @description Be smart! // @author ysslang // @match *://*/* // @supportURL https://greasyfork.org/scripts/454354 // @run-at document-start // @grant none // ==/UserScript== /* Done - 去除返回元素中的重复元素, 避免重复执行; bugfix: 忘记加const了; */ class WaitForNode { #currentURL; #observerList = []; #waitList = []; constructor() { this.#currentURL = window.location.href; } #checkIfUrlMatch(matcher) { var result = false; if (matcher === undefined || matcher === null) result = false; if (typeof matcher === "string") result = new RegExp(matcher.trim()).test(this.#currentURL); if (matcher instanceof RegExp) result = matcher.test(this.#currentURL); return result; } #determineParentElement(arg) { var result = document; if (typeof arg === "string" && document.querySelector(arg)) result = document.querySelector(arg); if (arg instanceof Element) result = arg; return result; } #mergeOptions(options) { options = options || {}; var result = { immediate: [options.immediate, options.imdt, true].find((e) => typeof (e) !== 'undefined'), recursive: [options.recursive, options.rcs, true].find((e) => typeof (e) !== 'undefined'), once: [options.once, false].find((e) => typeof (e) !== 'undefined'), subtree: [options.subtree, options.sbt, true].find((e) => typeof (e) !== 'undefined'), childList: [options.childList, options.cld, true].find((e) => typeof (e) !== 'undefined'), parentEl: this.#determineParentElement(options.parent), }; return result; } #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)); } } const result = [...new Set(matchedElements)] return result; } #on(selector, callback, options) { if (options.immediate) { [...options.parentEl.querySelectorAll(selector)].forEach(callback); } const observer = new MutationObserver((mutations) => { const 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); window.x = observer; return observer; } #injectStyle(styleString) { const style = document.createElement('style'); style.textContent = styleString; return document.head.append(style); } add(name, url, selector, callback, options) { if (url === '') url = ['.*']; const urls = Array.isArray(url) ? url : [url]; if (!urls.some(this.#checkIfUrlMatch, this)) return; const opts = this.#mergeOptions(options); const observer = this.#on(selector, callback, opts); this.#waitList.push({ 'name': name, 'url': url, 'selector': selector, 'callback': callback, 'options': opts, 'observer': observer }); } batchAdd(name, url, lists, para4, para5) { const callback = typeof para4 === 'function' ? para4 : (typeof para5 === 'function' ? para5 : undefined); const options = typeof para4 === 'object' ? para4 : (typeof para5 === 'object' ? para5 : undefined) lists.forEach((p) => { if (!p.find(pp => typeof pp === 'function')) { if (p.length === 1) this.add(name, url, p[0], callback, options); else if (p.length === 2) this.add(`${name}-${p[0]}`, url, p[1], callback, options); } else if (typeof p[1] === 'function') this.add(name, url, p[0], p[1], p[2] || options); else if (typeof p[2] === 'function') this.add(`${name}-${p[0]}`, url, p[1], p[2], p[3] || options); else if (typeof p[3] === 'function') this.add(`${name}-${p[0]}`, p[1], p[2], p[3], p[4] || options); else return; }) } addCss(name, url, cssString) { if (url === '') url = ['.*']; const urls = Array.isArray(url) ? url : [url]; if (!urls.some(this.#checkIfUrlMatch, this)) return; this.#injectStyle(cssString); } stopAll() { while (this.#observerList.length) this.#observerList.pop().disconnect(); } } const WFN = new WaitForNode();