How do I copy the text inside a div to the clipboard? I have a div and need to add a link which will add the text to the clipboard. Is there a solution for this?
It's very important that the input field does not have display: none
. The browser will not select the text and therefore will not be copied. Use opacity: 0
with a width of 0px to fix the problem.
Most of the proposed answers create an extra temporary hidden input element(s). Because most browsers nowadays support div content edit, I propose a solution that does not create hidden element(s), preserve text formatting and use pure JavaScript or jQuery library.
Here is a minimalist skeleton implementation using the fewest lines of codes I could think of:
//Pure javascript implementation:
document.getElementById("copyUsingPureJS").addEventListener("click", function() {
copyUsingPureJS(document.getElementById("copyTarget"));
alert("Text Copied to Clipboard Using Pure Javascript");
});
function copyUsingPureJS(element_id) {
element_id.setAttribute("contentEditable", true);
element_id.setAttribute("onfocus", "document.execCommand('selectAll',false,null)");
element_id.focus();
document.execCommand("copy");
element_id.removeAttribute("contentEditable");
}
//Jquery:
$(document).ready(function() {
$("#copyUsingJquery").click(function() {
copyUsingJquery("#copyTarget");
});
function copyUsingJquery(element_id) {
$(element_id).attr("contenteditable", true)
.select()
.on("focus", function() {
document.execCommand('selectAll', false, null)
})
.focus()
document.execCommand("Copy");
$(element_id).removeAttr("contenteditable");
alert("Text Copied to Clipboard Using jQuery");
}
});
#copyTarget {
width: 400px;
height: 400px;
border: 1px groove gray;
color: navy;
text-align: center;
box-shadow: 0 4px 8px 0 gray;
}
#copyTarget h1 {
color: blue;
}
#copyTarget h2 {
color: red;
}
#copyTarget h3 {
color: green;
}
#copyTarget h4 {
color: cyan;
}
#copyTarget h5 {
color: brown;
}
#copyTarget h6 {
color: teal;
}
#pasteTarget {
width: 400px;
height: 400px;
border: 1px inset skyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="copyTarget">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
<strong>Preserve <em>formatting</em></strong>
<br/>
</div>
<button id="copyUsingPureJS">Copy Using Pure JavaScript</button>
<button id="copyUsingJquery">Copy Using jQuery</button>
<br><br> Paste Here to See Result
<div id="pasteTarget" contenteditable="true"></div>
Clipboard-polyfill library is a polyfill for the modern Promise-based asynchronous clipboard API.
install in CLI:
npm install clipboard-polyfill
import as clipboard in JS file
window.clipboard = require('clipboard-polyfill');
example
I'm using it in a bundle with require("babel-polyfill");
and tested it on chrome 67. All good for production.
<div class="form-group">
<label class="font-normal MyText">MyText to copy</label>
<button type="button" class="btn btn-default btn-xs btnCopy" data="MyText">Copy</button>
</div>
$(".btnCopy").click(function () {
var element = $(this).attr("data");
copyToClipboard($('.' + element));
});
function copyToClipboard(element) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val($(element).text()).select();
document.execCommand("copy");
$temp.remove();
}
html code here
<input id="result" style="width:300px"/>some example text
<button onclick="copyToClipboard('result')">Copy P1</button>
<input type="text" style="width:400px" placeholder="Paste here for test" />
JS CODE:
function copyToClipboard(elementId) {
// Create a "hidden" input
var aux = document.createElement("input");
aux.setAttribute("value", document.getElementById(elementId).value);
// Append it to the body
document.body.appendChild(aux);
// Highlight its content
aux.select();
// Copy the highlighted text
document.execCommand("copy");
// Remove it from the body
document.body.removeChild(aux);
}
Pure JS, without inline onclick, for paired classes "content - copy button". Would be more comfortable, if you have many elements)
(function(){
/* Creating textarea only once, but not each time */
let area = document.createElement('textarea');
document.body.appendChild( area );
area.style.display = "none";
let content = document.querySelectorAll('.js-content');
let copy = document.querySelectorAll('.js-copy');
for( let i = 0; i < copy.length; i++ ){
copy[i].addEventListener('click', function(){
area.style.display = "block";
/* because the classes are paired, we can use the [i] index from the clicked button,
to get the required text block */
area.value = content[i].innerText;
area.select();
document.execCommand('copy');
area.style.display = "none";
/* decorative part */
this.innerHTML = 'Cop<span style="color: red;">ied</span>';
/* arrow function doesn't modify 'this', here it's still the clicked button */
setTimeout( () => this.innerHTML = "Copy", 2000 );
});
}
})();
hr { margin: 15px 0; border: none; }
<span class="js-content">1111</span>
<button class="js-copy">Copy</button>
<hr>
<span class="js-content">2222</span>
<button class="js-copy">Copy</button>
<hr>
<span class="js-content">3333</span>
<button class="js-copy">Copy</button>
Older browser support:
(function(){
var area = document.createElement('textarea');
document.body.appendChild( area );
area.style.display = "none";
var content = document.querySelectorAll('.js-content');
var copy = document.querySelectorAll('.js-copy');
for( var i = 0; i < copy.length; i++ ){
copyOnClick(i);
}
function copyOnClick(i){
copy[i].addEventListener('click', function(){
area.style.display = "block";
area.value = content[i].innerText;
area.select();
document.execCommand('copy');
area.style.display = "none";
var t = this;
t.innerHTML = 'Cop<span style="color: red;">ied</span>';
setTimeout( function(){
t.innerHTML = "Copy"
}, 2000 );
});
}
})();
hr { margin: 15px 0; border: none; }
<span class="js-content">1111</span>
<button class="js-copy">Copy</button>
<hr>
<span class="js-content">2222</span>
<button class="js-copy">Copy</button>
<hr>
<span class="js-content">3333</span>
<button class="js-copy">Copy</button>