您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Prevent highlighting on manga sites like WeebCentral
// ==UserScript== // @name Prevent highlighting on photos // @namespace http://tampermonkey.net/ // @version 0.0.1 // @description Prevent highlighting on manga sites like WeebCentral // @author You // @match https://weebcentral.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=create.t3.gg // @grant none // @license GNU GPLv3 // ==/UserScript== (() => { let enabled = true; const STYLE_ID = "tm-no-select-style"; // CSS that blocks selection everywhere except form/editable elements const css = ` html, body, * { -webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; } input, textarea, select, [contenteditable=""], [contenteditable="true"] { -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; user-select: text !important; } `; const eventsToBlock = [ "selectstart", // text selection start "dragstart", // double-click + drag "mousedown", // some sites use this to trigger selection "pointerdown", // pointer-based selection "dblclick", // double-click selection ]; // Add a style element to a (shadow) root function injectStyleInto(root) { if (!root || !root.ownerDocument) return; const doc = root.ownerDocument; // Avoid duplicates per root const existing = [ ...(root.querySelectorAll ? root.querySelectorAll(`#${STYLE_ID}`) : []), ].length; if (existing) return; const style = doc.createElement("style"); style.id = STYLE_ID; style.textContent = css; (root.head || root).appendChild(style); } // Attach event blockers at the root level function attachEventBlockers(target) { eventsToBlock.forEach((evt) => { target.addEventListener(evt, onBlocker, { capture: true, passive: false, }); }); } // Permit selection inside form/editable controls function isEditable(el) { if (!el) return false; if (el.closest("input, textarea, select")) return true; const ce = el.closest("[contenteditable]"); return ( ce && (ce.getAttribute("contenteditable") === "" || ce.getAttribute("contenteditable") === "true") ); } function onBlocker(e) { if (!enabled) return; if (isEditable(e.target)) return; e.stopPropagation(); e.preventDefault(); } // Process the main document and any existing shadow roots function processDocument(doc = document) { injectStyleInto(doc); attachEventBlockers(doc); // Walk the tree to find shadow roots already attached const walker = doc.createTreeWalker(doc, NodeFilter.SHOW_ELEMENT); let node; while ((node = walker.nextNode())) { if (node.shadowRoot) { processShadowRoot(node.shadowRoot); } } } // Handle a shadow root function processShadowRoot(sr) { injectStyleInto(sr); attachEventBlockers(sr); } // Intercept future shadow roots const origAttachShadow = Element.prototype.attachShadow; Element.prototype.attachShadow = function (init) { const sr = origAttachShadow.call(this, init); // Process after creation queueMicrotask(() => processShadowRoot(sr)); return sr; }; // Observe added elements to catch closed-over cases where styles might be removed const mo = new MutationObserver((muts) => { if (!enabled) return; for (const m of muts) { if (m.type === "childList") { m.addedNodes.forEach((n) => { // Re-inject style into document if removed if (n.nodeType === 1) { const el = /** @type {Element} */ (n); // If a <style> got removed elsewhere, ensure one exists if (!document.getElementById(STYLE_ID)) injectStyleInto(document); // Shadow roots on newly added custom elements (if any) get handled by attachShadow hook } }); } } }); function enable() { enabled = true; injectStyleInto(document); attachEventBlockers(document); } function disable() { enabled = false; } // Keyboard toggle: Ctrl + Alt + U window.addEventListener( "keydown", (e) => { if (e.ctrlKey && e.altKey && (e.key === "u" || e.key === "U")) { enabled ? disable() : enable(); // Optional toast try { const msg = `No-select: ${enabled ? "ON" : "OFF"}`; console.log(msg); } catch {} e.preventDefault(); e.stopPropagation(); } }, { capture: true } ); // Initialize if (document.readyState === "loading") { // document-start, but DOM not ready yet processDocument(document); } else { processDocument(document); } mo.observe(document.documentElement || document, { childList: true, subtree: true, }); })();