如何使用JavaScript复制到剪贴板? [英] How do I copy to the clipboard in JavaScript?

查看:123
本文介绍了如何使用JavaScript复制到剪贴板?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the best way to copy text to the clipboard? (multi-browser)

我试过:

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

but in Internet Explorer it gives a syntax error. In Firefox, it says unsafeWindow is not defined.

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

A nice trick without flash: How does Trello access the user's clipboard?

推荐答案

概述



有3个主要的浏览器API可以复制到剪贴板:

Overview

There are 3 primary browser APIs for copying to the clipboard:


  1. Async Clipboard API [navigator.clipboard.writeText]

  1. Async Clipboard API [navigator.clipboard.writeText]
    • Text-focused portion available in Chrome 66 (March 2018)
    • Access is asynchronous and uses JavaScript Promises, can be written so security user prompts (if displayed) don't interrupt the JavaScript in page.
    • Text can be copied to the clipboard directly from a variable.
    • Only supported on pages served over HTTPS.
    • In Chrome 66 pages in active tabs can write to the clipboard without a permissions prompt.

  • 截至2015年4月,大多数浏览器都支持此功能(请参阅下面的浏览器支持)。

  • 访问是同步的,即在页面中停止JavaScript直到完成,包括显示和用户与任何安全提示进行交互。

  • 从中读取文本DOM放置在剪贴板上。

  • 在测试期间〜2015年4月,只有Internet Explorer被注意到在写入剪贴板时显示权限提示。

  • Most browsers support this as of ~April 2015 (see Browser Support below).
  • Access is synchronous, i.e. stops JavaScript in the page until complete including displaying and user interacting with any security prompts.
  • Text is read from the DOM and placed on the clipboard.
  • During testing ~April 2015 only Internet Explorer was noted as displaying permissions prompts whilst writing to the clipboard.

  • 请参阅覆盖复制事件

  • 允许您修改任何复制事件在剪贴板上显示的内容,可以包括纯文本以外的其他格式的数据。

  • 此处未涉及,因为它没有直接回答问题。



一般开发说明



在测试控制台中的代码时,不要指望与剪贴板相关的命令可以正常工作。通常,页面必须是活动的(Async Clipboard API)或需要用户交互(例如用户单击)才能允许( document.execCommand('copy'))访问剪贴板请参阅下面的详细信息。

General development notes

Don't expect clipboard related commands to work whilst you testing code in the console. Generally the page is required to be active (Async Clipboard API) or requires user interaction (e.g. a user click) to allow (document.execCommand('copy')) to access the clipboard see below for more detail.

由于浏览器支持的水平新的Async Clipboard API您可能希望回退到 document.execCommand('copy')方法以获得良好的浏览器覆盖率。

Due to the level of browser support for the new Async Clipboard API you will likely want to fallback to the document.execCommand('copy') method to get good browser coverage.

这是一个简单的例子:

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  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>

请注意,此片段在StackOverflow的嵌入式预览中效果不佳您可以试试这里:
https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors = 1011

Note that this snippet is not working well in StackOverflow's embedded preview you can try it here: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

  • Chrome 66 announcement post (March 2018)
  • Reference Async Clipboard API draft documentation

请注意,可以通过Chrome 66中的权限API请求权限并测试访问剪贴板。

Note that there is an ability to "request permission" and test for access to the clipboard via the permissions API in Chrome 66.

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});



document.execCommand('copy')



本文的其余部分介绍了 document.execCommand('copy') API的细微差别和细节。

document.execCommand('copy')

The rest of this post goes into the nuances and detail of the document.execCommand('copy') API.

JavaScript document.execCommand('copy') 支持已经增长,请参阅以下链接了解浏览器更新:

The JavaScript document.execCommand('copy') support has grown, see the links below for browser updates:

  • IE10+ (although this document indicates some support was there from IE5.5+).
  • Google Chrome 43+ (~April 2015)
  • Mozilla Firefox 41+ (shipping ~September 2015)
  • Opera 29+ (based on Chromium 42, ~April 2015)

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');

copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
});

<p>
  <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
  <textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>

如果存在<$>上述简单示例效果很好c $ c> textarea 或输入元素在屏幕上可见。

The above simple example works great if there is a textarea or input element visible on screen.

在某些情况下,您可能希望将文本复制到剪贴板而不显示输入 / textarea 元素。这是解决此问题的一个示例(基本上是插入元素,复制到剪贴板,删除元素):

In some cases you might wish to copy text to the clipboard without displaying an input / textarea element. This is one example of a way to work around this (basically insert element, copy to clipboard, remove element):

使用Google Chrome 44,Firefox 42.0a1和IE进行测试11.0.8600.17814。

Tested with Google Chrome 44, Firefox 42.0a1 and IE 11.0.8600.17814.

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");

  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a flash,
  // so some of these are just precautions. However in IE the element
  // is visible whilst the popup box asking the user for permission for
  // the web page to copy to the clipboard.
  //

  // Place in top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;

  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';

  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;

  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';

  // Avoid flash of white box if rendered for any reason.
  textArea.style.background = 'transparent';


  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  document.body.removeChild(textArea);
}


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>

所有 document.execCommand('copy')必须进行调用作为用户动作的直接结果,例如点击事件处理程序这是一种措施,可以防止在用户剪贴板不期望时将其弄乱。

All document.execCommand('copy') calls must take place as a direct result of a user action, e.g. click event handler. This is a measure to prevent messing with the users clipboard when they don't expect it.

请参阅 Google Developers在此发布以获取更多信息。

See the Google Developers post here for more info.

注意完整的剪贴板API草案规范可以在这里找到:
https://w3c.github.io/clipboard-apis/

Note the full Clipboard API draft specification can be found here: https://w3c.github.io/clipboard-apis/


  • document.queryCommandSupported('copy')应返回 true 如果命令受浏览器支持。

  • document.queryCommandEnabled('copy') return true 如果现在调用 document.execCommand('copy')将成功。检查以确保从用户启动的线程调用该命令并满足其他要求。

  • document.queryCommandSupported('copy') should return true if the command "is supported by the browser".
  • and document.queryCommandEnabled('copy') return true if the document.execCommand('copy') will succeed if called now. Checking to ensure the command was called from a user-initiated thread and other requirements are met.

然而,作为浏览器兼容性问题的示例,Google Chrome从2015年4月到10月仅从 document.queryCommandSupported('copy')返回 true 命令是从用户发起的线程调用的。

However as an example of browser compatibility issues, Google Chrome from ~April to ~October 2015 only returned true from document.queryCommandSupported('copy') if the command was called from a user-initiated thread.

注意下面的兼容性详细信息。

Note compatibility detail below.

虽然简单地调用 document.execCommand('copy')包裹在中尝试 / catch 由于用户点击而调用的块将获得最大的兼容性使用以下有一些附带条件:

Whilst a simple call to document.execCommand('copy') wrapped in a try/catch block called as a result of a user click will get you the most compatibility use the following has some provisos:

document.execCommand document.queryCommandSupported document.queryCommandEnabled 应该包含在 try / catch 块中。

Any call to document.execCommand, document.queryCommandSupported or document.queryCommandEnabled should be wrapped in a try/catch block.

不同的浏览器实现ns和浏览器版本在调用时抛出不同类型的异常,而不是返回 false

Different browser implementations and browser versions throw differing types of exceptions when called instead of returning false.

不同的浏览器实现仍在flux和 Clipboard API 仍在草稿中,所以请记住进行测试。

Different browser implementations are still in flux and the Clipboard API is still in draft, so remember to do your testing.

这篇关于如何使用JavaScript复制到剪贴板?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆