Skip to content

Instantly share code, notes, and snippets.

@lgarron
Last active December 20, 2023 12:53
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save lgarron/d1dee380f4ed9d825ca7 to your computer and use it in GitHub Desktop.
Save lgarron/d1dee380f4ed9d825ca7 to your computer and use it in GitHub Desktop.
Simple `navigator.clipboard.writeText()` polyfill.
<script>
// A minimal polyfill for copying text to clipboard that works most of the time in most capable browsers.
// Note that:
// - You may not need this. `navigator.clipboard.writeText()` works directly in all modern browsers as of 2020.
// - In Edge, this may call `resolve()` even if copying failed.
// - In Safari, this may fail if there is nothing selected on the page.
// See https://github.com/lgarron/clipboard-polyfill for a more robust solution.
//
// License for this Gist: public domain / Unlicense
function writeText(str) {
return new Promise(function(resolve, reject) {
var success = false;
function listener(e) {
e.clipboardData.setData("text/plain", str);
e.preventDefault();
success = true;
}
document.addEventListener("copy", listener);
document.execCommand("copy");
document.removeEventListener("copy", listener);
success ? resolve(): reject();
});
};
</script>
<button onclick="writeText(this.textContent)">Copy me!</button>
@asumaran
Copy link

Doesn't work on Safari 12.0.1 (14606.2.104.1.1)

I get Unhandled Promise Rejection: undefined every time I click the button

@Offirmo
Copy link

Offirmo commented Jun 4, 2019

Still not working in Safari latest = 12.1.1 at this time

@lgarron
Copy link
Author

lgarron commented Jun 4, 2019

Still not working in Safari latest = 12.1.1 at this time

In Safari, you need to have part of the document selected for this to work. :-/

A simple workaround is to do this:

<script>
// A minimal polyfill for `navigator.clipboard.writeText()` that works most of the time in most modern browsers.
// Note that on Edge this may call `resolve()` even if copying failed.
// See https://github.com/lgarron/clipboard-polyfill for a more robust solution.
// License: public domain
function writeText(str) {
  return new Promise(function(resolve, reject) {

    /********************************/
    var range = document.createRange();
    range.selectNodeContents(document.body);
    document.getSelection().addRange(range);
    /********************************/

    var success = false;
    function listener(e) {
      e.clipboardData.setData("text/plain", str);
      e.preventDefault();
      success = true;
    }
    document.addEventListener("copy", listener);
    document.execCommand("copy");
    document.removeEventListener("copy", listener);

    /********************************/
    document.getSelection().removeAllRanges();
    /********************************/

    success ? resolve(): reject();
  });
};
</script>

<button onclick="writeText(this.textContent, console.error)">Copy me!</button>

However, this adds a non-trivial amount of code to this "simple" snippet and clears the current selection every time in all browsers. I recommend a library if you want reliable logic in all browsers (this is why I maintain https://github.com/lgarron/clipboard-polyfill !).

@Offirmo
Copy link

Offirmo commented Jun 4, 2019

Thanks. I just wanted to evaluate if this gist could be a lighter alternative to the full polyfill for just writing to the clipboard.

@khamiltonuk
Copy link

Doesn't work on Safari 12.0.1 (14606.2.104.1.1)

I get Unhandled Promise Rejection: undefined every time I click the button

I was getting the same error because I was on http and safari wants a https connection
https://portswigger.net/daily-swig/new-safari-clipboard-api-includes-additional-browser-security-privacy-mechanisms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment