Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
239 views
in Technique[技术] by (71.8m points)

How do I copy to the clipboard in JavaScript?

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

I have tried:

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

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Overview

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

  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 the page.
  • Text can be copied to the clipboard directly from a variable.
  • Only supported on pages served over HTTPS.
  • In Chrome 66 pages inactive tabs can write to the clipboard without a permissions prompt.
  1. document.execCommand('copy')
  • 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.
  1. Overriding the copy event
  • See Clipboard API documentation on Overriding the copy event.
  • Allows you to modify what appears on the clipboard from any copy event, can include other formats of data other than plain text.
  • Not covered here as it doesn't directly answer the question.

General development notes

Don't expect clipboard related commands to work whilst you are 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.

IMPORTANT (noted here 2020/02/20)

Note that since this post was originally written deprecation of permissions in cross-origin IFRAMEs and other IFRAME "sandboxing" prevents the embedded demos "Run code snippet" buttons and "codepen.io example" from working in some browsers (including Chrome and Microsoft Edge).

To develop create your own web page, serve that page over an HTTPS connection to test and develop against.

Here is a test/demo page which demonstrates the code working: https://deanmarktaylor.github.io/clipboard-test/

Async + Fallback

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

Here is a simple example (may not work embedded in this site, read "important" note above):

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...