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...
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["@"].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?
70 Answers
Overview
There are three primary browser APIs for copying to the clipboard:
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.
document.execCommand('copy')(deprecated) 👎- 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.
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.
Must Read
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:
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>
(codepen.io example may not work, read "important" note above) Note that this snippet is not working well in Stack Overflow's embedded preview you can try it here:
Async Clipboard API
- MDN Reference
- Chrome 66 announcement post (March 2018)
- Reference Async Clipboard API draft documentation
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')
The rest of this post goes into the nuances and detail of the document.execCommand('copy') API.