Greasy Fork

Greasy Fork is available in English.

[MWI]Marketplace Order Book Button Disabler

Disable and gray out buttons in MarketplacePanel_orderBook containers with dynamic content handling

当前为 2025-05-11 提交的版本,查看 最新版本

// ==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
// ==/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();
})();