RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1038379
Accepted
Raz Galstyan
Raz Galstyan
Asked:2020-10-25 05:23:37 +0000 UTC2020-10-25 05:23:37 +0000 UTC 2020-10-25 05:23:37 +0000 UTC

copyToClipboard js 在 chrome 扩展中不起作用

  • 772

我正在为chrome. 面临将文本复制到js的问题。复制代码本身很简单。

问题的本质是代码没有复制到剪贴板。

有人可以帮助解决问题吗?

这是代码本身。

function copyToClipboard() {
  /* Get the text field */
  var copyText = document.getElementById("clipboard-text");

  /* Select the text field */
  copyText.select();
  copyText.setSelectionRange(0, 99999); /*For mobile devices*/

  /* Copy the text inside the text field */
  document.execCommand("copy");

  /* Alert the copied text */
  alert("Copied the text: " + copyText.value);
}

document.getElementById('clipboard-copy').addEventListener("click", copyToClipboard);

单击按钮后,Copy会触发一个事件,但文本并未完全复制到剪贴板。

在此处输入图像描述

在此处输入图像描述

javascript
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Deliaz
    2020-10-31T04:39:57Z2020-10-31T04:39:57Z

    确保您已请求"clipboardWrite"权限:

    清单.json:

    {
        ...
        "permissions": [
            ...
            "clipboardWrite"
        ]
        ...
    }
    

    乍一看,代码看起来是正确的。在我的扩展中,我使用了一个非常相似的片段:

    const tempEl = document.createElement('textarea');
    document.body.appendChild(tempEl);
    tempEl.value = textToCopy;
    tempEl.select();
    const copied = document.execCommand('copy');
    document.body.removeChild(tempEl);
    
    • 1
  2. yar85
    2020-10-31T05:47:09Z2020-10-31T05:47:09Z

    应该使用新的剪贴板 API。
    有了它,复制到缓冲区是由方法执行的,该方法navigator.clipboard.writeText()将字符串值作为参数 - 要复制的文本。
    返回结果Promise——也就是说,执行是异步的……但另一方面,您可以方便地捕获错误。是的,而且async+await没有人取消;)

    从 Chrome 扩展程序中的弹出窗口调用方法时,不需要额外的权限。
    在 Firefox 扩展中,它们也是可选的,但有一个条件是方法调用必须在用户发起的事件处理程序的回调中执行(例如,在单击处理程序中)。

    我在 Chrome v77 开发人员模式下检查了扩展程序,一切正常。


    重复测试扩展的示例:

    /* popup.js */
    document.addEventListener('DOMContentLoaded', () => {
      const inputEl  = document.querySelector('input');
      document.querySelector('button').addEventListener('click', () => {
        navigator.clipboard.writeText(inputEl.value)
          .then(() => { setStatus('Скопировано!'); })
          .catch(setStatus);
      });
    });
    
    function setStatus(data) {    // эта функция только для показа результата
      const statusEl = document.querySelector('p');
      if (data instanceof Error) {
        statusEl.textContent = data.message;
        statusEl.style.color = '#e00';
      } else {
        statusEl.textContent = data;
        statusEl.style.color = '#0c0';
        setTimeout(() => setStatus(''), 2e3);
      }
    }
    /* popup.html > html > head > style */
    body { font-family: sans-serif; }
    body > * { font-size: 1rem; }
    div, p { margin: 1rem 0 0 0; padding: 0.5rem 0 0 0; border-top: 1px solid #eee; }
    textarea { display: block; width: 90%; }
    <!-- popup.html > html > body -->
    <input value="Lorem ipsum">
    <button>Скопировать в буфер обмена</button>
    <div>Сюда можно вставить текст (для проверки):</div>
    <textarea></textarea>
    <p></p>

    测试扩展清单:

    {
      "name": "Test extension",
      "description": "Test extension",
      "version": "0.0.1",
      "manifest_version": 2,
      "browser_action": {
        "default_popup": "popup.html"
      }
    }
    



    在网页上使用时(即不在扩展程序中),需要考虑三件事:

    • 显然,剪贴板 API 仅在页面通过 HTTPS 加载时才有效

    • 某些浏览器可能会要求您通过 Permissions API 请求权限

    • 剪贴板 API 是实验性的,这意味着较旧/滞后的浏览器不支持它,并且(目前)Android WebView 缺少支持(Android 版 Chrome 支持)

    MDN 页面:https ://wiki.developer.mozilla.org/en-US/docs/Web/API/Clipboard

    • 1
  3. Best Answer
    Alexander Lonberg
    2020-11-02T07:01:11Z2020-11-02T07:01:11Z

    奇怪,它在浏览器和扩展程序中都适用于我,没有任何额外的权限 - 而且execCommand,两者clipboard.writeText

    Chrome 版本 77.0.3865.120(官方构建),(64 位)

    在此处输入图像描述

    包括,代码也在这里工作

    // lib.js
    function isInt(v) {
        return typeof v === 'number' && isFinite(v) && Math.floor(v) === v
    }
    
    function randomMinMax(min, max) {
        return Math.floor(Math.random() * (++max - min)) + min;
    }
    
    function isProperty(prop, obj, type) {
        return typeof obj === 'object' && prop in obj && (type ? typeof obj[prop] === type : true)
    }
    
    // charGenerator.js
    function charGenerator(...arrs) {
        let arr = []
    
        const testpush = (s) => {
            if (arr.indexOf(s) === -1) {
                arr.push(s)
            }
        }
    
        const set = (s, e) => {
            if (!isInt(s) || !isInt(e)) {
                return
            }
            for (let i = s; i <= e; ++i) {
                testpush(String.fromCharCode(i))
            }
        }
    
        let s
        for (let i = 0; i < arrs.length; ++i) {
            s = arrs[i]
            if (typeof s !== 'string' || !s.length) {
                continue
            }
            testpush(arrs[i][0])
            if (s.length > 1) {
                set(s.charCodeAt(0) + 1, s.charCodeAt(1))
            }
        }
    
        return arr
    }
    
    // Log.js
    class Log {
        constructor(elout) {
            this.out = elout
        }
        log(mess, cl = 'log') {
            let l = document.createElement('code')
            l.className = cl
            l.textContent = mess
            this.out.appendChild(l)
        }
    }
    
    // InputRandomText.js
    const numberChar = 8
    const abc = charGenerator('09', 'AZ', 'az')
    
    class InputRandomText {
    
        constructor(random, input) {
            this.input = input
            this.buttonExec = random
            this.buttonExec.addEventListener('click', () => {
                this.setInput()
            })
        }
    
        static generate(length = numberChar) {
            let l = length > abc.length ? abc.length : length
            let arr = abc.slice()
            let arrTo = []
            let i
            while (l--) {
                i = randomMinMax(0, arr.length)
                arrTo.push(arr.splice(i, 1)[0])
            }
            return arrTo.join('')
        }
    
        setInput() {
            this.input.value = InputRandomText.generate(randomMinMax(5, numberChar))
        }
    }
    
    // CopyToClipboard.js
    class CopyToClipboard extends Log {
        constructor(input, exec, log, methodExecCommand) {
            super(log)
            this.input = input
            this.buttonExec = exec
            this.methodExecCommand = methodExecCommand
            this.write = null
            // test
            if (this.test()) {
                this.buttonExec.addEventListener('click', () => {
                    this.copy()
                })
            }
            else {
                this.log('Возможно браузер не поддерживает копирование в буфер обмена', 'error')
            }
        }
    
        copy() {
            if (/^\s+|\s+$/g.test(this.input.value)) {
                this.input.value = this.input.value.replace(/^\s+|\s+$/g, '')
            }
            if (this.input.value.length) {
                this.input.select()
                try {
                    this.write()
                } catch (e) {
                    this.log(e.message, 'error')
                    return
                }
                this.log(`Текст value.length: ${this.input.value.length} скопирован в буфер обмена`)
                return
            }
            this.log('Отсутствует текст в поле ввода', 'warn')
        }
    
        testExecCommand() {
            if (isProperty('queryCommandSupported', document, 'function') && document.queryCommandSupported('copy') && isProperty('execCommand', document, 'function')) {
                this.write = () => {
                    document.execCommand('copy')
                }
                this.log('Копируем через document.execCommand')
                return true
            }
            return false
        }
        testClipboard() {
            if (isProperty('clipboard', navigator) && isProperty('writeText', navigator.clipboard, 'function')) {
                this.write = () => {
                    navigator.clipboard.writeText(this.input.value)
                }
                this.log('Копируем через navigator.clipboard')
                return true
            }
            return false
        }
    
        test() {
            // для теста меняем порядок проверки
            // clipboard.html
            // clipboard.html?execCommand -> methodExecCommand
            if (this.methodExecCommand && this.testExecCommand()) {
                return true
            }
            if (this.testClipboard() || this.testExecCommand()) {
                return true
            }
            return false
        }
    }
    
    // clipboard.js
    
    document.addEventListener('DOMContentLoaded', () => {
        new CopyToClipboard(
            document.body.querySelector('[data-input]'),
            document.body.querySelector('[data-exec]'),
            document.body.querySelector('[data-log]'),
            /execCommand/i.test(document.location.search)
        )
        new InputRandomText(
            document.body.querySelector('[data-random]'),
            document.body.querySelector('[data-input]')
        )
    })
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="shortcut icon" href="./icons/chemistry.png" type="image/png">
        <title>clipboard</title>
        <script src="./clipboard.js" type="module"></script>
        <style>
            body {
                font-family: 'Courier New', Courier, monospace;
            }
    
            [data-log] {
                margin-top: 1em;
                width: 500px;
                min-height: 100px;
                padding: 1em;
                background-color: #ececec;
                border: 1px solid #9E9E9E;
            }
    
            [data-log]>code {
                display: block;
                margin-top: 1em;
                border-left: 3px solid green;
                padding-left: 1em;
                font-size: 1.5em;
            }
    
            [data-log]>code.error {
                border-left-color: red;
            }
    
            [data-log]>code.warn {
                border-left-color: #ff9800;
            }
        </style>
    </head>
    
    <body>
    
        <h1>Test Clipboard</h1>
        <!-- Только для расширения и браузера
        <div>Для теста меняем порядок проверки и использования доступных API</div>
        <ul>
            <li><a href="./clipboard.html?clipboard">clipboard.html?clipboard</a></li>
            <li><a href="./clipboard.html?execCommand">clipboard.html?execCommand</a></li>
        </ul>
        -->
    
        <button data-random>Для ленивых</button>
        <input data-input type="text" placeholder="input text">
        <button data-exec>Copy</button>
        <br><br>
        <input type="text" placeholder="проверим ctrl+p"> Сюда просто вставляем что скопировано горячими клавишами [ctrl+p]
        <div data-log></div>
    
    </body>
    
    </html>

    清单副本

    {
        "manifest_version": 2,
        "name": "TestClipboard",
        "description": "TestClipboard",
        "version": "1.0.0",
        "author": "Alexander Lonberg",
        "icons": {
            "32": "icons/chemistry.png"
        },
        "browser_action": {
            "default_icon": {
                "32": "icons/chemistry.png"
            },
            "default_popup": "clipboard.html",
            "default_title": "TestClipboard"
        },
        "permissions": []
    }
    

    您可以尝试将此文件夹作为扩展连接或在浏览器中运行它
    https://yadi.sk/d/055Y4jgQCTuJWQ

    当然是UPD
    错字ctrl+p
    ctrl+v

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5