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

发布于 2024-11-28 09:55:28 字数 278 浏览 1 评论 0 原文

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

到目前为止,我得到了这样的信息:

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

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

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

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. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

梨涡 2024-12-05 09:55:28

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

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

“复制” “粘贴” “剪切”
IE OK OK n/a
Edge OK n/a OK
Firefox OK n/a OK
Chrome 好的 不适用 好的

我的两点意见:

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

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

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

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.

This is the compatibility matrix of document.execCommand("...") concerning clipboard events:

"copy" "paste" "cut"
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. 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.

You can feature detect the possible commands using the document.queryCommandSupported method.

Edit: According to MDN document.queryCommandSupported is now deprecated and should no longer be used.

木落 2024-12-05 09:55:28

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

已转向更标准的 document.execCommand('paste')document.execCommand(' copy')document.execCommand('cut') 命令:

在 Chrome 中,您需要添加权限到您的清单:“clipboardRead”和“clipboardWrite”。

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

There used to be an experimental clipboard API in Chrome, but this was removed in Chrome 13.

Chrome has moved towards the more standard document.execCommand('paste'), document.execCommand('copy') and document.execCommand('cut') commands:

In Chrome you'll need permissions need to be added to your manifest: "clipboardRead" and "clipboardWrite".

Up until Chrome 38, these clipboard permissions were only available to extension pages such as background scripts. As of Chrome 39, content scripts can also use these clipboard APIs after declaring the clipboard permissions in the manifest file.

就此别过 2024-12-05 09:55:28

这对我来说在背景页面中效果很好。

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

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:

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);
情绪操控生活 2024-12-05 09:55:28

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

You can't execute it on a regular page, only in a background page.

缺⑴份安定 2024-12-05 09:55:28

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

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

You need to set the clipboardRead permission to use document.execCommand('paste') and the clipboardWrite permission to use execCommand('copy') and execCommand('cut').
Otherwise, the permissions will be denied and nothing will happen.

Check this link for more details.

错爱 2024-12-05 09:55:28

您可以通过手动执行相同的操作来模仿粘贴:

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

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. 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:

addEventListener("paste", pasteHandler);

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

For #4, add this after 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. For instance:

Vue.nextTick(() => {
  el.setSelectionRange(newCursorPos, newCursorPos);
});
鸢与 2024-12-05 09:55:28

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

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

关于 Chrome 扩展程序参见复制/粘贴在 Chrome 扩展程序中不起作用

you need to a control in focus 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
and http://help.dottoro.com/ljcvtcaw.php

Regarding Chrome extensions see Copy/Paste Not Working in Chrome Extension

风透绣罗衣 2024-12-05 09:55:28

由于在manifest v3上无法与Service Worker一起使用,经过长时间的研究,我找到了更好的解决方案:(您仍然需要在manifest中设置clipboardRead权限)

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

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)

navigator.clipboard
        .readText()
        .then(
            (clipText) => console.log(clipText)
        );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文