为什么document.execCommand(“粘贴”)无法在Google Chrome中运行?

时间:2011-08-06 22:31:37

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

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

到目前为止,我已经有了这个:

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

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

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

7 个答案:

答案 0 :(得分:11)

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。

答案 1 :(得分:6)

这在我的后台页面中效果很好。

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);

答案 2 :(得分:4)

由于安全方面的考虑,“ {理性}”浏览器不支持调用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

我为此付出的两分钱:

  • Edge Firefox Chrome 的行为是“合理的”,因为它们阻止了从剪贴板粘贴/读取数据。它们确实启用剪切,因为剪切只是复制然后是删除。
  • IE 的行为对我来说毫无意义,因为它启用了“危险”粘贴,但不执行cut事件。

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

答案 3 :(得分:2)

您无法在常规页面上执行此操作,只能在后台页面中执行。

答案 4 :(得分:1)

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

查看this链接了解详情。

答案 5 :(得分:0)

你需要一个能够接收内容的focues中的控件......

有关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

答案 6 :(得分:0)

您可以通过手工完成相同的操作来模仿粘贴:

  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);
});