您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
helper functions, intersection & mutation observers, lazyloader
当前为
// ==UserScript== // @name utils // @description helper functions, intersection & mutation observers, lazyloader // @namespace http://tampermonkey.net/ // @author smartacephale // @license MIT // @version 1.3.1 // @match *://*/* // ==/UserScript== function findNextSibling(el) { if (el.nextElementSibling) return el.nextElementSibling; if (el.parentElement) return findNextSibling(el.parentElement); return null; } function parseDOM(html) { const parsed = new DOMParser().parseFromString(html, 'text/html').body; return parsed.children.length > 1 ? parsed : parsed.firstElementChild; } const MOBILE_UA = [ 'Mozilla/5.0 (Linux; Android 10; K)', 'AppleWebKit/537.36 (KHTML, like Gecko)', 'Chrome/114.0.0.0 Mobile Safari/537.36'].join(' '); function fetchCustomUA(url, ua = MOBILE_UA) { const headers = new Headers({ "User-Agent": ua }); return fetch(url, { headers }); } function fetchMobHtml(url) { return fetchCustomUA(url).then((r) => r.text()).then((h) => parseDOM(h)); } function fetchHtml(url) { return fetch(url).then((r) => r.text()).then((h) => parseDOM(h)); } function timeToSeconds(t) { return (t.match(/\d+/gm) || ['0']) .reverse() .map((s, i) => parseInt(s) * 60 ** i) .reduce((a, b) => a + b) || 0; } function parseIntegerOr(n, or) { return Number.isInteger(parseInt(n)) ? parseInt(n) : or; } function stringToWords(s) { return s.split(",").map(s => s.trim().toLowerCase()).filter(_ => _); } function parseCSSUrl(s) { return s.replace(/url\("|\"\).*/g, ''); } function circularShift(n, c = 6, s = 1) { return (n + s) % c || c; } function range(size, startAt = 1) { return [...Array(size).keys()].map(i => i + startAt); } function listenEvents(dom, events, callback) { for (const e of events) { dom.addEventListener(e, callback, true); } } class Observer { constructor(callback) { this.callback = callback; this.observer = new IntersectionObserver(this.handleIntersection.bind(this)); } observe(target) { this.observer.observe(target); } throttle(target, throttleTime) { this.observer.unobserve(target); setTimeout(() => this.observer.observe(target), throttleTime); } handleIntersection(entries) { for (const entry of entries) { if (entry.isIntersecting) { this.callback(entry.target); } } } static observeWhile(target, callback, throttleTime) { const observer_ = new Observer(async (target) => { const condition = await callback(); if (condition) observer_.throttle(target, throttleTime); }); observer_.observe(target); return observer_; } } class LazyImgLoader { constructor(callback, attributeName = 'data-lazy-load', removeTagAfter = true) { this.attributeName = attributeName; this.removeTagAfter = removeTagAfter; this.lazyImgObserver = new Observer((target) => { callback(target, this.delazify); }); } lazify(target, img, imgSrc) { if (!img || !imgSrc) return; img.setAttribute(this.attributeName, imgSrc); img.src = ''; this.lazyImgObserver.observe(img); } delazify = (target) => { this.lazyImgObserver.observer.unobserve(target); target.src = target.getAttribute(this.attributeName); if (this.removeTagAfter) target.removeAttribute(this.attributeName); } static create(callback) { const lazyImgLoader = new LazyImgLoader((target, delazify) => { if (callback(target)) { delazify(target); } }); return lazyImgLoader; } } function waitForElementExists(parent, selector, callback) { const observer = new MutationObserver((mutations) => { const el = parent.querySelector(selector); if (el) { observer.disconnect(); callback(el); } }); observer.observe(document.body, { childList: true, subtree: true }); } function watchElementChildrenCount(element, callback) { let count = element.children.length; const observer = new MutationObserver((mutationList, observer) => { for (const mutation of mutationList) { if (mutation.type === "childList") { if (count !== element.children.length) { count = element.children.length; callback(observer, count); } } } }); observer.observe(element, { childList: true }); } function watchDomChangesWithThrottle(element, callback, throttle = 1000, options = { childList: true, subtree: true, attributes: true }) { let lastMutationTime; let timeout; const observer = new MutationObserver((mutationList, observer) => { const now = Date.now(); if (lastMutationTime && now - lastMutationTime < throttle) { timeout && clearTimeout(timeout); } timeout = setTimeout(callback, throttle); lastMutationTime = now; }); observer.observe(element, options); } class Tick { constructor(delay, startImmediate = true) { this.tick = null; this.delay = delay; this.startImmediate = startImmediate; } start(callback, callbackFinal = null) { this.stop(); this.callbackFinal = callbackFinal; if (this.startImmediate) callback(); this.tick = setInterval(callback, this.delay); } stop() { if(this.tick !== null) { clearInterval(this.tick); this.tick = null; } if (this.callbackFinal) { this.callbackFinal(); this.callbackFinal = null; } } } function copyAttributes(target, source) { for (const attr of source.attributes) { target.setAttribute(attr.nodeName, attr.nodeValue); } } function replaceElementTag(e, tagName) { const newTagElement = document.createElement(tagName); copyAttributes(newTagElement, e); newTagElement.innerHTML = e.innerHTML; e.parentNode.replaceChild(newTagElement, e); } function getAllUniqueParents(elements) { return Array.from(elements).reduce((acc, v) => acc.includes(v.parentElement) ? acc : [...acc, v.parentElement], []); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址