自动点击菜单

添加菜单,允许用户指定ID或类名进行自动点击,并基于网址保存不同选项

目前为 2024-07-15 提交的版本。查看 最新版本

// ==UserScript==
// @name         自动点击菜单
// @namespace    http://tampermonkey.net/
// @version      2024-07-15-1
// @description  添加菜单,允许用户指定ID或类名进行自动点击,并基于网址保存不同选项
// @author       YuoHira
// @license      MIT
// @match        *://*/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=github.io
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';

    window.onload = function() {
        // 获取根网址
        const currentUrl = window.location.origin;
        let autoClickEnabled = GM_getValue(`${currentUrl}_autoClickEnabled`, false);

        // 创建收起/展开按钮
        const toggleButton = document.createElement('button');
        toggleButton.innerText = '>';
        toggleButton.style.position = 'fixed';
        toggleButton.style.top = '10px';
        toggleButton.style.right = '10px';
        toggleButton.style.zIndex = '10001';
        toggleButton.style.backgroundColor = 'white';
        toggleButton.style.border = '1px solid #ccc';
        toggleButton.style.padding = '0';
        toggleButton.style.width = '10px';
        toggleButton.style.height = '10px';
        toggleButton.style.lineHeight = '10px';
        toggleButton.style.fontSize = '10px';
        toggleButton.style.cursor = 'pointer';
        document.body.appendChild(toggleButton);

        // 创建菜单容器
        const menuContainer = document.createElement('div');
        menuContainer.style.position = 'fixed';
        menuContainer.style.top = '10px';
        menuContainer.style.right = '10px';
        menuContainer.style.backgroundColor = 'white';
        menuContainer.style.border = '1px solid #ccc';
        menuContainer.style.padding = '10px';
        menuContainer.style.zIndex = '10000';
        menuContainer.style.display = 'none'; // 默认收起状态
        document.body.appendChild(menuContainer);

        // 添加标题
        const menuTitle = document.createElement('h3');
        menuTitle.innerText = '自动点击菜单';
        menuTitle.style.margin = '0';
        menuTitle.style.padding = '0';
        menuContainer.appendChild(menuTitle);

        // 添加应用按钮
        const applyButton = document.createElement('button');
        applyButton.innerText = '应用';
        menuContainer.appendChild(applyButton);

        // 添加加号按钮
        const addButton = document.createElement('button');
        addButton.innerText = '+';
        menuContainer.appendChild(addButton);

        // 添加开始/暂停按钮
        const toggleAutoClickButton = document.createElement('button');
        toggleAutoClickButton.innerText = autoClickEnabled ? '暂停' : '开始';
        menuContainer.appendChild(toggleAutoClickButton);

        // 输入框容器
        const inputContainer = document.createElement('div');
        menuContainer.appendChild(inputContainer);

        // 加载保存的数据
        function loadSavedData() {
            const savedData = GM_getValue(currentUrl, []);
            savedData.forEach(item => {
                addInputField(item.type, item.value);
            });
        }

        // 保存当前输入的数据
        function saveData() {
            const data = [];
            const inputs = inputContainer.getElementsByTagName('input');
            for (let i = 0; i < inputs.length; i++) {
                const input = inputs[i];
                const select = input.previousSibling;
                data.push({ type: select.value, value: input.value });
            }
            GM_setValue(currentUrl, data);
        }

        // 手动选取页面元素
        function selectElement(event, input, select) {
            event.stopPropagation();
            document.body.style.cursor = 'crosshair';
            const mouseMoveHandler = (e) => {
                const elements = document.elementsFromPoint(e.clientX, e.clientY);
                elements.forEach((el) => {
                    el.style.outline = '2px solid red';
                });
                document.addEventListener('mouseout', () => {
                    elements.forEach((el) => {
                        el.style.outline = '';
                    });
                });
            };

            const clickHandler = (e) => {
                e.stopPropagation();
                e.preventDefault();
                const selectedElement = e.target;
                if (select.value === 'id' && selectedElement.id) {
                    input.value = selectedElement.id;
                } else if (select.value === 'class' && selectedElement.className) {
                    input.value = selectedElement.className;
                }
                document.body.style.cursor = 'default';
                document.removeEventListener('mousemove', mouseMoveHandler);
                document.removeEventListener('click', clickHandler, true);
            };

            document.addEventListener('mousemove', mouseMoveHandler);
            document.addEventListener('click', clickHandler, true);
        }

        // 添加新的输入框和相关元素
        function addInputField(type = 'id', value = '') {
            const inputWrapper = document.createElement('div');
            inputWrapper.style.marginBottom = '5px';

            const select = document.createElement('select');
            const optionId = document.createElement('option');
            optionId.value = 'id';
            optionId.innerText = 'ID';
            const optionClass = document.createElement('option');
            optionClass.value = 'class';
            optionClass.innerText = '类名';
            select.appendChild(optionId);
            select.appendChild(optionClass);
            select.value = type;
            inputWrapper.appendChild(select);

            const input = document.createElement('input');
            input.type = 'text';
            input.value = value;
            input.style.marginLeft = '5px';
            inputWrapper.appendChild(input);

            const selectButton = document.createElement('button');
            selectButton.innerText = '选取';
            selectButton.style.marginLeft = '5px';
            selectButton.addEventListener('click', (e) => selectElement(e, input, select));
            inputWrapper.appendChild(selectButton);

            const removeButton = document.createElement('button');
            removeButton.innerText = '-';
            removeButton.style.marginLeft = '5px';
            removeButton.addEventListener('click', function() {
                inputWrapper.remove();
            });
            inputWrapper.appendChild(removeButton);

            inputContainer.appendChild(inputWrapper);
        }

        // 加号按钮事件监听
        addButton.addEventListener('click', (e) => {
            e.stopPropagation();
            addInputField();
        });

        // 应用按钮事件监听
        applyButton.addEventListener('click', (e) => {
            e.stopPropagation();
            saveData();
            applyAutoClick();
        });

        // 开始/暂停按钮事件监听
        toggleAutoClickButton.addEventListener('click', (e) => {
            e.stopPropagation();
            autoClickEnabled = !autoClickEnabled;
            toggleAutoClickButton.innerText = autoClickEnabled ? '暂停' : '开始';
            GM_setValue(`${currentUrl}_autoClickEnabled`, autoClickEnabled);
        });

        // 自动点击功能
        function applyAutoClick() {
            function autoClick() {
                if (autoClickEnabled) {
                    const inputs = inputContainer.getElementsByTagName('input');
                    for (let i = 0; i < inputs.length; i++) {
                        const input = inputs[i];
                        const select = input.previousSibling;
                        if (select.value === 'id') {
                            const element = document.getElementById(input.value);
                            if (element && typeof element.click === 'function' && !menuContainer.contains(element)) {
                                element.click();
                            }
                        } else if (select.value === 'class') {
                            const elements = document.getElementsByClassName(input.value);
                            for (let j = 0; j < elements.length; j++) {
                                const element = elements[j];
                                if (element && typeof element.click === 'function' && !menuContainer.contains(element)) {
                                    element.click();
                                }
                            }
                        }
                    }
                }
                requestAnimationFrame(autoClick);
            }

            // 启动自动点击
            requestAnimationFrame(autoClick);
        }

        // 加载保存的数据
        loadSavedData();

        // 展开/收起按钮事件监听
        toggleButton.addEventListener('click', (e) => {
            e.stopPropagation();
            if (menuContainer.style.display === 'none') {
                menuContainer.style.display = 'block';
                toggleButton.innerText = '<';
            } else {
                menuContainer.style.display = 'none';
                toggleButton.innerText = '>';
            }
        });

        // 防止菜单内元素点击事件冒泡影响自动点击逻辑
        menuContainer.addEventListener('click', (e) => {
            e.stopPropagation();
        });

        // 确保菜单元素可以正常响应输入事件
        inputContainer.addEventListener('mousedown', (e) => {
            e.stopPropagation();
        });

        inputContainer.addEventListener('mouseup', (e) => {
            e.stopPropagation();
        });

        inputContainer.addEventListener('click', (e) => {
            e.stopPropagation();
        });

        inputContainer.addEventListener('input', (e) => {
            e.stopPropagation();
        });

        // 启动自动点击功能
        applyAutoClick();
    };
})();