【问题标题】:Why is document.execCommand("paste") not working in Google Chrome?为什么 document.execCommand("paste") 在 Google Chrome 中不起作用?
【发布时间】:2011-08-06 22:31:37
【问题描述】:

我的扩展程序有问题。我想从剪贴板粘贴数据。

到目前为止,我得到了这个:

function pasteAndGo()
{
    document.execCommand('paste')
    alert("Pasted")
}

警报出现,但没有粘贴任何内容。

我感觉需要更改的是 document 部分,但我不知道该怎么做。有什么想法吗?

【问题讨论】:

标签: javascript google-chrome google-chrome-extension clipboard


【解决方案1】:

Chrome 中曾经有一个实验性剪贴板 API,但在 Chrome 13 中已被删除。

Chrome 已转向更标准的 document.execCommand('paste')document.execCommand('copy')document.execCommand('cut') 命令:https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla#Executing%5FCommands

在 Chrome 中,您需要将权限添加到清单中:“clipboardRead”和“clipboardWrite”。 http://developer.chrome.com/extensions/declare_permissions.html

在 Chrome 38 之前,这些剪贴板权限仅适用于后台脚本等扩展程序页面。从 Chrome 39 开始,内容脚本也可以在清单文件 (crbug.com/395376) 中声明剪贴板权限后使用这些剪贴板 API。

【讨论】:

【解决方案2】:

“合理的”浏览器不支持调用document.execCommand("paste"),因为它可能使脚本能够从剪贴板读取敏感数据(如密码)。

这是document.execCommand("...")关于剪贴板事件的兼容性矩阵

"copy" "paste" "cut"
IE OK OK n/a
Edge OK n/a OK
Firefox OK n/a OK
Chrome OK n/a OK

我的两分钱:

  • EdgeFirefoxChrome 的行为是“合理的”,因为它们会阻止从剪贴板粘贴/读取数据。它们确实启用了剪切,因为剪切只是一个副本,然后是一个删除。
  • IE 的行为对我来说毫无意义,因为它启用了“有风险的”粘贴,但不执行剪切事件。

您可以使用document.queryCommandSupported 方法特征检测可能的命令。

编辑:根据 MDN,document.queryCommandSupported 现在已弃用,不应再使用。

【讨论】:

    【解决方案3】:

    这对我来说在后台页面中效果很好。

    function getClipboard() {
        var pasteTarget = document.createElement("div");
        pasteTarget.contentEditable = true;
        var actElem = document.activeElement.appendChild(pasteTarget).parentNode;
        pasteTarget.focus();
        document.execCommand("Paste", null, null);
        var paste = pasteTarget.innerText;
        actElem.removeChild(pasteTarget);
        return paste;
    };
    

    当然,您的扩展程序仍然需要“clipboardRead”权限,并且您必须使用消息传递将此信息返回到您的内容脚本:

    content.js:

    chrome.extension.sendMessage({
        cmd: "clipboard", //$NON-NLS-0$
        action: "paste" //$NON-NLS-0$
    }, function(response) {
        if (response.paste) {
            var range = document.getSelection().getRangeAt(0);
            range.deleteContents();
            range.insertNode(document.createTextNode(response.paste));
        }
    });
    

    background.js:

    function getClipboard() {
        var pasteTarget = document.createElement("div");
        pasteTarget.contentEditable = true;
        var actElem = document.activeElement.appendChild(pasteTarget).parentNode;
        pasteTarget.focus();
        document.execCommand("Paste", null, null);
        var paste = pasteTarget.innerText;
        actElem.removeChild(pasteTarget);
        return paste;
    };
    
    function onClipboardMessage(request, sender, sendResponse) {
        if (request.action === "paste") { //$NON-NLS-0$
            sendResponse({
                paste: getClipboard()
            });
        }
    }
    
    chrome.extension.onMessage.addListener(onClipboardMessage);
    

    【讨论】:

    • @peter-ehrlich 嗨,彼得,这个例子怎么样?是你要求的吗?
    • 嗨@josephduffy 你让这个工作了吗?你的例子有帮助吗?
    【解决方案4】:

    您不能在常规页面上执行它,只能在后台页面中执行。

    【讨论】:

    • 你会做整个不可见的文本区域吗?谁有代码示例?
    • 不再正确,请参阅下面的答案('从 chrome 39 开始,在清单文件中声明剪贴板权限后,内容脚本也可以使用这些剪贴板 API')
    • 背景页面示例?
    • 什么是“常规页面”与“背景页面”?
    • @brandaemon 确实,这没有任何意义
    【解决方案5】:

    您需要一个能够接收内容的焦点控件...

    有关 JS 中剪贴板的一些示例,请参阅http://www.geekpedia.com/tutorial126_Clipboard-cut-copy-and-paste-with-JavaScript.html
    http://help.dottoro.com/ljcvtcaw.php

    关于 Chrome 扩展,请参阅Copy/Paste Not Working in Chrome Extension

    【讨论】:

    • 那是我找到我的信息表单的确切页面(指向另一个 Stack Overflow 问题的链接)。我会努力让它粘贴在正确的区域? :S
    • 您需要将注意力集中在可以接受剪贴板中的内容的内容上——比如剪贴板包含文本时的文本区域...
    【解决方案6】:

    您需要设置clipboardRead 权限才能使用document.execCommand('paste')clipboardWrite 权限才能使用execCommand('copy')execCommand('cut')
    否则,权限将被拒绝并且不会发生任何事情。

    查看this链接了解更多详情。

    【讨论】:

      【解决方案7】:

      您可以自己动手做同样的事情来模仿粘贴:

      1. 可选:当用户尝试粘贴时触发
      2. 获取剪贴板的内容(需要用户通过浏览器提供的弹出窗口获得许可)
      3. 将内容插入活动控件
      4. 可选:触发真实粘贴会触发的事件(为了所有听众的利益)

      首先关注步骤#2 和#3,在此示例中,我检查活动元素是否为文本输入。如果是这样,我会通过替换该文本框的突出显示内容并重新定位光标来模拟粘贴。

      function myPaste() {
        navigator.clipboard.readText()
          .then(clipText => {
            const el = document.activeElement;
            if (el.nodeName === 'INPUT') {
              const newCursorPos = el.selectionStart + clipText.length;
              el.value =
                el.value.substring(0, el.selectionStart) +
                clipText +
                el.value.substring(el.selectionEnd);
              el.setSelectionRange(newCursorPos, newCursorPos);
            }
          });
      }
      

      对于#1,添加一个监听器来拦截用户的粘贴尝试:

      addEventListener("paste", pasteHandler);
      
      function pasteHandler(e) {
        e.preventDefault();
        myPaste();
      }
      

      对于#4,在el.setSelectionRange(newCursorPos, newCursorPos);之后添加:

      el.dispatchEvent(new Event('input'));
      el.dispatchEvent(new Event('change'));
      

      请注意,如果您使用的是基于数据绑定代表您操作 DOM 的反应式框架,则需要将光标位置更新推迟到下一次 DOM 渲染之后。例如:

      Vue.nextTick(() => {
        el.setSelectionRange(newCursorPos, newCursorPos);
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-19
        相关资源
        最近更新 更多