A-A+

选中即弹出复制按钮的tampermonkey(油猴)脚本

2025年11月28日 21:20 学习笔记 暂无评论 共5202字 (阅读53 views次)

【注意:此文章为博主原创文章!转载需注意,请带原文链接,至少也要是txt格式!】

使用此脚本,选中任何网站的内容,在内容旁都会弹出复制按钮,点击即可复制选中的内容。(部分百度等不可以。)

// ==UserScript==
// @name         精准选区复制按钮
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  在选区结尾精准弹出复制按钮,兼容输入框和页面选区
// @author       GPT
// @match        *://*/*
// @grant        GM_setClipboard
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    // 复制功能
    function copyTextToClipboard(text) {
        if (typeof GM_setClipboard === "function") {
            GM_setClipboard(text, "text");
        } else if (navigator.clipboard) {
            navigator.clipboard.writeText(text);
        } else {
            const textarea = document.createElement('textarea');
            textarea.value = text;
            document.body.appendChild(textarea);
            textarea.select();
            document.execCommand('copy');
            document.body.removeChild(textarea);
        }
    }

    // 复制按钮生成
    function createCopyBtn() {
        const btn = document.createElement('div');
        btn.innerHTML = `
            <span style="
                font-size:15px;
                user-select:none;
                cursor:pointer;
                color:#fff;
                background:rgba(33,36,50,0.9);
                border-radius:5px;
                padding:4px 8px;
                box-shadow:0 2px 8px #0002;
                display:flex;
                align-items:center;
            ">
                <svg width="18" height="18" style="margin-right:3px;" viewBox="0 0 24 24" fill="none"><rect x="9" y="9" width="13" height="13" rx="2" fill="#fff" fill-opacity="0.3"/><rect x="2" y="2" width="13" height="13" rx="2" fill="#fff"/></svg>
                复制
            </span>
        `;
        btn.style.position = 'fixed';
        btn.style.zIndex = '999999';
        btn.style.display = 'none';
        btn.style.pointerEvents = 'auto';
        btn.className = 'tm-copy-selection-btn-gpt';
        document.body.appendChild(btn);
        return btn;
    }

    const copyBtn = createCopyBtn();
    let hideTimer = null;

    function showCopyBtn(text, clientX, clientY) {
        copyBtn.style.left = `${clientX + 6}px`;
        copyBtn.style.top = `${clientY + 8}px`;
        copyBtn.style.display = 'block';
        copyBtn.children[0].innerHTML = `
            <svg width="18" height="18" style="margin-right:3px;" viewBox="0 0 24 24" fill="none"><rect x="9" y="9" width="13" height="13" rx="2" fill="#fff" fill-opacity="0.3"/><rect x="2" y="2" width="13" height="13" rx="2" fill="#fff"/></svg>
            复制`;
        copyBtn.onclick = function(e) {
            e.stopPropagation();
            copyTextToClipboard(text);
            copyBtn.children[0].innerText = "✔ 已复制";
            setTimeout(hideCopyBtn, 1000);
        };
        clearTimeout(hideTimer);
        hideTimer = setTimeout(hideCopyBtn, 10000);  // 注释或删除这一行 复制按钮就不回消失
    }

    function hideCopyBtn() {
        copyBtn.style.display = 'none';
    }

    // 判断是否是在输入框选区
    function getInputSelectionPosition(inputEl) {
        // 当前文本选区结束位置
        const start = inputEl.selectionEnd;
        // 创建一个临时 span 计算实际位置
        const value = inputEl.value;

        // 创建 shadow span
        const div = document.createElement('div');
        const style = getComputedStyle(inputEl);

        for(let p of ['fontSize','fontFamily','fontWeight','letterSpacing','paddingLeft','paddingTop','paddingRight','paddingBottom','borderLeftWidth','borderTopWidth','borderRightWidth','borderBottomWidth','whiteSpace']){
            div.style
= style
; } div.style.position = 'absolute'; div.style.visibility = 'hidden'; div.style.whiteSpace = 'pre-wrap'; div.style.wordBreak = 'break-word'; div.style.left = '-9999px'; div.textContent = value.substring(0, start); document.body.appendChild(div); // 计算 span 的位置 const rect = div.getBoundingClientRect(); const inputRect = inputEl.getBoundingClientRect(); let x = inputRect.left + rect.width; let y = inputRect.top + rect.height; document.body.removeChild(div); // 修正超出 x = Math.min(x, inputRect.right - 20); y = Math.min(y, inputRect.bottom - 20); return {clientX: x, clientY: y}; } // 处理mouseup事件 document.addEventListener('mouseup', function(e) { setTimeout(() => { let sel = window.getSelection(); // 普通页面选区 if(sel && sel.toString().trim()) { let range = sel.getRangeAt(0); // 对于嵌入式容器的选区,要能聚焦实际内容最后 let rect = range.getClientRects(); let visibleRect = rect[rect.length - 1] || range.getBoundingClientRect(); if(visibleRect.width === 0 && visibleRect.height === 0) { hideCopyBtn(); return; } // 计算相对于视口的位置 let clientX = visibleRect.right; let clientY = visibleRect.bottom; showCopyBtn(sel.toString(), clientX, clientY); return; } // 如果是在输入框或textarea选中内容 let activeEl = document.activeElement; if (activeEl && (activeEl.tagName === 'TEXTAREA' || (activeEl.tagName === 'INPUT' && /text|search|url|email|password/.test(activeEl.type)))) { const s = activeEl.selectionStart, e = activeEl.selectionEnd; if (s !== e) { // 获取选区位置 let pos = getInputSelectionPosition(activeEl); showCopyBtn(activeEl.value.substring(s,e), pos.clientX, pos.clientY); return; } } hideCopyBtn(); }, 15); }); // 隐藏按钮:点页面/ESC document.addEventListener('mousedown', function(e){ if (!copyBtn.contains(e.target)) { hideCopyBtn(); } }); document.addEventListener('keydown', function(e){ if(e.key === "Escape"){ hideCopyBtn(); } }); document.addEventListener('scroll', hideCopyBtn, true); window.addEventListener('resize', hideCopyBtn, true); // 强制支持 ctrl+C document.addEventListener('copy', function(e){ let sel = window.getSelection(); if(sel && sel.toString() && e.clipboardData){ e.clipboardData.setData('text/plain', sel.toString()); e.preventDefault(); } // 针对输入textarea let activeEl = document.activeElement; if (activeEl && (activeEl.tagName === 'TEXTAREA' || (activeEl.tagName === 'INPUT' && /text|search|url|email|password/.test(activeEl.type)))) { const s = activeEl.selectionStart, ee = activeEl.selectionEnd; if (s !== ee) { e.clipboardData.setData('text/plain', activeEl.value.substring(s, ee)); e.preventDefault(); } } }, true); })();

布施恩德可便相知重

微信扫一扫打赏

支付宝扫一扫打赏

×

给我留言