提问者:小点点

如何用JavaScript复制到剪贴板?


将文本复制到剪贴板的最佳方式是什么?(多浏览器)

我试过:

function copyToClipboard(text) {
    if (window.clipboardData) { // Internet Explorer
        window.clipboardData.setData("Text", text);
    } else {  
        unsafeWindow.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");  
        const clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper);  
        clipboardHelper.copyString(text);
    }
}

但在Internet Explorer中会出现语法错误。在Firefox中,它表示unsafewindow未定义

一个没有Flash的好技巧:Trello如何访问用户的剪贴板?


共3个答案

匿名用户

有三个主要的浏览器API用于复制到剪贴板:

  • 异步剪贴板API[navigator.Clipboard.writeText]
    • 在Chrome 66(2018年3月)中提供的文本聚焦部分
    • 访问是异步的,使用JavaScript承诺,可以编写为安全用户提示(如果显示)不要中断页面中的JavaScript.
    • 文本可以直接从变量复制到剪贴板。
    • 仅支持通过HTTPS提供服务的页面。
    • 在Chrome 66中,活动选项卡中的页面可以在没有权限提示的情况下写入剪贴板。
    • 自2015年4月起,大多数浏览器都支持此功能(请参见下面的浏览器支持)。
    • 访问是同步的,即在页面中停止JavaScript直到完成,包括显示和用户与任何安全提示交互。
    • 从DOM读取文本并将其放在剪贴板上。
    • 在测试期间~2015年4月,只有Internet Explorer在写入剪贴板时显示权限提示。
    • 请参阅有关重写复制事件的剪贴板API文档。
    • 允许您修改任何复制事件中出现在剪贴板上的内容,可以包括纯文本以外的其他格式的数据。
    • 此处未讨论,因为它没有直接回答问题。

    在控制台中测试代码时,不要指望剪贴板相关命令能正常工作。通常,页面需要处于活动状态(异步剪贴板API),或者需要用户交互(例如用户单击),以允许(document.execcommand('copy'))访问剪贴板,请参阅下面的详细信息。

    请注意,由于这篇文章最初是写的,反对跨源IFRAME和其他IFRAME“沙箱”中的权限,使得嵌入式演示“Run code Snippet”按钮和“codepen.io example”无法在某些浏览器(包括Chrome和Microsoft Edge)中工作。

    要开发和创建您自己的web页面,请通过HTTPS连接为该页面提供服务,以便对其进行测试和开发。

    下面是一个测试/演示页面,它演示了代码的工作原理:https://deanmarktaylor.github.io/clipboard-test/

    由于浏览器对新的Async Clipboard API的支持程度,您可能希望返回到document.execcommand('copy')方法以获得良好的浏览器覆盖率。

    这里有一个简单的例子(嵌入本站点可能无法工作,阅读上面的“重要”注释):

    null

    function fallbackCopyTextToClipboard(text) {
      var textArea = document.createElement("textarea");
      textArea.value = text;
      
      // Avoid scrolling to bottom
      textArea.style.top = "0";
      textArea.style.left = "0";
      textArea.style.position = "fixed";
    
      document.body.appendChild(textArea);
      textArea.focus();
      textArea.select();
    
      try {
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        console.log('Fallback: Copying text command was ' + msg);
      } catch (err) {
        console.error('Fallback: Oops, unable to copy', err);
      }
    
      document.body.removeChild(textArea);
    }
    function copyTextToClipboard(text) {
      if (!navigator.clipboard) {
        fallbackCopyTextToClipboard(text);
        return;
      }
      navigator.clipboard.writeText(text).then(function() {
        console.log('Async: Copying to clipboard was successful!');
      }, function(err) {
        console.error('Async: Could not copy text: ', err);
      });
    }
    
    var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
      copyJaneBtn = document.querySelector('.js-copy-jane-btn');
    
    copyBobBtn.addEventListener('click', function(event) {
      copyTextToClipboard('Bob');
    });
    
    
    copyJaneBtn.addEventListener('click', function(event) {
      copyTextToClipboard('Jane');
    });
    <div style="display:inline-block; vertical-align:top;">
      <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
      <button class="js-copy-jane-btn">Set clipboard to JANE</button>
    </div>
    <div style="display:inline-block;">
      <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:
    
      </textarea>
    </div>

匿名用户

自动复制到剪贴板可能是危险的,因此大多数浏览器(IE除外)让它变得非常困难。就我个人而言,我使用以下简单的诀窍:

function copyToClipboard(text) {
  window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
}

将向用户显示提示框,其中已经选择了要复制的文本。现在只需按Ctrl+CEnter(关闭框)就可以了--瞧!

现在剪贴板复制操作是安全的,因为用户手动完成(但是以一种相当简单的方式)。当然,适用于所有浏览器。

null

<button id="demo" onclick="copyToClipboard(document.getElementById('demo').innerHTML)">This is what I want to copy</button>

<script>
  function copyToClipboard(text) {
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
</script>

匿名用户

以下方法适用于Chrome,Firefox,Internet Explorer和Edge,以及Safari的最新版本(2016年10月发布的第10版增加了复制支持)。

  • 创建文本区域并将其内容设置为要复制到剪贴板的文本。
  • 将文本区域追加到DOM.
  • 选择文本区域中的文本。
  • 调用document.execcommand(“copy”)
  • 从DOM中删除文本区域。

注意:您不会看到textarea,因为它是在Javascript代码的相同同步调用中添加和删除的。

如果您自己执行此操作,请注意以下事项:

  • 出于安全考虑,只能从事件处理程序(如click)调用此函数(就像打开窗口一样)。
  • Internet Explorer将在第一次更新剪贴板时显示权限对话框。
  • Internet Explorer和边缘将在文本区域聚焦时滚动。
  • 在某些情况下可能引发execcommand()。
  • 除非使用文本区,否则换行和制表符会被吞噬。(大多数文章似乎都建议使用div)
  • 显示Internet Explorer对话框时文本区域将可见,您需要隐藏它,或者使用Internet Explorer特定的剪贴板数据API.
  • 在Internet Explorer系统管理员可以禁用剪贴板API.

下面的函数应该尽可能干净地处理以下所有问题。如发现问题或有改进建议,请留言评论。

// Copies a string to the clipboard. Must be called from within an
// event handler such as click. May return false if it failed, but
// this is not always possible. Browser support for Chrome 43+,
// Firefox 42+, Safari 10+, Edge and Internet Explorer 10+.
// Internet Explorer: The clipboard feature may be disabled by
// an administrator. By default a prompt is shown the first
// time the clipboard is used (per session).
function copyToClipboard(text) {
    if (window.clipboardData && window.clipboardData.setData) {
        // Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
        return clipboardData.setData("Text", text);

    }
    else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
        var textarea = document.createElement("textarea");
        textarea.textContent = text;
        textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in Microsoft Edge.
        document.body.appendChild(textarea);
        textarea.select();
        try {
            return document.execCommand("copy");  // Security exception may be thrown by some browsers.
        }
        catch (ex) {
            console.warn("Copy to clipboard failed.", ex);
            return false;
        }
        finally {
            document.body.removeChild(textarea);
        }
    }
}

https://jsfiddle.net/fx6a6n6x/