您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
async requre element
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/448197/1072378/ElementGetter.js
// ==UserScript== // @name ElementGetter // @author cxxjackie // @version 1.0.0 // ==/UserScript== class ElementGetter { #window; #matchesSelector; #mutationObserver; #addListener; #listeners; #addObserver(target, callback) { const observer = new this.#mutationObserver(mutations => { for (const mutation of mutations) { for (const addedNode of mutation.addedNodes) { if (observer.canceled) return; callback(addedNode); } } }); observer.canceled = false; observer.observe(target, { childList: true, subtree: true }); return function() { observer.canceled = true; observer.disconnect(); }; } #addEvent(target, callback) { const listener = e => callback(e.target); target.addEventListener('DOMNodeInserted', listener); return function() { target.removeEventListener('DOMNodeInserted', listener); }; } #addFilter(target, filter) { if (this.#listeners.has(target)) { const listener = this.#listeners.get(target); listener.filters.push(filter); } else { const removeFunc = this.#addListener(target, node => { if (node instanceof Element) { listener.filters.forEach(f => f(node)); } }); const listener = { filters: [filter], remove: removeFunc }; this.#listeners.set(target, listener); } } #removeFilter(target, filter) { if (!this.#listeners.has(target)) return; const listener = this.#listeners.get(target); const index = listener.filters.indexOf(filter); listener.filters.splice(index, 1); if (listener.filters.length === 0) { listener.remove(); this.#listeners.delete(target); } } #getOne(selector, parent, timeout) { return new Promise(resolve => { const result = parent.querySelector(selector); if (result) return resolve(result); let timer; const filter = node => { const isMatches = this.#matchesSelector.call(node, selector); const result = isMatches ? node : node.querySelector(selector); if (result) { this.#removeFilter(parent, filter); timer && clearTimeout(timer); resolve(result); } }; this.#addFilter(parent, filter); if (timeout > 0) { timer = setTimeout(() => { this.#removeFilter(parent, filter); resolve(null); }, timeout); } }); } #getAll(selectorList, parent, timeout) { const promiseList = []; for (const selector of selectorList) { promiseList.push(this.#getOne(selector, parent, timeout)); } return Promise.all(promiseList); } constructor() { this.#window = window.unsafeWindow || document.defaultView || window; const elmProto = this.#window.Element.prototype; this.#matchesSelector = elmProto.matches || elmProto.matchesSelector || elmProto.webkitMatchesSelector || elmProto.msMatchesSelector || elmProto.mozMatchesSelector; this.#mutationObserver = this.#window.MutationObserver || this.#window.WebkitMutationObserver || this.#window.MozMutationObserver; this.#addListener = this.#mutationObserver ? this.#addObserver : this.#addEvent; this.#listeners = new WeakMap(); } get(selector, parent = this.#window.document, timeout = 0) { if (typeof selector === 'string' || selector instanceof String) { return this.#getOne(selector, parent, timeout); } else if (selector instanceof Array) { return this.#getAll(selector, parent, timeout); } else { return Promise.resolve(null); } } each(selector, parent, callback) { let removed = false; const handle = { remove: () => { removed = true; } }; setTimeout(() => { const elms = parent.querySelectorAll(selector); for (const elm of elms) { callback(elm, false); if (removed) return; } const removeFunc = this.#addListener(parent, node => { if (node instanceof Element) { let elms = node.querySelectorAll(selector); if (this.#matchesSelector.call(node, selector)) { elms = [node, ...elms]; } for (const elm of elms) { callback(elm, true); if (removed) return; } } }); handle.remove = () => { removed = true; removeFunc(); }; }, 0); return handle; } remove(handle) { handle && handle.remove(); } create(domString) { const template = this.#window.document.createElement('template'); template.innerHTML = domString; const node = template.content.firstElementChild || template.content.firstChild; node.remove(); return node; } }