40

I spent a good 20 min searching online for this, but couldn't find it. What I want is to to be able to copy a text string on click without a button. The text string will be inside a "span" class.

  1. User hovers over text string
  2. User clicks text string
  3. Text string is copied to clipboard

Any help would be greatly appreciated. Thanks!

aloisdg
  • 19,231
  • 5
  • 81
  • 97
Matthew
  • 479
  • 1
  • 5
  • 12
  • Is it just the "without a button" part that you're stuck on? As in, you want to know how write a click event handler for a span element? (Hint: it's very, *very* similar to a click event handler on a button.) Your point 1 about the hovering seems irrelevant if nothing actually happens until the user clicks. – nnnnnn Jul 13 '17 at 04:24
  • @matthew What exactly you want to do after copy where you want to paste? – mayank Jul 13 '17 at 04:26

9 Answers9

53

You can attach copy event to <span> element, use document.execCommand("copy") within event handler, set event.clipboardData to span .textContent with .setData() method of event.clipboardData

const span = document.querySelector("span");

span.onclick = function() {
  document.execCommand("copy");
}

span.addEventListener("copy", function(event) {
  event.preventDefault();
  if (event.clipboardData) {
    event.clipboardData.setData("text/plain", span.textContent);
    console.log(event.clipboardData.getData("text"))
  }
});
<span>text</span>
guest271314
  • 1
  • 12
  • 91
  • 170
  • 1
    How to achieve this with click on a sibling div button? – Flo Dec 13 '17 at 00:48
  • @Flo You can use the same pattern. Attach `copy` event to an element, set the clipboard data within event handler. – guest271314 Jan 22 '18 at 06:46
  • How do I get a hold of `clipboardData` without a `copy` event? As in from another event handler, like a click event on a separate element? The `copy` event is not firing. – Chloe May 12 '18 at 20:21
  • 2
    This code is prone to problem if user has already selected some text. see https://stackoverflow.com/a/53977796/6665568 for a full solution . – Natesh bhat Dec 30 '18 at 12:58
35

Try this .document.execCommand('copy')

  1. click the element and copy the text and post with tmp input element
  2. Then copy the text from this input

function copy(that){
var inp =document.createElement('input');
document.body.appendChild(inp)
inp.value =that.textContent
inp.select();
document.execCommand('copy',false);
inp.remove();
}
<p onclick="copy(this)">hello man</p>
prasanth
  • 21,342
  • 4
  • 27
  • 50
  • This method works well, but how would one go about copying the text including the new lines? (\n in js , in html) I have an onclick set to a tag, so users can just click and copy code, but still wont copy the new lines. I can provide more explanation and code if needed. – Malmadork Dec 09 '19 at 16:23
  • this worked, thank you so much for your help!! – Aryan Mar 18 '21 at 01:12
19

This is the Code pen.

<link href='https://fonts.googleapis.com/css?family=Oswald' rel='stylesheet' type='text/css'> 
<p style="color:wheat;font-size:55px;text-align:center;">How to copy a TEXT to Clipboard on a Button-Click</p>

<center>
<p id="p1">This is  TEXT 1</p>
<p id="p2">This is TEXT 2</p><br/>

<button onclick="copyToClipboard('#p1')">Copy TEXT 1</button>
<button onclick="copyToClipboard('#p2')">Copy TEXT 2</button>

<br/><br/><input class="textBox" type="text" id="" placeholder="Dont belive me?..TEST it here..;)" />
</center>

Jquery Code here

function copyToClipboard(element) {
  var $temp = $("<input>");
  $("body").append($temp);
  $temp.val($(element).text()).select();
  document.execCommand("copy");
  $temp.remove();
}
Black Mamba
  • 11,092
  • 6
  • 67
  • 93
  • 7
    People will reach the question on searching how to copy the text and jQuery might be an option for them even though op might not be directly benefited from my answer but a lot of community members will be – Black Mamba Sep 11 '17 at 16:32
8

Along with copying the text , you also have to make sure that any previously selected component remains selected after copying to clipboard.

Here's the full code :

const copyToClipboard = str => {
  const el = document.createElement('textarea');  // Create a <textarea> element
  el.value = str;                                 // Set its value to the string that you want copied
  el.setAttribute('readonly', '');                // Make it readonly to be tamper-proof
  el.style.position = 'absolute';                 
  el.style.left = '-9999px';                      // Move outside the screen to make it invisible
  document.body.appendChild(el);                  // Append the <textarea> element to the HTML document
  const selected =            
    document.getSelection().rangeCount > 0        // Check if there is any content selected previously
      ? document.getSelection().getRangeAt(0)     // Store selection if found
      : false;                                    // Mark as false to know no selection existed before
  el.select();                                    // Select the <textarea> content
  document.execCommand('copy');                   // Copy - only works as a result of a user action (e.g. click events)
  document.body.removeChild(el);                  // Remove the <textarea> element
  if (selected) {                                 // If a selection existed before copying
    document.getSelection().removeAllRanges();    // Unselect everything on the HTML document
    document.getSelection().addRange(selected);   // Restore the original selection
  }
};

ps adding the source

marcomow
  • 199
  • 1
  • 10
Natesh bhat
  • 10,121
  • 9
  • 68
  • 112
  • 2
    This should be correct answer. Accepted answer works wrong. – user0103 May 14 '19 at 20:32
  • I have read both your answer and the original but somehow, can't seem to get the browser (firefox) to reselect the previously selected text once the element in question has been copied. Not sure how to debug; there's no console issues. – Martin Sep 16 '20 at 17:21
5

Use the Clipboard API!

The simplest modern solution is:

navigator.clipboard.writeText(value)

That value can later be accessed with:

navigator.clipboard.readText()

NOTE: To use in an iframe, you'll need to add write (and maybe read) permissions

<iframe src='' allow='clipboard-read; clipboard-write'/>

NOTE: To use in an browser extension (on a webpage), you'll need either to:

  • call from a user triggered event (click...)
  • add the 'clipboardWrite' permission to the manifest

NOTE: To use in the dev console, use copy() instead

copy('string')

W3Schools Tutorial

CanIUse

Gibolt
  • 33,561
  • 12
  • 157
  • 107
2

HTML:

<button type='button' id='btn'>Copy</button>

JS

document.querySelect('#btn').addEventListener('click', function() {
   copyToClipboard('copy this text');
});

JS / Function:

function copyToClipboard(text) {
    var selected = false;
    var el = document.createElement('textarea');
    el.value = text;
    el.setAttribute('readonly', '');
    el.style.position = 'absolute';
    el.style.left = '-9999px';
    document.body.appendChild(el);
    if (document.getSelection().rangeCount > 0) {
        selected = document.getSelection().getRangeAt(0)
    }
    el.select();
    document.execCommand('copy');
    document.body.removeChild(el);
    if (selected) {
        document.getSelection().removeAllRanges();
        document.getSelection().addRange(selected);
    }
};
Ricardo Canelas
  • 1,952
  • 23
  • 19
1

guest271314's answer applied to multiple elements:

spans = document.querySelectorAll(".class");
for (const span of spans) {
  span.onclick = function() {
    document.execCommand("copy");
  }

  span.addEventListener("copy", function(event) {
    event.preventDefault();
    if (event.clipboardData) {
      event.clipboardData.setData("text/plain", span.textContent);
      console.log(event.clipboardData.getData("text"))
    }
  });
}
<span class="class">text</span>
<br>
<span class="class">text2</span>
Pat Myron
  • 3,910
  • 2
  • 19
  • 38
1

This is the most suitable way to do it. It will copy all text in elements with the class "copy" in them.

var copy = document.querySelectorAll(".copy"); 

for (const copied of copy) { 
  copied.onclick = function() { 
    document.execCommand("copy"); 
  };  
  copied.addEventListener("copy", function(event) { 
    event.preventDefault(); 
    if (event.clipboardData) { 
      event.clipboardData.setData("text/plain", copied.textContent);
      console.log(event.clipboardData.getData("text"))
    };
  });
};
.copy {
            
  cursor: copy;
            
}
<p><span class="copy">Text</span></p>
<p><span class="copy">More Text</span></p>
<p><span class="copy">Even More Text</span></p>
topsoftwarepro
  • 679
  • 3
  • 19
-3

function copy(that){
var inp =document.createElement('input');
document.body.appendChild(inp)
inp.value =that.textContent
inp.select();
document.execCommand('copy',false);
inp.remove();
}
<p onclick="copy(this)">hello man</p>
Gtm
  • 385
  • 3
  • 11