简体   繁体   English

为什么 document.execCommand("paste") 在 Google Chrome 中不起作用?

[英]Why is document.execCommand("paste") not working in Google Chrome?

I have a problem with my extension.我的分机有问题。 I want to paste data from the clipboard.我想从剪贴板粘贴数据。

So far, I've got this:到目前为止,我有这个:

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

The alert comes up, but nothing has been pasted.警报出现,但没有粘贴任何内容。

I've got a feeling it's the document part that needs changing, but I don't know what to do.我感觉是document部分需要更改,但我不知道该怎么做。 Any ideas?有任何想法吗?

Calling document.execCommand("paste") is not supported by "reasonable" browsers, because of security concerns as it might enable the script to read sensitive data (like passwords) from the clipboard.出于安全考虑,“合理”浏览器不支持调用document.execCommand("paste") ,因为它可能使脚本能够从剪贴板读取敏感数据(如密码)。

This is the compatibility matrix of document.execCommand("...") concerning clipboard events:这是关于剪贴板事件的document.execCommand("...")兼容性矩阵

"copy" “复制” "paste" “粘贴” "cut" “切”
IE IE OK OK n/a不适用
Edge边缘 OK n/a不适用 OK
Firefox火狐 OK n/a不适用 OK
Chrome铬合金 OK n/a不适用 OK

My two cents to this:我的两分钱:

  • The behaviour of Edge , Firefox and Chrome is "reasonable" as they prevent pasting/reading data from the clipboard. EdgeFirefoxChrome的行为是“合理的”,因为它们阻止从剪贴板粘贴/读取数据。 They do enable cut, as cut is simply a copy followed by a delete.它们确实启用了剪切,因为剪切只是一个副本,然后是删除。
  • The behaviour of IE makes no sense to me, as it enables the "risky" paste, but does not execute the cut event. IE的行为对我来说毫无意义,因为它启用了“有风险”的粘贴,但不执行剪切事件。

You can feature detect the possible commands using the document.queryCommandSupported method.您可以使用document.queryCommandSupported方法检测可能的命令。

Edit: According to MDN document.queryCommandSupported is now deprecated and should no longer be used.编辑:根据 MDN document.queryCommandSupported现在已弃用,不应再使用。

There used to be an experimental clipboard API in Chrome, but this was removed in Chrome 13. Chrome 中曾经有一个实验性的剪贴板 API,但它在 Chrome 13 中被删除了。

Chrome has moved towards the more standard document.execCommand('paste') , document.execCommand('copy') and document.execCommand('cut') commands: https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla#Executing%5FCommands Chrome 已转向更标准的document.execCommand('paste')document.execCommand('copy')document.execCommand('cut')命令: https : //developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla #Executing%5FCommands

In Chrome you'll need permissions need to be added to your manifest: "clipboardRead" and "clipboardWrite".在 Chrome 中,您需要将权限添加到清单中:“clipboardRead”和“clipboardWrite”。 http://developer.chrome.com/extensions/declare_permissions.html http://developer.chrome.com/extensions/declare_permissions.html

Up until Chrome 38, these clipboard permissions were only available to extension pages such as background scripts.在 Chrome 38 之前,这些剪贴板权限仅适用于扩展页面,例如后台脚本。 As of Chrome 39, content scripts can also use these clipboard APIs after declaring the clipboard permissions in the manifest file ( crbug.com/395376 ).从 Chrome 39 开始,在清单文件 ( crbug.com/395376 ) 中声明剪贴板权限后,内容脚本也可以使用这些剪贴板 API。

This works well for me in a background page.这在背景页面中对我很有效。

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

Of course your extension still needs "clipboardRead" permission and you have to use message passing to get this information back to your content script:当然,您的扩展仍然需要“clipboardRead”权限,您必须使用消息传递将此信息返回到您的内容脚本:

content.js:内容.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:背景.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);

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

You need to set the clipboardRead permission to use document.execCommand('paste') and the clipboardWrite permission to use execCommand('copy') and execCommand('cut') .您需要设置clipboardRead权限以使用document.execCommand('paste')clipboardWrite权限以使用execCommand('copy')execCommand('cut')
Otherwise, the permissions will be denied and nothing will happen.否则,权限将被拒绝,什么也不会发生。

Check this link for more details.查看链接了解更多详情。

You can mimic a paste by doing the same thing yourself by hand:您可以自己动手做同样的事情来模仿粘贴:

  1. Optional: trigger when the user tries to paste可选:当用户尝试粘贴时触发
  2. Get the contents of the clipboard (requires permission from user via a pop-up the browser will provide)获取剪贴板的内容(需要通过浏览器提供的弹出窗口获得用户的许可)
  3. Insert content into the active control将内容插入活动控件
  4. Optional: trigger the events a real paste would have triggered (for the benefit of any listeners)可选:触发真正的粘贴会触发的事件(为了任何听众的利益)

Focusing on steps #2 and #3 first, in this example, I check whether the active element is a text input.首先关注步骤#2 和#3,在这个例子中,我检查活动元素是否是文本输入。 If so, I simulate a paste by replacing that text box's highlighted content and repositioning the cursor.如果是这样,我通过替换该文本框的突出显示内容并重新定位光标来模拟粘贴。

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

For #1, add a listener to intercept the user's paste attempts:对于#1,添加一个监听器来拦截用户的粘贴尝试:

addEventListener("paste", pasteHandler);

function pasteHandler(e) {
  e.preventDefault();
  myPaste();
}

For #4, add this after el.setSelectionRange(newCursorPos, newCursorPos);对于 #4,在el.setSelectionRange(newCursorPos, newCursorPos);之后添加这个:

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

Note that if you are using a reactive framework that manipulates the DOM on your behalf based on data binding, you will need to defer the cursor position update until after the next DOM render.请注意,如果您使用的是基于数据绑定代表您操作 DOM 的反应式框架,则您需要将光标位置更新推迟到下一次 DOM 渲染之后。 For instance:例如:

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

you need to a control in focues which is capable of receiving the content...你需要一个能够接收内容的焦点控件......

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

Regarding Chrome extensions see Copy/Paste Not Working in Chrome Extension关于 Chrome 扩展程序,请参阅在 Chrome 扩展程序中复制/粘贴不起作用

Because on manifest v3 does not work with service worker, I found a better solution after long researches: (You still need to set the clipboardRead permission in manifest)因为在 manifest v3 上不支持 service worker,经过长时间的研究,我找到了一个更好的解决方案:(你仍然需要在 manifest 中设置 clipboardRead 权限)

navigator.clipboard
        .readText()
        .then(
            (clipText) => console.log(clipText)
        );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM