3730

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?

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Santiago Corredoira
  • 40,844
  • 8
  • 48
  • 56
  • Just curious, what is it that you want to copy to the clipboard that the user can't do themselves? – scunliffe Dec 30 '08 at 16:52
  • 272
    Nothing special. They can do it by themselves but I want to offer also the possibility of clicking a button without worrying about selecting the correct portion of text. – Santiago Corredoira Dec 31 '08 at 00:03
  • 6
    This long blog post contains a lot of ways to do this: [Accessing the System Clipboard with JavaScript – A Holy Grail?](http://brooknovak.wordpress.com/2009/07/28/accessing-the-system-clipboard-with-javascript/) – Aaron Digulla Apr 21 '11 at 08:26
  • 1
    It is giving browser undefined exception in IE as well as in FF – Jagadeesh Feb 22 '13 at 07:43
  • 3
    If we can put text into the user's clipboard, we can ruin his clipboard. – Frank Fang Jun 11 '14 at 12:15
  • This still isn't perfectly supported. You can see support on [Can I use Clipboard API](http://caniuse.com/#feat=clipboard)? which details support for the [W3C Clipboard APIs document](http://www.w3.org/TR/clipboard-apis/). – mkobit Apr 28 '15 at 21:47
  • @Mike it probably never will because of the security implications. – Santiago Corredoira Apr 30 '15 at 09:12
  • I created an easy to use Angular library [ngxyz-c2c](https://www.npmjs.com/package/ngxyz-c2c) if you guys want it. – Ankit Singh Dec 12 '19 at 21:32
  • Personaly, I prefer 3rd party such as clipboardjs. clipboardjs: https://clipboardjs.com/ vue-clipboards: https://zhuowenli.github.io/vue-clipboards/ v-clipboard: https://vuejsexamples.com/a-clipboard-library-with-vue-js/ – 4givN Jan 23 '20 at 08:49

62 Answers62

2678

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.
  2. 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.
  3. 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>

(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: https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

Async Clipboard 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')

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

Browser Support

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

Simple Example

(may not work embedded in this site, read "important" note above)

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>

Complex Example: Copy to clipboard without displaying input

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

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 an element, copy to clipboard, remove element):

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

(may not work embedded in this site, read "important" note above)

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 the 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
  // Internet Explorer the element is visible whilst the popup
  // box asking the user for permission for the web page to
  // copy to the clipboard.
  //

  // Place in the 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 the 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>

Additional notes

Only works if the user takes an action

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 user's clipboard when they don't expect it.

See the Google Developers post here for more info.

Clipboard API

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

Is it supported?

  • 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.

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.

Browser Compatibility Detail

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:

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

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

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

H. Pauwelyn
  • 11,346
  • 26
  • 71
  • 115
Dean Taylor
  • 32,609
  • 2
  • 24
  • 47
  • 18
    Sorry to break the party , but `document.execCommand is obsolete`. See https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand – tnkh Oct 12 '20 at 05:41
  • @tnkh sure, but the replacement (Clipboard API) isn't fully baked and supported yet. – forresto May 03 '21 at 07:16
1304

Automatic copying to the clipboard may be dangerous, and therefore most browsers (except Internet Explorer) make it very difficult. Personally, I use the following simple trick:

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

The user is presented with the prompt box, where the text to be copied is already selected. Now it's enough to press Ctrl + C and Enter (to close the box) -- and voila!

Now the clipboard copy operation is safe, because the user does it manually (but in a pretty straightforward way). Of course, it works in all browsers.

<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>
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Jarek Milewski
  • 14,409
  • 1
  • 12
  • 2
  • 16
    But there is a limit on the amount of characters displayed in that dialog, and thus there is a limit on the amount of data to be copied. – Denilson Sá Maia Sep 04 '11 at 02:32
  • 96
    Clever, but this only supports single line. – Aram Kocharyan Oct 23 '11 at 08:56
  • 63
    It's trivial to change the "prompt" function to a custom modal, the meat of the trick is to use an editable content field and pre-select the text, and that it doesn't break the browser UI by enforcing that the user take the action themselves. A++ – Jon z Jan 17 '12 at 18:57
  • 1
    *"... prompt box, where the text to be copied is already selected"* - but how do you assure that the text in the prompt box is already selected? – Tomas Feb 17 '12 at 13:44
  • First of all, slick solution =] But couldn't this functionality be replicated without js? (Not as simply of course.) – b1nary.atr0phy Oct 01 '12 at 23:23
  • 24
    If your text is over 2000 characters it will be truncated, but for smaller text samples it works great – RasTheDestroyer Sep 04 '13 at 18:51
  • 9
    @RasTheDestroyer - Truncation at 2k chars seems to be a Chrome issue, but it's good to know regardless – Marcus Pope Sep 18 '13 at 23:19
  • 2
    @AramKocharyan I tried newlines in chrome and IE and both worked for me, it presents it without newlines but when you paste the info into an editor the newlines are preserved - IE10 & Chrome29 anyway – Marcus Pope Sep 18 '13 at 23:20
  • 2
    Its so simple way to do it..Thanks..But the text is not pr selected..is there any way to preselect the text? – Dibish Dec 13 '13 at 11:08
  • Doesn't work in Firefox 25.0 on OS X. I get the prompt, but the text field is empty. In Chrome it works. – borisdiakur Dec 18 '13 at 11:04
  • 2
    @Qix It has 579 votes because there is no way to do it with pure JavaScript, as far as I know (unless your only target is IE). Sites do it "all the time" using Flash. – cubuspl42 May 12 '14 at 16:28
  • For mobile, in Chrome, when I select the text in the prompt it apparently doesn't allow me to copy, just cut. – gab06 Sep 08 '20 at 23:06
  • Why not just using and function selectText() { const input = document.getElementById('text-box'); input.focus(); input.select(); } I think it quicker. – G M Apr 28 '21 at 08:19
385

The following approach works in Chrome, Firefox, Internet Explorer and Edge, and in recent versions of Safari (copy support was added in version 10 which was released Oct 2016).

  • Create a textarea and set its contents to the text you want copied to the clipboard.
  • Append the textarea to the DOM.
  • Select the text in the textarea.
  • Call document.execCommand("copy")
  • Remove the textarea from the dom.

Note: you will not see the textarea, as it is added and removed within the same synchronous invocation of Javascript code.

Some things to watch out for if you are implementing this yourself:

  • For security reasons, this can only called from an event handler such as click (Just as with opening windows).
  • Internet Explorer will show a permission dialog the first time the clipboard is updated.
  • Internet Explorer, and Edge will scroll when the textarea is focused.
  • execCommand() may throw in some cases.
  • Newlines and tabs can get swallowed unless you use a textarea. (Most articles seem to recommend using a div)
  • The textarea will be visible while the Internet Explorer dialog is shown, you either need to hide it, or use the Internet Explorer specific clipboardData API.
  • In Internet Explorer system administrators can disable the clipboard API.

The function below should handle all of the following issues as cleanly as possible. Please leave a comment if you find any problems or have any suggestions for improving it.

// 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 window.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/

Geoffrey Hale
  • 8,152
  • 4
  • 34
  • 42
Greg Lowe
  • 11,582
  • 2
  • 23
  • 32
  • 12
    Nice answer : cross browser support, error handling + clean up. As of today's new support for queryCommandSupported, copying to clipboard is now feasible in Javascript and this should be the accepted answer, instead of awkward 'window.prompt("Copy to clipboard: Ctrl+C, Enter", text)' workaround. window.clipboardData is supported in IE9, so you should add IE9 in the browser support list and I think maybe IE8 and previous also, but need to verify. – user627283 Dec 01 '15 at 17:38
  • Yeah. IE 8/9 Should be ok. Our app doesn't support them. So I haven't tested. IE stops support in Jan, so I'm not too fussed. Hopefully Safari support will land soon. I'm sure it's on their radar. – Greg Lowe Dec 01 '15 at 22:08
  • 6
    @SantiagoCorredoira: In 2016, this deserves to be the accepted answer. Please consider reassigning the BGT (big green tick). – Lawrence Dol Apr 22 '16 at 01:25
  • @drooh It is supported in Safari 10+. Safari 10 is still in beta. It will be released with the MacOS 10.12 (probably in October). – Greg Lowe Aug 02 '16 at 01:43
  • textarea.select() does not work for me on Chrome. The function exists but the contents of the text area do not actually get into the clipboard – mwag May 09 '17 at 19:21
  • Did you try the code in JS Fiddle? https://jsfiddle.net/fx6a6n6x/ This works for me in chrome and canary on MacOS. – Greg Lowe May 09 '17 at 22:54
  • If focus is not in the html document, like say you just clicked Windows task bar, and then you click the Copy button in your html document, the function returns `true` but it fails to copy. This was the case in Firefox 55 for me today. But thanks for sharing this, I am using it, very much appreciated. – Noitidart Aug 07 '17 at 00:16
  • 3
    @Noitidart I Tested and it works perfectly for firefox 54, chrome 60 and edge browser, even when focus is not in the html document, the error you're having is probably specific to version FF 55 – Tosin John Aug 12 '17 at 01:01
  • Thanks @TosinJohn - may you please open the dev tools, then focus that, then with your first click - click the ` – Noitidart Aug 12 '17 at 04:59
  • 2
    @Noitidart It still works perfectly here, focusing on dev tools didn't stop it. And by the way, what will a normal web app user be doing on developer tools – Tosin John Aug 12 '17 at 16:48
  • Thanks @TosinJohn - this is very interesting. I don't know why my first copy is failing. Thanks so much for that test. Yes true they might not be in dev tools, but they may have two windows next to each other and click from one window into my web app (first click being on the copy). – Noitidart Aug 12 '17 at 17:26
  • the command:clipboardData,setData ("Text",text) doesn't copy formatted text, so, for example, if you copied a text containing several lines (with new line chars as separators), the new line char won't be part of the copied string, and instead you'll get one long string – shayuna Mar 04 '18 at 11:14
  • **jQuery UI users**: Note that you'll run into problems with this method if you try to use this function from within a modal dialog box. I suspect it's because the jQuery UI modal is managing/manipulating the document focus. If it fits your use case, one workaround is to close the modal dialog first and then copy the text. Or, to simply use a non-modal dialog box. I suspect you may also be able to modify this function so it adds the textarea to the modal instead of to the body. – rinogo Dec 31 '18 at 20:30
  • i'm probably asking the wrong questions in the wrong place, but feel like trying it anyway... could this be made into a two liner, by using some sort of trusted always updated import from gitlab or something? – cregox Sep 19 '19 at 07:52
  • needs a fix, there's a great "if" guard to check that window.clipboardData.setData is available, but then if it passes the code bypasses window and hits "clipboardData" direct! I added code asis to a CRA and it splatted, just needs window. prefix – Andy Lorenz Jun 16 '20 at 16:26
141

Here is my take on that one...

function copy(text) {
    var input = document.createElement('input');
    input.setAttribute('value', text);
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
 }

@korayem: Note that using html input field won't respect line breaks \n and will flatten any text into a single line.

As mentioned by @nikksan in the comments, using textarea will fix the problem as follows:

function copy(text) {
    var input = document.createElement('textarea');
    input.innerHTML = text;
    document.body.appendChild(input);
    input.select();
    var result = document.execCommand('copy');
    document.body.removeChild(input);
    return result;
}
Korayem
  • 10,709
  • 5
  • 65
  • 52
nikksan
  • 2,699
  • 2
  • 16
  • 25
90

Reading and modifying the clipboard from a webpage raises security and privacy concerns. However, in Internet Explorer, it is possible to do it. I found this example snippet:

    <script type="text/javascript">
        function select_all(obj) {
            var text_val=eval(obj);
            text_val.focus();
            text_val.select();
            r = text_val.createTextRange();
            if (!r.execCommand) return; // feature detection
            r.execCommand('copy');
        }
    </script>
    <input value="http://www.sajithmr.com"
     onclick="select_all(this)" name="url" type="text" />
bandi
  • 4,028
  • 1
  • 23
  • 24
  • 7
    Using flash for a simple copy operation seems like overkill, glad there was a clean JS way to do this. And since we are in a corporate env. IE is just fine. Thanks Bandi! – Eddie Jan 26 '11 at 15:10
  • 5
    plz explain what `execCommand(\\’copy\\’);` does, if not copy to clipboard for IE ? @mrBorna – RozzA Apr 24 '12 at 18:02
  • 20
    Do not use `if(!document.all)` but `if(!r.execCommand)` lest anybody else implements it! Document.all is absolutely non-relevant to this. – m93a Apr 15 '13 at 18:24
  • How come these privacy concerns were never raised for a decade when people were using Flash to alter the clipboard? And if we only allow one way (i-e copying, and not reading its content) how does that generate a privacy concern? – Muhammad bin Yusrat Jun 06 '15 at 11:35
  • @MuhammadbinYusrat: Although not a privacy concern, it _is_ a UX concern. Consider that the user has copied something and think he knows what is on the clipboard, then browsing your site, and suddenly the clipboard contains something he hasn't asked for, and he has lost what he copied in the first place. – awe Oct 02 '15 at 12:01
86

If you want a really simple solution (takes less than 5 minutes to integrate) and looks good right out of the box, then Clippy is a nice alternative to some of the more complex solutions.

It was written by a cofounder of GitHub. Example Flash embed code below:

<object
    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
    width="110"
    height="14"
    id="clippy">

    <param name="movie" value="/flash/clippy.swf"/>
    <param name="allowScriptAccess" value="always"/>
    <param name="quality" value="high"/>
    <param name="scale" value="noscale"/>
    <param NAME="FlashVars" value="text=#{text}"/>
    <param name="bgcolor" value="#{bgcolor}"/>
    <embed
        src="/flash/clippy.swf"
        width="110"
        height="14"
        name="clippy"
        quality="high"
        allowScriptAccess="always"
        type="application/x-shockwave-flash"
        pluginspage="http://www.macromedia.com/go/getflashplayer"
        FlashVars="text=#{text}"
        bgcolor="#{bgcolor}"/>
</object>

Remember to replace #{text} with the text you need copied, and #{bgcolor} with a color.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Brent Matzelle
  • 3,715
  • 3
  • 24
  • 26
  • 13
    For anyone interested, check Clippy being used on GitHub when copying the URL for the repo. – Radek May 23 '11 at 11:19
74

I have recently written a technical blog post on this very problem (I work at Lucidchart and we recently did an overhaul on our clipboard).

Copying plain text to the clipboard is relatively simple, assuming you attempt to do it during a system copy event (user presses Ctrl + C or uses the browser's menu).

var isIe = (navigator.userAgent.toLowerCase().indexOf("msie")    != -1 ||
            navigator.userAgent.toLowerCase().indexOf("trident") != -1);

document.addEventListener('copy', function(e) {
    var textToPutOnClipboard = "This is some text";
    if (isIe) {
        window.clipboardData.setData('Text', textToPutOnClipboard);
    } else {
        e.clipboardData.setData('text/plain', textToPutOnClipboard);
    }
    e.preventDefault();
});

Putting text on the clipboard not during a system copy event is much more difficult. It looks like some of these other answers reference ways to do it via Flash, which is the only cross-browser way to do it (so far as I understand).

Other than that, there are some options on a browser-by-browser basis.

This is the most simple in Internet Explorer, where you can access the clipboardData object at anytime from JavaScript via:

window.clipboardData

(When you attempt to do this outside of a system cut, copy, or paste event, however, Internet Explorer will prompt the user to grant the web application clipboard permission.)

In Chrome, you can create a Chrome extension that will give you clipboard permissions (this is what we do for Lucidchart). Then for users with your extension installed you'll just need to fire the system event yourself:

document.execCommand('copy');

It looks like Firefox has some options that allow users to grant permissions to certain sites to access the clipboard, but I haven't tried any of these personally.

Richard Shurtz
  • 1,443
  • 13
  • 11
  • 3
    Not mentioned in the blog post (I'm hoping to update it in the near future), is the ability to trigger cut and copy using execCommand. This is supported in IE10+, Chrome 43+, and Opera29+. Read about it here. http://updates.html5rocks.com/2015/04/cut-and-copy-commands – Richard Shurtz May 20 '15 at 21:30
  • A problem with this is that it hijacks other normal copy events. – Brock Adams Feb 04 '17 at 05:32
  • NB! This browser sniffing is BAD. Do feature sniffing. You're making it hard for IE to update. – odinho - Velmont Dec 03 '18 at 11:31
70

I like this one:

<input onclick="this.select();" type='text' value='copy me' />

If a user doesn't know how to copy text in their OS, then it's likely they don't know how to paste either. So just have it automatically selected, leaving the rest to the user.

Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
Matthew Scragg
  • 3,886
  • 3
  • 17
  • 26
56

clipboard.js is a small, non-Flash, utility that allows copying of text or HTML data to the clipboard. It's very easy to use, just include the .js and use something like this:

<button id='markup-copy'>Copy Button</button>

<script>
document.getElementById('markup-copy').addEventListener('click', function() {
  clipboard.copy({
    'text/plain': 'Markup text. Paste me into a rich text editor.',
    'text/html': '<i>here</i> is some <b>rich text</b>'
  }).then(
    function(){console.log('success'); },
    function(err){console.log('failure', err);
  });

});
</script>

clipboard.js is also on GitHub.

Note: This has been deprecated now. Migrate to here.

bsound
  • 722
  • 7
  • 16
a coder
  • 6,796
  • 19
  • 77
  • 121
  • This library is used by angular.io for its Tour of Hero and fallback in graceful mode for browser not supporting execCommand by displaying a preselected text the user has just to copy. – John-Philip Jan 30 '17 at 14:43
  • 1
    Looks either clipboard.js has been replaced, or forked, but it seems to live on and is actively maintained at https://www.npmjs.com/package/clipboard – Joao Jun 18 '19 at 22:19
37

In 2018, here's how you can go about it:

async copySomething(text?) {
  try {
    const toCopy = text || location.href;
    await navigator.clipboard.writeText(toCopy);
    console.log('Text or Page URL copied');
  }
  catch (err) {
    console.error('Failed to copy: ', err);
  }
}

It is used in my Angular 6+ code like so:

<button mat-menu-item (click)="copySomething()">
    <span>Copy link</span>
</button>

If I pass in a string, it copies it. If nothing, it copies the page's URL.

More gymnastics to the clipboard stuff can be done too. See more information here:

Unblocking Clipboard Access

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
KhoPhi
  • 7,701
  • 11
  • 70
  • 115
34

ZeroClipboard is the best cross-browser solution I've found:

<div id="copy" data-clipboard-text="Copy Me!">Click to copy</div>
<script src="ZeroClipboard.js"></script>
<script>
  var clip = new ZeroClipboard( document.getElementById('copy') );
</script>

If you need non-Flash support for iOS you just add a fall-back:

clip.on( 'noflash', function ( client, args ) {
    $("#copy").click(function(){
        var txt = $(this).attr('data-clipboard-text');
        prompt ("Copy link, then click OK.", txt);
    });
});

http://zeroclipboard.org/

https://github.com/zeroclipboard/ZeroClipboard

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Justin
  • 22,998
  • 16
  • 104
  • 122
  • 26
    cross-browser with Flash ? not working in iOS and Android 4.4 – Raptor Jan 27 '14 at 10:29
  • 1
    See updated answer. This allows less steps for flash-users and a fall-back for everyone else. – Justin Jan 27 '14 at 17:38
  • 10
    it has a billion lines of code. it's absolutely ridicules. better not to do it at all than including such a monster in a project – vsync Oct 27 '14 at 11:25
  • 2
    There is a simple version https://gist.github.com/JamesMGreene/8698897 that is 20K that doesn't have all the bells and whistles in the 74k version. Neither is very large. My guess is most users are okay with the extra milliseconds that a 74k or a 20k file being downloaded will take so copy/paste is one click instead of two. – Justin Oct 27 '14 at 15:35
  • @Justin I just can't make it work locally, even if I copy&paste the examples (I make minimum changes, e.g. the value of `src` in script tags). I feel that their documentation is pretty but inefficient. – Gui Imamura Jul 23 '15 at 13:47
28

Since Chrome 42+ and Firefox 41+ now support the document.execCommand('copy') command, I created a couple of functions for a cross-browser copy-to-clipboard ability using a combination of Tim Down's old answer and Google Developer's answer:

function selectElementContents(el) {
    // Copy textarea, pre, div, etc.
    if (document.body.createTextRange) {
        // Internet Explorer
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.select();
        textRange.execCommand("Copy");
    }
    else if (window.getSelection && document.createRange) {
        // Non-Internet Explorer
        var range = document.createRange();
        range.selectNodeContents(el);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
        try {
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            console.log('Copy command was ' + msg);
        }
        catch (err) {
            console.log('Oops, unable to copy');
        }
    }
} // end function selectElementContents(el)

function make_copy_button(el) {
    var copy_btn = document.createElement('input');
    copy_btn.type = "button";
    el.parentNode.insertBefore(copy_btn, el.nextSibling);
    copy_btn.onclick = function() {
        selectElementContents(el);
    };

    if (document.queryCommandSupported("copy") || parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 42) {
        // Copy works with Internet Explorer 4+, Chrome 42+, Firefox 41+, Opera 29+
        copy_btn.value = "Copy to Clipboard";
    }
    else {
        // Select only for Safari and older Chrome, Firefox and Opera
        copy_btn.value = "Select All (then press Ctrl + C to Copy)";
    }
}
/* Note: document.queryCommandSupported("copy") should return "true" on browsers that support copy,
    but there was a bug in Chrome versions 42 to 47 that makes it return "false".  So in those
    versions of Chrome feature detection does not work!
    See https://code.google.com/p/chromium/issues/detail?id=476508
*/

make_copy_button(document.getElementById("markup"));
<pre id="markup">
  Text that can be copied or selected with cross browser support.
</pre>
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Jeff Baker
  • 1,232
  • 1
  • 10
  • 12
  • Thanks for summing this up! You have a little mistakes in your code: you defined the "range" variable twice (var range = document.createRange()). – Christian Engel Nov 17 '15 at 08:59
  • 1
    You are correct @ChristianEngel . I have removed the second one. I don't know how it got in there. – Jeff Baker Nov 19 '15 at 02:11
26

I use this very successfully (without jQuery or any other framework).

function copyToClp(txt){
    var m = document;
    txt = m.createTextNode(txt);
    var w = window;
    var b = m.body;
    b.appendChild(txt);
    if (b.createTextRange) {
        var d = b.createTextRange();
        d.moveToElementText(txt);
        d.select();
        m.execCommand('copy');
    } 
    else {
        var d = m.createRange();
        var g = w.getSelection;
        d.selectNodeContents(txt);
        g().removeAllRanges();
        g().addRange(d);
        m.execCommand('copy');
        g().removeAllRanges();
    }
    txt.remove();
}

Warning

Tabs are converted to spaces (at least in Chrome).

Grim
  • 4,939
  • 8
  • 46
  • 97
25

From one of the projects I've been working on, a jQuery copy-to-clipboard plugin that utilizes the ZeroClipboard library.

It is easier to use than the native Zero Clipboard plugin if you're a heavy jQuery user.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
SteamDev
  • 447
  • 4
  • 4
  • jQuery doesn't count as a legit answer to a JavaScript question as it's not only bloated it uses unreliable proprietary Microsoft JScript methods like innerHTML that do not correctly register the DOM. – John Feb 23 '12 at 15:50
  • 6
    92kb isn't all that big really, it works fast & you can use `text()` instead of `innerHTML()` if you like.. – RozzA Apr 24 '12 at 17:59
  • 17
    @John: `innerHTML` has been supported cross-browser for a long time now. Just because Microsoft originally came up with the idea it doesn't make it unreliable or proprietary. It is also now _finally_ being added to the official spec (after every major browser vendor already added support for it... _sigh_). – James M. Greene Jan 17 '13 at 16:43
  • 19
    @John You complain about jQuery not being JavaScripty enough in an answer that uses Flash ;) – Max Nanasy Apr 19 '13 at 02:12
  • There are plenty of things that are standardized that should not. If you decide to use maybe code that MIGHT work and MIGHT NOT then it's your gamble, not mine. People who actually care about their work will always be looking out to improve their skills, their understanding, themselves versus justifying something that is easy to use but also easy to break. Really, doing it the right way use real standards isn't difficult and people can either do things right now or pile on more hassles down the road. – John Apr 19 '13 at 21:15
  • 4
    innerHTML is better than alternatives in most cases. Get off your high horse! It is faster, more efficient and doesn't require a page re-render. – Orbiting Eden Jun 18 '13 at 19:13
  • 4
    @RozzA `92KB` is really big. Until [LTE](https://en.wikipedia.org/wiki/LTE_%28telecommunication%29) matures [GPRS](https://en.wikipedia.org/wiki/General_Packet_Radio_Service) is the [WW mobile data standard](http://www.track-earth.com/gsm.html), and it starts at `1 KB/s`. Do the math yourself. – Tino Aug 02 '13 at 07:26
  • Here is a minimalistic usage of ZeroClipboard JS library: http://jsfiddle.net/N36uH/ – Adrien Be Jun 18 '14 at 11:40
  • ["GitHub Replaces Copy And Paste With ZeroClipboard" article on TechCrunch](http://techcrunch.com/2013/01/02/github-replaces-copy-and-paste-with-zeroclipboard/) – Adrien Be Jun 18 '14 at 11:46
  • Here are 2 other simple examples to get started http://jsfiddle.net/c3DUZ/ and http://jsfiddle.net/69RLv/ – Adrien Be Jun 18 '14 at 12:20
  • @AdrienBe none of your examples work for me in either Firefox or Chrome – bhan Apr 03 '15 at 23:04
  • @AdrienBe They don't work here either. No errors on console, just warnings. Most of them are from `jshint.js` – Gui Imamura Jul 23 '15 at 13:57
  • @GuiImamura and bhan: sorry guys I not able to help for now. Try the demo on the ZeroClipboard page and see if you can use that code to get started. – Adrien Be Jul 24 '15 at 01:34
  • 1
    The page linked is now dead, with only some scam-vertising junk – MightyPork Mar 21 '16 at 21:54
24

I've put together what I think is the best one.

  • Uses cssText to avoid exceptions in Internet Explorer as opposed to style directly.
  • Restores selection if there was one
  • Sets read-only so the keyboard doesn't come up on mobile devices
  • Has a workaround for iOS so that it actually works as it normally blocks execCommand.

Here it is:

const copyToClipboard = (function initClipboardText() {
  const textarea = document.createElement('textarea');

  // Move it off-screen.
  textarea.style.cssText = 'position: absolute; left: -99999em';

  // Set to readonly to prevent mobile devices opening a keyboard when
  // text is .select()'ed.
  textarea.setAttribute('readonly', true);

  document.body.appendChild(textarea);

  return function setClipboardText(text) {
    textarea.value = text;

    // Check if there is any content selected previously.
    const selected = document.getSelection().rangeCount > 0 ?
      document.getSelection().getRangeAt(0) : false;

    // iOS Safari blocks programmatic execCommand copying normally, without this hack.
    // https://stackoverflow.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
      const editable = textarea.contentEditable;
      textarea.contentEditable = true;
      const range = document.createRange();
      range.selectNodeContents(textarea);
      const sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
      textarea.setSelectionRange(0, 999999);
      textarea.contentEditable = editable;
    }
    else {
      textarea.select();
    }

    try {
      const result = document.execCommand('copy');

      // Restore previous selection.
      if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
      }

      return result;
    }
    catch (err) {
      console.error(err);
      return false;
    }
  };
})();

Usage: copyToClipboard('some text')

Andhi Irawan
  • 404
  • 6
  • 13
Dominic
  • 48,717
  • 14
  • 109
  • 126
24

    $("td").click(function (e) {
        var clickedCell = $(e.target).closest("td");
        navigator.clipboard.writeText(clickedCell.text());
        alert(clickedCell.text());
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>First<td>
</tr>
<tr>
<td>Second<td>
</tr>
<tr>
<td>Third<td>
</tr>
<tr>
<td>Fourth<td>
</tr>
</table>

I've read all the answers, as of June 1st, 2020, I've beeen struggling to solve this when I finally found documentation:

$("td").click(function (e) {
    var clickedCell = $(e.target).closest("td");
    navigator.clipboard.writeText(clickedCell.text());
});

It will write the clicked cell text to the browser clipboard.

You can change the selectors "td" for anything you want, you can add console.log for debugging and/or alert functions.

Here is documentation: https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText

SanTasso
  • 351
  • 2
  • 3
22

I found the following solution:

The on-key-down handler creates a "pre" tag. We set the content to copy to this tag, and then make a selection on this tag and return true in the handler. This calls the standard handler of Chrome and copies selected text.

And if you need it, you may set the timeout for a function for restoring the previous selection. My implementation on MooTools:

function EnybyClipboard() {
    this.saveSelection = false;
    this.callback = false;
    this.pastedText = false;

    this.restoreSelection = function() {
        if (this.saveSelection) {
            window.getSelection().removeAllRanges();
            for (var i = 0; i < this.saveSelection.length; i++) {
                window.getSelection().addRange(this.saveSelection[i]);
            }
            this.saveSelection = false;
        }
    };

    this.copyText = function(text) {
        var div = $('special_copy');
        if (!div) {
            div = new Element('pre', {
                'id': 'special_copy',
                'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
            });
            div.injectInside(document.body);
        }
        div.set('text', text);
        if (document.createRange) {
            var rng = document.createRange();
            rng.selectNodeContents(div);
            this.saveSelection = [];
            var selection = window.getSelection();
            for (var i = 0; i < selection.rangeCount; i++) {
                this.saveSelection[i] = selection.getRangeAt(i);
            }
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(rng);
            setTimeout(this.restoreSelection.bind(this), 100);
        } else return alert('Copy did not work. :(');
    };

    this.getPastedText = function() {
        if (!this.pastedText) alert('Nothing to paste. :(');
        return this.pastedText;
    };

    this.pasteText = function(callback) {
        var div = $('special_paste');
        if (!div) {
            div = new Element('textarea', {
                'id': 'special_paste',
                'style': 'opacity: 0;position: absolute;top: -10000px;right: 0;'
            });
            div.injectInside(document.body);
            div.addEvent('keyup', function() {
                if (this.callback) {
                    this.pastedText = $('special_paste').get('value');
                    this.callback.call(null, this.pastedText);
                    this.callback = false;
                    this.pastedText = false;
                    setTimeout(this.restoreSelection.bind(this), 100);
                }
            }.bind(this));
        }
        div.set('value', '');
        if (document.createRange) {
            var rng = document.createRange();
            rng.selectNodeContents(div);
            this.saveSelection = [];
            var selection = window.getSelection();
            for (var i = 0; i < selection.rangeCount; i++) {
                this.saveSelection[i] = selection.getRangeAt(i);
            }
            window.getSelection().removeAllRanges();
            window.getSelection().addRange(rng);
            div.focus();
            this.callback = callback;
        } else return alert('Failed to paste. :(');
    };
}

Usage:

enyby_clip = new EnybyClipboard(); // Init

enyby_clip.copyText('some_text'); // Place this in the Ctrl+C handler and return true;

enyby_clip.pasteText(function callback(pasted_text) {
    alert(pasted_text);
}); // Place this in Ctrl+V handler and return true;

On paste, it creates a textarea and works the same way.

PS: Maybe this solution can be used for creating a full cross-browser solution without Flash. It works in Firefox and Chrome.

Enyby
  • 3,484
  • 2
  • 26
  • 35
  • 2
    Has anyone tried that out? Sounds like a nifty thingy, in case it really works on a range of browsers! – Michael Feb 15 '13 at 14:47
  • 1
    http://jsfiddle.net/H2FHC/ Demo: http://fiddle.jshell.net/H2FHC/show/ Please open it and press Ctrl+V or Ctrl+C. In FF 19.0 forks perfectly. In Chrome 25.0.1364.97 m too. Opera 12.14 - OK. Safari 5.1.7 for Windows - OK. IE - FAIL. – Enyby Feb 28 '13 at 12:06
  • For IE need run focus on element inside page. See http://fiddle.jshell.net/H2FHC/3/show/ and http://fiddle.jshell.net/H2FHC/3/ Worked in IE 9/10. IE 6/7 need process create selection in other way because document.createRange not supported. – Enyby Feb 28 '13 at 12:33
22

The other methods will copy plain text to the clipboard. To copy HTML (i.e., you can paste results into a WYSIWYG editor), you can do the following in Internet Explorer only. This is is fundamentally different from the other methods, as the browser actually visibly selects the content.

// Create an editable DIV and append the HTML content you want copied
var editableDiv = document.createElement("div");
with (editableDiv) {
    contentEditable = true;
}
editableDiv.appendChild(someContentElement);

// Select the editable content and copy it to the clipboard
var r = document.body.createTextRange();
r.moveToElementText(editableDiv);
r.select();
r.execCommand("Copy");

// Deselect, so the browser doesn't leave the element visibly selected
r.moveToElementText(someHiddenDiv);
r.select();
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Chase Seibert
  • 15,061
  • 5
  • 48
  • 58
  • 1
    see more complete HTML solution here http://stackoverflow.com/questions/34191780/javascript-copy-string-to-clipboard-as-text-html – kofifus Dec 17 '15 at 04:48
13

As of Flash 10, you can only copy to clipboard if the action originates from user interaction with a Flash object. (Read the related section from Adobe's Flash 10 announcement.)

The solution is to overlay a Flash object above the Copy button, or whatever element initiates the copy. ZeroClipboard is currently the best library with this implementation. Experienced Flash developers may just want to make their own library.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
matthuhiggins
  • 1,855
  • 1
  • 12
  • 13
12

There are many answers already, however like to add one (jQuery). Works great on any browser, also mobile ones (i.e., prompts about security, but when you accept it just works fine).

function appCopyToClipBoard(sText)
{
    var oText = false,
        bResult = false;
    try
    {
        oText = document.createElement("textarea");
        $(oText).addClass('clipboardCopier').val(sText).insertAfter('body').focus();
        oText.select();
        document.execCommand("Copy");
        bResult = true;
    }
    catch(e) {
    }

    $(oText).remove();
    return bResult;
}

In your code:

if (!appCopyToClipBoard('Hai there! This is copied to the clipboard.'))
{
    alert('Sorry, copy to clipboard failed.');
}
Codebeat
  • 6,123
  • 5
  • 51
  • 88
12

I found the following solution:

I have the text in a hidden input. Because setSelectionRange doesn't work on hidden inputs, I changed temporarily the type to text, copied the text, and then made it hidden again. If you want to copy the text from an element, you can pass it to the function and save its content in the target variable.

jQuery('#copy').on('click', function () {
    copyToClipboard();
});

function copyToClipboard() {
    var target = jQuery('#hidden_text');

    // Make it visible, so can be focused
    target.attr('type', 'text');
    target.focus();
    // Select all the text
    target[0].setSelectionRange(0, target.val().length);

    // Copy the selection
    var succeed;
    try {
        succeed = document.execCommand("copy");
    }
    catch (e) {
        succeed = false;
    }

    // Hide input again
    target.attr('type', 'hidden');

    return succeed;
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Vassilis Pallas
  • 4,384
  • 4
  • 27
  • 46
11

Copy text from HTML input to the clipboard:

 function myFunction() {
   /* Get the text field */
   var copyText = document.getElementById("myInput");

   /* Select the text field */
   copyText.select();

   /* Copy the text inside the text field */
   document.execCommand("Copy");

   /* Alert the copied text */
   alert("Copied the text: " + copyText.value);
 }
 <!-- The text field -->
 <input type="text" value="Hello Friend" id="myInput">

 <!-- The button used to copy the text -->
<button onclick="myFunction()">Copy text</button>

Note: The document.execCommand() method is not supported in Internet Explorer 9 and earlier.

Source: W3Schools - Copy Text to Clipboard

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Alexandru Sirbu
  • 159
  • 1
  • 8
9

This is a bit of a combination between the other answers.

var copyToClipboard = function(textToCopy){
    $("body")
        .append($('<textarea name="fname" class="textToCopyInput"/>' )
        .val(textToCopy))
        .find(".textToCopyInput")
        .select();
      try {
        var successful = document.execCommand('copy');
        var msg = successful ? 'successful' : 'unsuccessful';
        alert('Text copied to clipboard!');
      } catch (err) {
          window.prompt("To copy the text to clipboard: Ctrl+C, Enter", textToCopy);
      }
     $(".textToCopyInput").remove();
}

It uses jQuery, but it doesn't have to of course. You can change that if you want. I just had jQuery to my disposal. You can also add some CSS to make sure the input doesn't show. For instance something like:

.textToCopyInput{opacity: 0; position: absolute;}

Or of course you could also do some inline styling

.append($('<textarea name="fname" style="opacity: 0;  position: absolute;" class="textToCopyInput"/>' )
yurenchen
  • 921
  • 10
  • 12
Bart Burg
  • 4,470
  • 7
  • 46
  • 81
8

In browsers other than Internet Explorer you need to use a small Flash object to manipulate the clipboard, e.g.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Quog
  • 504
  • 3
  • 15
8

I had the same problem building a custom grid edit from (something like Excel) and compatibility with Excel. I had to support selecting multiple cells, copying and pasting.

Solution: create a textarea where you will be inserting data for the user to copy (for me when the user is selecting cells), set focus on it (for example, when user press Ctrl) and select the whole text.

So, when the user hit Ctrl + C he/she gets copied cells he/she selected. After testing just resizing the textarea to one pixel (I didn't test if it will be working on display:none). It works nicely on all browsers, and it is transparent to the user.

Pasting - you could do same like this (differs on your target) - keep focus on textarea and catch paste events using onpaste (in my project I use textareas in cells to edit).

I can't paste an example (commercial project), but you get the idea.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
xiniu
  • 89
  • 1
  • 1
7

I have used clipboard.js.

We can get it on npm:

npm install clipboard --save

And also on Bower

bower install clipboard --save

Usage & examples are at https://zenorocha.github.io/clipboard.js/.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
CodecPM
  • 273
  • 4
  • 18
  • I was afraid that it wasn't compatible with dynamic content, but it is ;-) I think it's the better solution, NOW, than the old one of 2008. – BENARD Patrick Jan 05 '16 at 15:19
  • They say: *"[While Bower is maintained, we recommend using Yarn and Webpack or Parcel for front-end projects](https://bower.io/)"* – Peter Mortensen Oct 27 '19 at 17:48
7

To copy a selected text ('Text To Copy') to your clipboard, create a Bookmarklet (browser bookmark that executes JavaScript) and execute it (click on it). It will create a temporary textarea.

Code from GitHub:

https://gist.github.com/stefanmaric/2abf96c740191cda3bc7a8b0fc905a7d

(function (text) {
  var node = document.createElement('textarea');
  var selection = document.getSelection();

  node.textContent = text;
  document.body.appendChild(node);

  selection.removeAllRanges();
  node.select();
  document.execCommand('copy');

  selection.removeAllRanges();
  document.body.removeChild(node);
})('Text To Copy');
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Mau
  • 1,024
  • 2
  • 14
  • 20
7
function copytoclipboard(element) {

    var $temp = $("<input>");
    $("body").append($temp);
    $temp.val('0' + element).select();
    document.execCommand("copy");
    $temp.remove();
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Araston
  • 81
  • 2
  • 1
6

This is an expansion of Chase Seibert's answer, with the advantage that it will work for IMAGE and TABLE elements, not just DIVs on Internet Explorer 9.

if (document.createRange) {
    // Internet Explorer 9 and modern browsers
    var r = document.createRange();
    r.setStartBefore(to_copy);
    r.setEndAfter(to_copy);
    r.selectNode(to_copy);
    var sel = window.getSelection();
    sel.addRange(r);
    document.execCommand('Copy');  // Does nothing on Firefox
} else {
    // Internet Explorer 8 and earlier. This stuff won't work
    // on Internet Explorer 9.
    // (unless forced into a backward compatibility mode,
    // or selecting plain divs, not img or table).
    var r = document.body.createTextRange();
    r.moveToElementText(to_copy);
    r.select()
    r.execCommand('Copy');
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Oliver Bock
  • 4,185
  • 3
  • 33
  • 56
5

My bad. This only works in Internet Explorer.

Here's yet another way to copy text:

<p>
    <a onclick="window.clipboardData.setData('text', document.getElementById('Test').innerText);">Copy</a>
</p>
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
dvallejo
  • 988
  • 10
  • 25
  • 9
    This does not work in current Chrome (V31) or FireFox (v25). Error is that window.clipboardData is undefined. On the plus side, it works in IE9. So as long as you don't care about good browsers and want to lock your site into using bad ones, this is the way for you to do it! – Anthony Nov 14 '13 at 14:13
  • 4
    i don't get why so many silly answers. https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_copy_clipboard – Martian2049 Feb 08 '18 at 01:56
5

As far as I know that only works in Internet Explorer.

See also Dynamic Tools - JavaScript Copy To Clipboard, but it requires the user to change the configuration first and even then it doesn't seems to work.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Stormenet
  • 23,672
  • 8
  • 50
  • 65
5

This was the only thing I ever got working, after looking up various ways all around the Internet. This is a messy topic. There are lots of solutions posted around the world and most of them do not work. This worked for me:

NOTE: This code will only work when executed as direct synchronous code to something like an 'onClick' method. If you call in an asynchronous response to Ajax or in any other asynchronous way it will not work.

copyToClipboard(text) {
    var copyText = document.createElement("input");
    copyText.type = "text";
    document.body.appendChild(copyText);
    copyText.style = "display: inline; width: 1px;";
    copyText.value = text;
    copyText.focus();
    document.execCommand("SelectAll");
    document.execCommand("Copy");
    copyText.remove();
}

I do realize this code will show a 1-pixel wide component visibly on the screen for a millisecond, but decided not to worry about that, which is something that others can address if a real problem.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
5

It seems I misread the question, but for reference, you can extract a range of the DOM (not to the clipboard; compatible with all modern browsers), and combine it with the oncopy, onpaste, and onbeforepaste events to get the clipboard behaviour. Here's the code to achieve this:

function clipBoard(sCommand) {
  var oRange = contentDocument.createRange();
  oRange.setStart(startNode, startOffset);
  oRange.setEnd(endNode, endOffset);

  /* This is where the actual selection happens.
     in the above, startNode and endNode are
     DOM nodes defining the beginning and
     end of the "selection" respectively.

     startOffset and endOffset are constants
     that are defined as follows:

         END_TO_END: 2
         END_TO_START: 3
         NODE_AFTER: 1
         NODE_BEFORE: 0
         NODE_BEFORE_AND_AFTER: 2
         NODE_INSIDE: 3
         START_TO_END: 1
         START_TO_START: 0

     And it would be used like oRange.START_TO_END
  */

  switch(sCommand) {

    case "cut":
      this.oFragment = oRange.extractContents();
      oRange.collapse();
      break;

    case "copy":
      this.oFragment = oRange.cloneContents();
      break;

    case "paste":
      oRange.deleteContents();
      var cloneFragment = this.oFragment.cloneNode(true)
      oRange.insertNode(cloneFragment);
      oRange.collapse();
      break;
  }
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
mrBorna
  • 1,638
  • 16
  • 16
  • 1
    actually I corrected the code. It works in all browsers but doesn't actually copy to clipboard. Just extracts (cuts), clones (copies) content through variables. It seems I had forgotten the usage. – mrBorna Aug 17 '11 at 14:18
4

It looks like you took the code from Greasemonkey\JavaScript Copy to Clipboard button or the original source of this snippet...

This code was for Greasemonkey, hence the unsafeWindow. And I guess the syntax error in Internet Explorer comes from the const keyword which is specific to Firefox (replace it with var).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
PhiLho
  • 38,673
  • 6
  • 89
  • 128
  • The `const` keyword is not specific to Firefox, but to a specific version of JavaScript, which not all browsers implement properly. – ProfK Feb 28 '19 at 05:18
  • 2
    @ProfK At time of writing (10 years ago...), `const` was only implemented in Firefox and was not official (as far as I can remember). Today, nearly all living browsers support it, of course. – PhiLho Mar 26 '19 at 09:51
4

I had to copy the non-input boxes text (text within any div/span tag) from the page and came up with following code. The only trick is to have a hidden field, but as type TEXT. It won't work with type hidden.

function copyToClipboard(sID) {
    var aField = document.getElementById("hiddenField");

    aField.hidden = false;
    aField.value  = document.getElementById(sID).textContent;
    aField.select();
    document.execCommand("copy");
    alert("Following text has been copied to the clipboard.\n\n" + aField.value);
    aField.hidden = true;
}

And in the HTML add the following:

input type="text" id="hiddenField" style="width:5px;border:0" />
...
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
NewToIOS
  • 91
  • 1
  • 2
4

This code tested @ 2021 May . Work on Chrome , IE , Edge. 'message' parameter on below is the string value you want to copy.

<script type="text/javascript">
    function copyToClipboard(message) {
        var textArea = document.createElement("textarea");
        textArea.value = message;
        textArea.style.opacity = "0"; 
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();


        try {
            var successful = document.execCommand('copy');
            var msg = successful ? 'successful' : 'unsuccessful';
            alert('Copying text command was ' + msg);
        } catch (err) {
            alert('Unable to copy value , error : ' + err.message);
        }

        document.body.removeChild(textArea);
    }

</script>
HO LI Pin
  • 706
  • 6
  • 7
3

In addition to Dean Taylor's updated answer (July 2015), I wrote a jQuery method looking like his example.

jsFiddle

/**
* Copies the current selected text to the SO clipboard
* This method must be called from an event to work with `execCommand()`
* @param {String} text Text to copy
* @param {Boolean} [fallback] Set to true shows a prompt
* @return Boolean Returns `true` if the text was copied or the user clicked on accept (in prompt), `false` otherwise
*/
var CopyToClipboard = function(text, fallback){
    var fb = function () {
        $t.remove();
        if (fallback !== undefined && fallback) {
            var fs = 'Please, copy the following text:';
            if (window.prompt(fs, text) !== null) return true;
        }
        return false;
    };
    var $t = $('<textarea />');
    $t.val(text).css({
        width: '100px',
        height: '40px'
    }).appendTo('body');
    $t.select();
    try {
        if (document.execCommand('copy')) {
            $t.remove();
            return true;
        }
        fb();
    }
    catch (e) {
        fb();
    }
};
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
kosmos
  • 4,202
  • 1
  • 16
  • 34
3

Update 2015: currently there's a way to use document.execCommand to work with the clipboard.

clipboard.js provides a cross-browser way to work with the clipboard (browser support).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Yaroslav Yakovlev
  • 5,652
  • 5
  • 35
  • 57
3

This solution was found here. The document.execCommand("copy"); is not supported on Internet Explorer 8 and earlier.

const copyBtn =  document.getElementById("copyBtn");
const input = document.getElementById("input");

function copyText() {
  const value = input.value;
  
  input.select(); // selects the input variable as the text to be copied
  input.setSelectionRange(0, 99999); // this is used to set the selection range for mobile devices
  
  document.execCommand("copy"); // copies the selected text
  
  alert("Copied the text " + value); // displays the copied text in a prompt
}

copyBtn.onmousedown = function () {
  copyText();
}
<input type="text" id="input" placeholder="Type text to copy... "/>
<button id="copyBtn">
  Copy
</button>
YeetYeet
  • 120
  • 6
  • The execCommand is considered obsolete: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand – Jarede Jan 12 '21 at 12:25
2

If the copied link has to be pasted on the same site, then a simple solution is to highlight the text before pressing the simple HTML copy button and then on pressing it, the text content is stored in a session. And wherever it is to be pasted, there is a paste button.

**I know, it's not a persistent and universal solution, but it's something :)

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
UserBSS1
  • 1,607
  • 1
  • 19
  • 27
2

Here is the simple Ajax/session based clipboard for the same website.

Note that the session must be enabled & valid and this solution works for the same site. I tested it on CodeIgniter, but I ran into session/Ajax problem, but this solved that problem too. If you don't want to play with sessions, use a database table.

JavaScript/jQuery

<script type="text/javascript">
    $(document).ready(function() {

        $("#copy_btn_id").click(function(){

            $.post("<?php echo base_url();?>ajax/foo_copy/"+$(this).val(), null,
                function(data){
                    // Copied successfully
                }, "html"
            );
        });

        $("#paste_btn_id").click(function() {

           $.post("<?php echo base_url();?>ajax/foo_paste/", null,
               function(data) {
                   $('#paste_btn_id').val(data);
               }, "html"
           );
        });
    });
</script>

HTML content

<input type='text' id='copy_btn_id' onclick='this.select();'  value='myvalue' />
<input type='text' id='paste_btn_id' value='' />

PHP code

<?php
    class Ajax extends CI_Controller {

        public function foo_copy($val){
            $this->session->set_userdata(array('clipboard_val' => $val));
        }

        public function foo_paste(){
            echo $this->session->userdata('clipboard_val');
            exit();
        }
    }
?>
UserBSS1
  • 1,607
  • 1
  • 19
  • 27
  • 1
    This is the only answer on here that doesn't involve coercing the browser into doing something that it wasn't designed to do. Solid +1. – Luke A. Leber May 08 '15 at 22:13
2

In case you're reading text from the clipboard in a Chrome extension, with 'clipboardRead' permission allowed, you can use the below code:

function readTextFromClipboardInChromeExtension() {
    var ta = $('<textarea/>');
    $('body').append(ta);
    ta.focus();
    document.execCommand('paste');
    var text = ta.val();
    ta.blur();
    ta.remove();
    return text;
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
supNate
  • 352
  • 1
  • 9
2

In Chrome you can use copy('the text or variable etc'). While this isn't cross-browser (and doesn't work in a snippet?), you could add it to the other cross-browser answers.

drzaus
  • 21,536
  • 14
  • 123
  • 183
  • 5
    This only works when entered in the chrome command line. When I add it to my code, the copy function is not defined. – EricP Oct 01 '14 at 18:23
  • @JoeCoder thank you for explicitly pointing that out, as I meant that to be apparent from the link, but in retrospect it's not very obvious. – drzaus Oct 03 '14 at 14:08
2

For the security reason you can't do that. You must choose Flash for copying to the clipboard.

I suggest this one: http://zeroclipboard.org/

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
sinister
  • 59
  • 4
2

I was going to use clipboard.js, but it doesn't have any mobile solution in place (yet) ... so I wrote a super small library:

Cheval

This will either copy the text (desktop, Android, and Safari 10+), or at the very least, select the text (older versions of iOS). Minified it is just over 1 kB. In desktop Safari (before version 10) it tells the user to "Press Command + C to copy". You also don't need to write any JavaScript to use it.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
ryanpcmcquen
  • 5,446
  • 3
  • 20
  • 34
2

I compiled a few functions in a simple solution to cover all cases, with prompt fallback if needed.

window.copyToClipboard = function(text) {
  // Internet Explorer specific
  if (window.clipboardData && window.clipboardData.setData) {
    return clipboardData.setData("Text", text);
  }

  // All other modern browsers
  target = document.createElement("textarea");
  target.style.position = "absolute";
  target.style.left = "-9999px";
  target.style.top = "0";
  target.textContent = text;
  document.body.appendChild(target);
  target.focus();
  target.setSelectionRange(0, target.value.length);

  // Copy the selection of fall back to prompt
  try {
    document.execCommand("copy");
    target.remove();
    console.log('Copied to clipboard: "'+text+'"');
  }
  catch(e) {
    console.log("Can't copy string on this browser. Try to use Chrome, Firefox or Opera.")
    window.prompt("Copy to clipboard: Ctrl+C, Enter", text);
  }
}

Test it here: https://jsfiddle.net/jv0avz65/

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Dino Reic
  • 2,393
  • 1
  • 19
  • 11
2

This was the only thing that worked for me:

let textarea = document.createElement('textarea');
textarea.setAttribute('type', 'hidden');
textarea.textContent = 'the string you want to copy';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
Alexander Mills
  • 1
  • 80
  • 344
  • 642
2

Using the JavaScript feature using try/catch you can even have better error handling in doing so like this:

copyToClipboard() {
    let el = document.getElementById('Test').innerText
    el.focus(); // el.select();
    try {
        var successful = document.execCommand('copy');
        if (successful) {
            console.log('Copied Successfully! Do whatever you want next');
        }
        else {
            throw ('Unable to copy');
        }
    }
    catch (err) {
        console.warn('Oops, Something went wrong ', err);
    }
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Adeel Imran
  • 8,751
  • 5
  • 45
  • 71
2

Using document.execCommand will do the job for you...

Using that, you can also do cut, copy and paste...

This is one simple clipboard copy functionality which copies everything from input text...

function copyInputText() {
  var copyText = document.querySelector("#input");
  copyText.select();
  document.execCommand("copy");
}

document.querySelector("#copy").addEventListener("click", copyInputText);
<input id="input" type="text" />
<button id="copy">Copy</button>

For more information, see Interact with the clipboard (add-on).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Alireza
  • 83,698
  • 19
  • 241
  • 152
2

This is a standalone class and ensures no flashing could occur from the temporary textarea by placing it off-screen.

This works in Safari (desktop), Firefox, and Chrome.

// ================================================================================
// ClipboardClass
// ================================================================================
var ClipboardClass = (function() {

    function copyText(text) {
        // Create a temporary element off-screen to hold text.
        var tempElem = $('<textarea style="position: absolute; top: -8888px; left: -8888px">');
        $("body").append(tempElem);

        tempElem.val(text).select();
        document.execCommand("copy");
        tempElem.remove();
    }


    // ============================================================================
    // Class API
    // ============================================================================
    return {
        copyText: copyText
    };

})();
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Crashalot
  • 31,452
  • 56
  • 235
  • 393
2

Simple, ready-to-use and not obsolete solution:

function copyToClipboard(elementIdToCopy, elementIdToNotifyOutcome) {
    const contentToCopy = document.getElementById(elementIdToCopy).innerHTML;
    const elementToNotifyOutcome = document.getElementById(elementIdToNotifyOutcome);

    navigator.clipboard.writeText(contentToCopy).then(function() {
        elementToNotifyOutcome.classList.add('success');
        elementToNotifyOutcome.innerHTML = 'Copied!';
    }, function() {
        elementToNotifyOutcome.classList.add('failure');
        elementToNotifyOutcome.innerHTML = 'Sorry, did not work.';
    });
}
1

After searching a solution that supports Safari and other browsers (Internet Explorer 9 and later),

I use the same as GitHub: ZeroClipboard

Example:

http://zeroclipboard.org/index-v1.x.html

HTML

<html>
  <body>
    <button id="copy-button" data-clipboard-text="Copy Me!" title="Click to copy me.">Copy to Clipboard</button>
    <script src="ZeroClipboard.js"></script>
    <script src="main.js"></script>
  </body>
</html>

JavaScript

var client = new ZeroClipboard(document.getElementById("copy-button"));

client.on("ready", function (readyEvent) {
    // alert( "ZeroClipboard SWF is ready!" );

    client.on("aftercopy", function (event) {
        // `this` === `client`
        // `event.target` === the element that was clicked
        event.target.style.display = "none";
        alert("Copied text to clipboard: " + event.data["text/plain"]);
    });
});
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Mathieu Lescaudron
  • 6,832
  • 4
  • 29
  • 44
1

This is the best. So much winning.

var toClipboard = function(text) {
    var doc = document;

    // Create temporary element
    var textarea = doc.createElement('textarea');
    textarea.style.position = 'absolute';
    textarea.style.opacity  = '0';
    textarea.textContent    = text;

    doc.body.appendChild(textarea);

    textarea.focus();
    textarea.setSelectionRange(0, textarea.value.length);

    // Copy the selection
    var success;
    try {
        success = doc.execCommand("copy");
    }
    catch(e) {
        success = false;
    }

    textarea.remove();

    return success;
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
mmm
  • 18,431
  • 26
  • 99
  • 165
1

Here is an easy example ;)

<!DOCTYPE html>
<html>
    <body>
        <input type="text"
               value="Hello, World!"
               id="myInput">
        <button onclick="myFunction()">Copy text</button>

        <p>The document.execCommand() method is not supported
           in Internet&nbsp;Explorer&nbsp;8 and earlier.</p>

        <script>
            function myFunction() {
                var copyText = document.getElementById("myInput");
                copyText.select();
                document.execCommand("copy");
                alert("Copied the text: " + copyText.value);
            }
        </script>
    </body>
</html>
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Lars Gross
  • 84
  • 6
1
document.querySelector('#some_your_textfield_id').select();
document.execCommand('copy');

The first line is to select the text that you want to copy.

The second line is to copy the selected text.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
1

The below function can be used to copy into the clipboard:

copyToclipboard = (event, text) => {
    var container = event.currentTarget;
    let tempInnerHtml = container.innerHTML;
    container.innerHTML = text;
    window.getSelection().removeAllRanges();
    let range = document.createRange();
    range.selectNode(container);
    window.getSelection().addRange(range);
    document.execCommand('copy');
    window.getSelection().removeAllRanges();
    container.innerHTML = tempInnerHtml;
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
  • execCommand is now considered obsolete: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand – Jarede Jan 12 '21 at 12:16
0

I have put together the solution presented by @dean-taylor here along with some other select / unselect code from elsewhere into a jQuery plugin available on NPM:

https://www.npmjs.com/package/jquery.text-select

Install:

npm install --save jquery.text-select

Usage:

<script>
    $(document).ready(function(){
        $("#selectMe").selectText(); // Hightlight / select the text
        $("#selectMe").selectText(false); // Clear the selection

        $("#copyMe").copyText(); // Copy text to clipboard
    });
</script>

Futher info on methods / events can be found at the NPM registry page above.

Gruffy
  • 1,093
  • 1
  • 11
  • 17
0

Here's an elegant solution for Angular 5.x+:

Component:

import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ElementRef,
  EventEmitter,
  Input,
  OnInit,
  Output,
  Renderer2,
  ViewChild
} from '@angular/core';

@Component({
  selector: 'copy-to-clipboard',
  templateUrl: './copy-to-clipboard.component.html',
  styleUrls: ['./copy-to-clipboard.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})

export class CopyToClipboardComponent implements OnInit {
  @ViewChild('input') input: ElementRef;
  @Input() size = 'md';
  @Input() theme = 'complement';
  @Input() content: string;
  @Output() copied: EventEmitter<string> = new EventEmitter<string>();
  @Output() error: EventEmitter<string> = new EventEmitter<string>();

  constructor(private renderer: Renderer2) {}

  ngOnInit() {}

  copyToClipboard() {

    const rootElement = this.renderer.selectRootElement(this.input.nativeElement);

    // iOS Safari blocks programmtic execCommand copying normally, without this hack.
    // https://stackoverflow.com/questions/34045777/copy-to-clipboard-using-javascript-in-ios
    if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {

      this.renderer.setAttribute(this.input.nativeElement, 'contentEditable', 'true');

      const range = document.createRange();

      range.selectNodeContents(this.input.nativeElement);

      const sel = window.getSelection();

      sel.removeAllRanges();
      sel.addRange(range);

      rootElement.setSelectionRange(0, 999999);
    } else {
      rootElement.select();
    }

    try {
      document.execCommand('copy');
      this.copied.emit();
    } catch (err) {
      this.error.emit(err);
    }
  };
}

Template:

<button class="btn btn-{{size}} btn-{{theme}}" type="button" (click)="copyToClipboard()">
  <ng-content></ng-content>
</button>

<input #input class="hidden-input" [ngModel]="content">

Styles:

.hidden-input {
  position: fixed;
  top: 0;
  left: 0;
  width: 1px; 
  height: 1px;
  padding: 0;
  border: 0;
  box-shadow: none;
  outline: none;
  background: transparent;
}
Chrillewoodz
  • 22,596
  • 18
  • 73
  • 147
0

Here is my solution:

var codeElement =
    document.getElementsByClassName("testelm") &&
        document.getElementsByClassName("testelm").length ?
    document.getElementsByClassName("testelm")[0] :
    "";
if (codeElement != "") {
    var e = document.createRange();
    e.selectNodeContents(codeElement);
    var selection = window.getSelection();
    selection.removeAllRanges();
    selection.addRange(e);
    document.execCommand("Copy");
    selection.removeAllRanges();
}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Adithya Sai
  • 1,226
  • 1
  • 13
  • 29
0

This can be done just by using a combination of getElementbyId, Select(), blur() and the copy command.

Note

The select() method selects all the text in a <textarea> element or an <input> element with a text field. This might not work on a button.

Usage

let copyText = document.getElementById('input-field');
copyText.select()
document.execCommand("copy");
copyReferal.blur()
document.getElementbyId('help-text').textContent = 'Copied'

The blur() method will remove the ugly highlighted portion instead of that you can show at beautiful message that your content was copied successfully.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Nishant Singh
  • 330
  • 5
  • 11
0

I have tried many solutions. If it works in modern browsers, it won't in Internet Explorer. If it works in Internet Explorer, it won't on iOS. I finally groomed them all and arrived at the below fix that works in all the browsers, iOS, webview, and Android.

Note: I also covered the scenario where the user denies permission to the clipboard. Additionally, the message "link copied" will be displayed even if the user copies manually.

<div class="form-group col-md-12">
    <div class="input-group col-md-9">
        <input name="copyurl"
               type="text"
               class="form-control br-0 no-focus"
               id="invite-url"
               placeholder="http://www.invitelink.com/example"
               readonly>
        <span class="input-group-addon" id="copy-link" title="Click here to copy the invite link">
            <i class="fa fa-clone txt-18 text-success" aria-hidden="true"></i>
        </span>
    </div>
    <span class="text-success copy-success hidden">Link copied.</span>
</div>

Script:

var addEvent =  window.attachEvent || window.addEventListener;
var event = 'copy';
var $inviteUrl = $('#invite-url');

$('#copy-link').on('click', function(e) {
    if ($inviteUrl.val()) {
        if (navigator.userAgent.match(/ipad|ipod|iphone/i)) {
            var el = $inviteUrl.get(0);
            var editable = el.contentEditable;
            var readOnly = el.readOnly;
            el.contentEditable = true;
            el.readOnly = false;
            var range = document.createRange();
            range.selectNodeContents(el);
            var sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
            el.setSelectionRange(0, 999999);
            el.contentEditable = editable;
            el.readOnly = readOnly;
            document.execCommand('copy');
            $inviteUrl.blur();
        }
        else {
            $inviteUrl.select();
            document.execCommand("copy");
        }
    }
});

addEvent(event, function(event) {
    if ($inviteUrl.val() && event.target.id == 'invite-url') {
        var $copyLink = $('#copy-link i');
        $copyLink.removeClass('fa-clone');
        $copyLink.addClass('fa-check');
        $('.copy-success').removeClass('hidden');
        setTimeout(function() {
            $copyLink.removeClass('fa-check');
            $copyLink.addClass('fa-clone');
            $('.copy-success').addClass('hidden');
        }, 2000);
    }
});
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Renga
  • 201
  • 3
  • 7
-3

This could be the solution to your problem

function CopyToNotepad(id){
    var r = document.createRange();
    r.selectNode(document.getElementById(id));
    window.getSelection().removeAllRanges();
    window.getSelection().addRange(r);
    document.execCommand('copy');
    window.getSelection().removeAllRanges();
}

Note: id should be the parent element id to which you want to copy the content. Eg: suppose you want to copy every content inside the list, then id should be used as follows:

<ul id="dummy_id">
<li>copy content 1 </li>
<li>copy content 2 </li>
<li>copy content 3 </li>
<li>copy content 4 </li>
<li>copy content 5 </li>
</ul>

then function call should be like this

CopyToNotepad(dummy_id)

Thanks. Sure this could solve your problem!