DEV Community

tq-bit
tq-bit

Posted on • Updated on

How to copy text to the clipboard with Javascript

Copying data from the browser into your clipboard is a small feature, yet a quite powerful one. No more manual selecting & crtl + c does save a bit of time when following larger coding articles. I've just added the small clipboard sign next to all my snippets for a reader's convenience myself. Read on to find out how I did it.

Boilerplate


Create an index.html file, as well as a main.js file in a directory of your choice. Fill the index - file up with the following and let's jump in.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Copy to clipboard</title>
  </head>
  <body>
    <h1>With textarea</h1>
    <section>
      <textarea
        placeholder="Write your content here and press 'Copy Text'"
        id="clipboard-area"
        cols="30"
        rows="2"
      ></textarea>
      <textarea
        placeholder="Paste your content here"
        cols="30"
        rows="2"
      ></textarea>
    </section>
    <button style="width: 260px" onclick="handleCopyTextFromArea()">
      Copy text
    </button>

    <h1>Without textarea</h1>
    <section style="display: flex">
      <p style="width: 260px; margin: 0">
        Lorem ipsum, dolor sit amet consectetur adipisicing elit.
      </p>
      <textarea
        placeholder="Paste your content here"
        cols="30"
        rows="2"
      ></textarea>
    </section>
    <button style="width: 260px" onclick="handleCopyTextFromParagraph()">
      Copy text
    </button>

    <script src="main.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

We'll have two functions attached to the buttons - handleCopyTextFromArea and

handleCopyTextFromParagraph - let's fill them with life.

an image that shows a simple html user interface with three textareas and a paragraph

Method 1: execCommand('copy')

While the functionality of this method is deprecated according to MDN docs, it still works well with a textarea - html tag. And even if you do not have such available, creating it - and filling its value with the desired text content - is done very quickly.

If you have a text area available, add the following to your index.html

function handleCopyTextFromArea() {
  const area = document.querySelector('#clipboard-area')
  area.select();
  document.execCommand('copy')
}
Enter fullscreen mode Exit fullscreen mode

If you do not have said element at your disposal, you can just add it for the time copying takes place. The below steps usually happen in a breeze, a user will not notice the extra tag being added and removed again:

  1. Create the textarea element and add it to the DOM.
  2. Populate its value with the text from the paragraph - or any other element.
  3. Use the above execCommand('copy') - method to copy the textual content
  4. Remove the element again.
function handleCopyTextFromParagraph() {
  const body = document.querySelector('body');
  const paragraph = document.querySelector('p');
  const area = document.createElement('textarea');
  body.appendChild(area);

  area.value = paragraph.innerText;
  area.select();
  document.execCommand('copy');

  body.removeChild(area);
}
Enter fullscreen mode Exit fullscreen mode

If you now try and crtl + v into the textarea to the right, you should see the input being pasted. While this approach does still work very well, modern browsers have implemented their own interfaces to take care of clipboard features. Let's take a look at that next.

Method 2: Clipboard API

The clipboard API is a modern, promise based approach that solely focuses on the clipboard instead of doing many things at once. It requests you for permission and works only over https, making it more secure by design. According to Can I use, older browsers do not support this functionality, therefor you might want to consider having the alternative in place as well.

Let's replace the above handleCopyTextFromParagraph function with the following:

function handleCopyTextFromParagraph() {
  const cb = navigator.clipboard;
  const paragraph = document.querySelector('p');
  cb.writeText(paragraph.innerText).then(() => alert('Text copied'));
}
Enter fullscreen mode Exit fullscreen mode

And that's about it, really. You might want to replace the .then() - callback with some neater type of user feedback and check for user permission, still - goal achieved - the text is available and ready to be parsed.

UPDATE: Copy to clipboard with Vue 3 directive

If you're using Vue.js to build your application, you can wrap the above function using a Vue custom directive. Then, you achieve the same functionality by clicking on (or interacting in any other way with) the component that has v-clip bound to it.

Declare the following function inside of you main.js file and have it registered globally after creating the Vue app:

const vClip = {
  // For Vue 2, you can use bind instead of mounted
  mounted: (el) => {
    el.addEventListener('click', () => {
      const cb = navigator.clipboard;

      // Check if the clicked on element is an input element
      const input = el.tagName === 'input' ? 
          el : 
          el.querySelector('input');

      // Copy the text to clipboard
      cb.writeText(input.value).then(() => alert('Text copied'));
    });
  },
};

// Create the app and mount it
const app = createApp(App);

app.directive('clip', vClip);
app.mount('#app');
Enter fullscreen mode Exit fullscreen mode

Then, assuming you have the following component:

<q-base-input
 label="Short link:"
 v-model="form.result"
 disabled />
Enter fullscreen mode Exit fullscreen mode

You can add the v-clip directive to it:

<q-base-input
 label="Short link:"
 v-clip
 v-model="form.result"
 disabled />
Enter fullscreen mode Exit fullscreen mode

This post was originally published at https://blog.q-bit.me/use-javascript-to-copy-text-to-the-clipboard/
Thank you for reading. If you enjoyed this article, let's stay in touch on Twitter 🐤 @qbitme

Discussion (12)

Collapse
devmor profile image
Devmor

Hey thanks this is good. Just found a typo:

const input = el.tagName === 'input' ? ...
Enter fullscreen mode Exit fullscreen mode

'input' should be 'INPUT' because tag names are uppercase.

const input = el.tagName === 'INPUT' ? ...
Enter fullscreen mode Exit fullscreen mode
Collapse
off_samuelzin profile image
samuel

Thank you guy I need this.

Collapse
tqbit profile image
tq-bit Author

Glad it helped. Out of curiousity: Did you go for the execCommand or navigator option?

Collapse
off_samuelzin profile image
samuel

Navigation option in my vision it's so much better

Collapse
sincapshop profile image
Sincap Shop

Method 2: Clipboard API
How can I integrate it into my chrome extension because it doesn't work in the extension while it works in the normal browser.

Let me put it this way, I print a part of the source of a web page to my plugin and I want it to copy when a button is clicked.

Collapse
tqbit profile image
tq-bit Author

I think chrome extensions run in their own sandbox environment. Instead of requesting permission in the browser, you need to 'proxy' them towards the env plugins run within.

There's this section in the docs describing how to do so, I hope it'll help you: developer.chrome.com/docs/extensio...

Collapse
jorik profile image
Jorik • Edited on

Also worth mentioning Transmat for a third option using the DataTransfer API, this will also include drag-drop! :-)

google.github.io/transmat/

Collapse
tqbit profile image
tq-bit Author • Edited on

Cool idea. I've already used DataTransfer for dropping a file in the browser for fileupload, didn't know it works the other way around as well

Collapse
burgercousin profile image
Pentium_4

thx!

Collapse
dquanghuy4444 profile image
Đặng Quang Huy

you are kind

Collapse
aalphaindia profile image
Pawan Pawar

excellent!

Collapse
diraskreact profile image
Info Comment hidden by post author - thread only accessible via permalink
Dirask-React • Edited on

Some comments have been hidden by the post's author - find out more