您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Suppress default previews, persistent “You” highlight dropdown, and Q‑key Quick‑Reply for holotower.org.
当前为
// ==UserScript== // @name Holotower Custom Fixes // @namespace http://holotower.org/ // @version 1.0 // @author /hlgg/ // @license MIT // @description Suppress default previews, persistent “You” highlight dropdown, and Q‑key Quick‑Reply for holotower.org. // @icon https://boards.holotower.org/favicon.gif // @match *://boards.holotower.org/* // @match *://holotower.org/* // @grant GM_addStyle // @run-at document-end // ==/UserScript== (function() { 'use strict'; // -------------------------------------------------------------------------- // 1) Hide the site's built-in hover previews // We only want our custom iq-preview-* popups to show. // -------------------------------------------------------------------------- GM_addStyle(` /* Any .qp element that does NOT have an id starting with "iq-preview-" will be hidden */ div.qp:not([id^="iq-preview-"]) { display: none !important; } `); // -------------------------------------------------------------------------- // 2) Prepare a <style> tag to hold our dynamic "You" highlighting rules // We'll update its contents when the user picks a new border style. // -------------------------------------------------------------------------- const youStyleEl = document.createElement('style'); youStyleEl.id = 'you-custom-style'; document.head.appendChild(youStyleEl); // Key under which we store the user's chosen border style in localStorage const STORAGE_KEY = 'youBorderStyle'; const DEFAULT_STYLE = 'dashed'; /** * Writes CSS into our <style> tag to highlight posts: * - Blue left-border for your own replies (.you) * - Red left-border for replies quoting you (.quoting-you) * @param {string} style - the CSS border-style (e.g., solid, dashed) */ function updateYouBorder(style) { youStyleEl.textContent = ` /* Own posts: add blue border */ div.post.reply.you:has(span.own_post) { border-left: 5px ${style} #00b8e6 !important; } /* Replies quoting you: add red border */ div.post.reply.quoting-you { border-left: 5px ${style} #ff3d3d !important; } /* Re-add "(You)" text after the quote link */ div.post.reply.quoting-you a:has(+ small)::after { content: " (You)" !important; } /* Hide any original small "(You)" or embed placeholders */ div.post.reply div.body a + small, div.post.reply div.body span.embed-container { display: none !important; } `; // Save the user's choice so it persists across reloads try { localStorage.setItem(STORAGE_KEY, style); } catch (e) { // localStorage may not be available; ignore errors } } // -------------------------------------------------------------------------- // 3) Create and insert a dropdown UI for the user to select their border style // -------------------------------------------------------------------------- const container = document.createElement('div'); container.style.cssText = 'float:right; margin-bottom:10px'; container.innerHTML = ` Border style: <select id="youBorderSelector"> <option value="solid">solid</option> <option value="dashed">dashed</option> <option value="dotted">dotted</option> <option value="double">double</option> <option value="groove">groove</option> <option value="ridge">ridge</option> </select> `; // Insert our dropdown before the existing #style-select element (site's theme selector) const styleSelect = document.getElementById('style-select'); if (styleSelect && styleSelect.parentNode) { styleSelect.parentNode.insertBefore(container, styleSelect); } // Initialize dropdown value from localStorage (or default) const dropdown = document.getElementById('youBorderSelector'); const saved = localStorage.getItem(STORAGE_KEY); const initial = saved && dropdown.querySelector(`option[value="${saved}"]`) ? saved : DEFAULT_STYLE; dropdown.value = initial; updateYouBorder(initial); // Update the border style whenever the user picks a new option dropdown.addEventListener('change', e => updateYouBorder(e.target.value)); // -------------------------------------------------------------------------- // 4) JavaScript marking of posts with "you" and "quoting-you" classes // .you => posts authored by you // .quoting-you => replies that quote "(You)" // -------------------------------------------------------------------------- /** * Scans the given root (default: whole document) and adds classes: * - "you" to posts containing <span class="own_post"> * - "quoting-you" to posts containing a <small> with text "(You)" */ function markYou(root = document.body) { // Mark own posts root.querySelectorAll('div.post.reply span.own_post') .forEach(el => el.closest('div.post.reply')?.classList.add('you')); // Mark replies quoting you root.querySelectorAll('div.post.reply .body small') .forEach(sm => { if (sm.textContent.trim() === '(You)') { sm.closest('div.post.reply')?.classList.add('quoting-you'); } }); } // Initial pass on page load markYou(); // Observe for new or inlined replies to apply marking new MutationObserver(muts => { muts.forEach(m => { m.addedNodes.forEach(n => { if (n.nodeType === 1) markYou(n); }); }); }).observe(document.body, { childList: true, subtree: true }); // -------------------------------------------------------------------------- // 5) Q-key Quick‑Reply toggle and auto-focus on citeReply links // -------------------------------------------------------------------------- /** * Toggles the Quick‑Reply panel when the user presses 'q' (unless typing in a form). */ function onKey(e) { if (e.key.toLowerCase() !== 'q' || e.ctrlKey || e.altKey || e.metaKey) return; // If the user is typing into an input or textarea, do nothing const active = document.activeElement; const nm = active?.getAttribute('name'); if (active?.tagName === 'TEXTAREA' || (active?.tagName === 'INPUT' && ['name','email','subject','embed'].includes(nm))) { return; } const form = document.getElementById('quick-reply'); if (form && form.style.display !== 'none') { // Close Quick‑Reply if it's open form.querySelector('.close-btn')?.click(); } else { // Otherwise open it and focus the textarea document.querySelector('.quick-reply-btn')?.click(); setTimeout(() => { document.querySelector('#quick-reply textarea[name="body"]')?.focus(); }, 50); } e.preventDefault(); } // Capture keydown at the documentElement level to override site handlers document.documentElement.addEventListener('keydown', onKey, true); // When clicking on a post_no link (citeReply), auto-focus the textarea document.body.addEventListener('click', e => { const link = e.target.closest('a.post_no'); if (link && /^citeReply\(\d+\)$/.test(link.getAttribute('onclick') || '')) { setTimeout(() => { const ta = document.querySelector('#quick-reply textarea[name="body"]'); if (ta) { ta.focus(); ta.setSelectionRange(ta.value.length, ta.value.length); } }, 50); } }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址