// ==UserScript== // @name [MWI]Marketplace Order Book Button Disabler // @name:zh-CN [银河奶牛]市场订单簿按钮禁用器 // @namespace https://cnb.cool/shenhuanjie/skyner-cn/tamper-monkey-script/mwi-orderbook-button-disabler // @version 1.0.0 // @description Disable and gray out buttons in MarketplacePanel_orderBook containers with dynamic content handling // @description:zh-CN 禁用并灰化市场订单簿面板中的按钮,支持动态内容处理 // @author shenhuanjie // @license MIT // @match https://www.milkywayidle.com/game* // @icon https://www.milkywayidle.com/favicon.svg // @grant none // @homepage https://cnb.cool/shenhuanjie/skyner-cn/tamper-monkey-script/mwi-orderbook-button-disabler // @supportURL https://cnb.cool/shenhuanjie/skyner-cn/tamper-monkey-script/mwi-orderbook-button-disabler // @run-at document-idle // @require https://cdn.tailwindcss.com // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 配置选项 const config = { containerSelector: 'div[class*="MarketplacePanel_orderBook"]', buttonSelector: 'button', logPrefix: '[OrderBookDisabler]', disabledClass: 'orderbook-disabled', mutationDebounce: 300, // 突变事件防抖时间(毫秒) maxScanDepth: 3 // 递归扫描DOM树的最大深度 }; // 样式定义 const style = document.createElement('style'); style.textContent = ` .${config.disabledClass} { opacity: 0.5 !important; cursor: not-allowed !important; pointer-events: none !important; background-color: #e0e0e0 !important; color: #888 !important; border-color: #ccc !important; filter: grayscale(100%); transition: all 0.3s ease; } `; document.head.appendChild(style); // 日志函数 function log(...args) { console.log(config.logPrefix, ...args); } // 错误处理函数 function handleError(error) { console.error(config.logPrefix, 'Error:', error); } // 防抖函数 function debounce(func, delay) { let timeout; return function() { const context = this; const args = arguments; clearTimeout(timeout); timeout = setTimeout(() => func.apply(context, args), delay); }; } // 递归扫描DOM节点 function scanNode(node, depth = 0) { if (depth > config.maxScanDepth) return 0; let count = 0; // 如果是目标容器,处理其内部按钮 if (node.matches && node.matches(config.containerSelector)) { const buttons = node.querySelectorAll(config.buttonSelector); buttons.forEach(button => { if (!button.classList.contains(config.disabledClass)) { button.disabled = true; button.classList.add(config.disabledClass); count++; log('已禁用动态加载的按钮:', button.textContent.trim()); } }); } // 递归处理子节点 if (node.children) { for (const child of node.children) { count += scanNode(child, depth + 1); } } return count; } // 处理DOM变化 const handleMutations = debounce(mutationsList => { try { let totalNewButtons = 0; for (const mutation of mutationsList) { // 处理新增节点 if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { for (const addedNode of mutation.addedNodes) { if (addedNode.nodeType === 1) { // 元素节点 totalNewButtons += scanNode(addedNode); } } } // 处理属性变化 if (mutation.type === 'attributes' && mutation.attributeName === 'class') { const target = mutation.target; if (target.matches && target.matches(config.containerSelector)) { const buttons = target.querySelectorAll(config.buttonSelector); buttons.forEach(button => { if (!button.classList.contains(config.disabledClass)) { button.disabled = true; button.classList.add(config.disabledClass); totalNewButtons++; log('已禁用属性变化后匹配的按钮:', button.textContent.trim()); } }); } } } if (totalNewButtons > 0) { log(`处理DOM变化: 新增 ${totalNewButtons} 个禁用按钮`); } } catch (error) { handleError(error); } }, config.mutationDebounce); // 初始化函数 function init() { try { log('脚本已启动,正在监听DOM变化...'); // 初始扫描 const startTime = performance.now(); const initialButtons = document.querySelectorAll(`${config.containerSelector} ${config.buttonSelector}`); let initialCount = 0; initialButtons.forEach(button => { if (!button.classList.contains(config.disabledClass)) { button.disabled = true; button.classList.add(config.disabledClass); initialCount++; } }); const endTime = performance.now(); log(`初始扫描: 已禁用 ${initialCount} 个按钮 (耗时: ${(endTime - startTime).toFixed(2)}ms)`); // 设置MutationObserver监听DOM变化 const observer = new MutationObserver(handleMutations); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['class'] }); log('已设置DOM变化监听'); // 页面加载完成后再次检查 window.addEventListener('load', () => { const loadTimeButtons = document.querySelectorAll(`${config.containerSelector} ${config.buttonSelector}`); let loadTimeCount = 0; loadTimeButtons.forEach(button => { if (!button.classList.contains(config.disabledClass)) { button.disabled = true; button.classList.add(config.disabledClass); loadTimeCount++; } }); if (loadTimeCount > 0) { log(`页面加载完成后: 新增 ${loadTimeCount} 个禁用按钮`); } }); } catch (error) { handleError(error); } } // 启动脚本 init(); })();