Greasy Fork

Greasy Fork is available in English.

自动复制选中文本和解除复制限制按钮

在任意网站选中任意文本时自动复制,并提供设置选项以启用/禁用解除网站的复制限制和自动复制功能,以及显示/隐藏按钮

当前为 2024-06-29 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        自动复制选中文本和解除复制限制按钮
// @name:zh     自动复制选中文本和解除复制限制按钮
// @name:en     Automatic Copy Selected Text and Remove Copy Restrictions Button
// @namespace   http://tampermonkey.net/
// @version     2.9
// @description 在任意网站选中任意文本时自动复制,并提供设置选项以启用/禁用解除网站的复制限制和自动复制功能,以及显示/隐藏按钮
// @description:en Automatically copy selected text on any website and provide settings to enable/disable unlocking copy restrictions, auto-copy functionality, and show/hide button
// @author      lbihhe
// @license     MIT
// @icon        https://img.icons8.com/nolan/64/password1.png
// @match       *://*/*
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_registerMenuCommand
// ==/UserScript==

(function() {
    'use strict';

    // 语言检测
    var userLanguage = navigator.language || navigator.userLanguage;
    var isChinese = userLanguage.startsWith('zh');

    // 文本定义
    var text = {
        enableCopy: isChinese ? '🔓解除复制限制并启用自动复制' : '🔓Enable Copy Restrictions and Auto Copy',
        disableCopy: isChinese ? '🔒禁用复制功能' : '🔒Disable Copy Function',
        copyTextAlert: isChinese ? '选中文本已复制到剪贴板' : 'Selected text copied to clipboard',
        copyHTMLAlert: isChinese ? '选中的 HTML 已复制到剪贴板' : 'Selected HTML copied to clipboard',
        copyFailureAlert: isChinese ? '复制失败' : 'Copy failed',
        copyExceptionAlert: isChinese ? '复制过程中出现异常: ' : 'Exception during copy: ',
        invalidCopyFormatAlert: isChinese ? '无效的复制格式,保留当前设置。' : 'Invalid copy format, retaining current settings.',
        copyFormatPrompt: isChinese ? '请选择复制格式(text: 纯文本, html: HTML, link: 链接和文本):' : 'Please select copy format (text: Plain text, html: HTML, link: Link and text):',
    };

    // 读取存储的设置
    var copyState = {
        enabled: GM_getValue('enabled', false),
        showButton: GM_getValue('showButton', true),
        copyFormat: GM_getValue('copyFormat', 'text'),
        showAlert: GM_getValue('showAlert', true)
    };

    // 创建按钮
    var button = createButton();
    copyState.button = button;

    // 停止事件传播的处理函数
    function stopPropagation(e) {
        e.stopPropagation();
    }

    // 自动复制选中文本的处理函数
    function autoCopyHandler() {
        var selectedText = window.getSelection().toString().trim();
        if (selectedText) {
            if (copyState.copyFormat === 'text') {
                copyTextToClipboard(selectedText);
            } else if (copyState.copyFormat === 'html') {
                copyHTMLToClipboard(selectedText);
            } else if (copyState.copyFormat === 'link') {
                var url = window.location.href;
                copyTextToClipboard(`${selectedText}\n${url}`);
            }
        }
    }

    // 将文本复制到剪贴板
    function copyTextToClipboard(text) {
        var tempTextarea = document.createElement('textarea');
        tempTextarea.style.position = 'fixed';
        tempTextarea.style.top = '0';
        tempTextarea.style.left = '0';
        tempTextarea.style.width = '2em';
        tempTextarea.style.height = '2em';
        tempTextarea.style.padding = '0';
        tempTextarea.style.border = 'none';
        tempTextarea.style.outline = 'none';
        tempTextarea.style.boxShadow = 'none';
        tempTextarea.style.background = 'transparent';
        tempTextarea.value = text;
        document.body.appendChild(tempTextarea);
        tempTextarea.select();
        try {
            var successful = document.execCommand('copy');
            if (successful) {
                showAlert(text.copyTextAlert);
            } else {
                showAlert(text.copyFailureAlert);
            }
        } catch (err) {
            showAlert(text.copyExceptionAlert + err);
        }
        document.body.removeChild(tempTextarea);
    }

    // 将 HTML 复制到剪贴板
    function copyHTMLToClipboard(html) {
        var tempDiv = document.createElement('div');
        tempDiv.style.position = 'fixed';
        tempDiv.style.top = '0';
        tempDiv.style.left = '0';
        tempDiv.style.width = '2em';
        tempDiv.style.height = '2em';
        tempDiv.style.padding = '0';
        tempDiv.style.border = 'none';
        tempDiv.style.outline = 'none';
        tempDiv.style.boxShadow = 'none';
        tempDiv.style.background = 'transparent';
        tempDiv.innerHTML = html;
        document.body.appendChild(tempDiv);
        var range = document.createRange();
        range.selectNodeContents(tempDiv);
        var selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
        try {
            var successful = document.execCommand('copy');
            if (successful) {
                showAlert(text.copyHTMLAlert);
            } else {
                showAlert(text.copyFailureAlert);
            }
        } catch (err) {
            showAlert(text.copyExceptionAlert + err);
        }
        document.body.removeChild(tempDiv);
    }

    // 显示提示信息
    function showAlert(message) {
        if (copyState.showAlert) {
            var alertBox = document.createElement('div');
            alertBox.innerText = message;
            alertBox.style.position = 'fixed';
            alertBox.style.bottom = '70px';
            alertBox.style.right = '20px';
            alertBox.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
            alertBox.style.color = '#fff';
            alertBox.style.padding = '10px 15px';
            alertBox.style.borderRadius = '10px';
            alertBox.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
            alertBox.style.fontFamily = '微软雅黑, Arial, sans-serif';
            alertBox.style.fontSize = '14px';
            alertBox.style.zIndex = '9999';
            document.body.appendChild(alertBox);
            setTimeout(function() {
                document.body.removeChild(alertBox);
            }, 3000);
        }
    }

    // 解除复制限制的函数
    function enableCopy() {
        // 移除常见的禁止复制的事件监听器
        ['copy', 'cut', 'contextmenu', 'selectstart', 'mousedown', 'mouseup', 'keydown', 'keyup', 'keypress', 'oncopy', 'oncut', 'onpaste'].forEach(event => {
            document.addEventListener(event, stopPropagation, true);
        });

        // 解除 CSS 样式限制
        var css = `
            * {
                -webkit-user-select: auto !important;
                -moz-user-select: auto !important;
                -ms-user-select: auto !important;
                user-select: auto !important;
                pointer-events: auto !important;
                -webkit-touch-callout: default !important;
            }
        `;
        var style = document.createElement('style');
        style.type = 'text/css';
        style.appendChild(document.createTextNode(css));
        document.head.appendChild(style);

        // 处理 body 标签的 oncontextmenu 属性
        if (document.body) {
            document.body.oncontextmenu = null;
        }

        // 处理常见的框架
        var frames = [...document.getElementsByTagName('iframe'), ...document.getElementsByTagName('object'), ...document.getElementsByTagName('embed')];
        frames.forEach(frame => {
            try {
                var frameDoc = frame.contentWindow.document;
                ['copy', 'cut', 'contextmenu', 'selectstart', 'mousedown', 'mouseup', 'keydown', 'keyup', 'keypress'].forEach(event => {
                    frameDoc.addEventListener(event, stopPropagation, true);
                });
            } catch (e) {
                console.error('无法访问框架内容:', e);
            }
        });

        // 添加鼠标抬起事件监听器
        document.addEventListener('mouseup', autoCopyHandler, true);
    }

    // 禁用复制功能的函数
    function disableCopy() {
        // 恢复默认事件
        ['copy', 'cut', 'contextmenu', 'selectstart', 'mousedown', 'mouseup', 'keydown', 'keyup', 'keypress', 'oncopy', 'oncut', 'onpaste'].forEach(event => {
            document.removeEventListener(event, stopPropagation, true);
        });

        // 移除 CSS 样式限制
        var styles = document.getElementsByTagName('style');
        for (var i = 0; i < styles.length; i++) {
            if (styles[i].innerHTML.includes('-webkit-user-select: auto !important')) {
                styles[i].parentNode.removeChild(styles[i]);
            }
        }

        // 移除鼠标抬起事件监听器
        document.removeEventListener('mouseup', autoCopyHandler, true);
    }

    // 创建按钮的函数
    function createButton() {
        var button = document.createElement('button');
        button.innerHTML = text.enableCopy;
        button.style.position = 'fixed';
        button.style.bottom = '20px';
        button.style.right = '20px';
        button.style.zIndex = '9999';
        button.style.padding = '10px 15px';
        button.style.backgroundColor = 'rgba(173, 216, 230, 0.9)';
        button.style.color = '#000';
        button.style.border = 'none';
        button.style.borderRadius = '10px';
        button.style.cursor = 'pointer';
        button.style.fontFamily = '微软雅黑, Arial, sans-serif';
        button.style.fontSize = '14px';
        button.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
        button.style.transition = 'background-color 0.3s, transform 0.3s';
        button.onmouseover = function() {
            button.style.backgroundColor = 'rgba(135, 206, 235, 0.9)';
            button.style.transform = 'scale(1.05)';
        };
        button.onmouseout = function() {
            button.style.backgroundColor = 'rgba(173, 216, 230, 0.9)';
            button.style.transform = 'scale(1)';
        };
        button.addEventListener('click', function() {
            toggleCopyState();
        });
        if (copyState.showButton) {
            document.body.appendChild(button);
        }
        return button;
    }

    // 切换复制状态的函数
    function toggleCopyState() {
        if (copyState.enabled) {
            disableCopy();
            copyState.button.innerHTML = text.enableCopy;
        } else {
            enableCopy();
            copyState.button.innerHTML = text.disableCopy;
        }
        copyState.enabled = !copyState.enabled;
        GM_setValue('enabled', copyState.enabled);
    }

    // 设置自动复制功能开关
    GM_registerMenuCommand(text.enableCopy, function() {
        toggleCopyState();
    });

    // 设置按钮显示开关
    GM_registerMenuCommand(isChinese ? '设置显示解除复制限制按钮' : 'Toggle Show Copy Restrictions Button', function() {
        copyState.showButton = !copyState.showButton;
        GM_setValue('showButton', copyState.showButton);
        if (copyState.showButton) {
            document.body.appendChild(button);
        } else {
            if (button.parentNode) {
                button.parentNode.removeChild(button);
            }
        }
    });

    // 设置复制格式
    GM_registerMenuCommand(isChinese ? '设置复制格式' : 'Set Copy Format', function() {
        var copyFormatOptions = ['text', 'html', 'link'];
        var copyFormat = prompt(text.copyFormatPrompt, copyState.copyFormat);

        if (copyFormatOptions.includes(copyFormat)) {
            copyState.copyFormat = copyFormat;
            GM_setValue('copyFormat', copyState.copyFormat);
        } else {
            alert(text.invalidCopyFormatAlert);
        }
    });

    // 根据存储的设置启用或禁用自动复制功能
    if (copyState.enabled) {
        enableCopy();
    }
})();