I have scoured this site's similar questions, but I'm still at a loss.
Basically, I'm taking over a project for a co-worker who is moving on. His plans for an intranet page is supposed to have multiple textareas each with its own predefined text and their own "copy text" button.
On click, it copies to the user's clipboard. I pulled apart the code and for whatever reason, when I add new textareas and a button, it will not copy. The first one will.
What am I missing or doing wrong?
<html>
<head>
<script>
window.onload = function () {
var copyTextareaBtn = document.querySelector('.js-textareacopybtn');
copyTextareaBtn.addEventListener('click', function (event) {
var copyTextarea = document.querySelector('.js-copytextarea');
copyTextarea.select();
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Whoops, unable to copy');
}
});
}
</script>
</head>
<body>
<p>Test #1 </p>
<div>
<textarea class="js-copytextarea" readonly="readonly" style="width:20%;"
rows="5">Hello. This is textarea test bed #1</textarea>
<button class="js-textareacopybtn">Copy Text (works)</button>
<p>Test #2:</p>
<textarea class="js-copytextarea" readonly="readonly" style="width:20%;"
rows="5">Hi! Welcome to textarea test bed #2 </textarea>
<button class="js-textareacopybtn">Copy Text (broken)</button>
</div>
</body>
</html>
It's not working because you are only hooking the first button up to a click event because you are only getting a reference to the first button:
var copyTextareaBtn = document.querySelector('.js-textareacopybtn');
Change that to:
var copyTextareaBtn = document.querySelectorAll('.js-textareacopybtn');
.querySelector()
only returns a reference to the first element it finds that matches the selector. querySelectorAll()
returns a node list that contains all elements that match the selector.
Next, you'll need to attach the click event to each element within that node list and, if you convert those node lists to Arrays, the .forEach() method makes looping very easy.
See the updated code below:
window.onload = function () {
// Get all the elements that match the selector as arrays
var copyTextareaBtn = Array.prototype.slice.call(document.querySelectorAll('.js-textareacopybtn'));
var copyTextarea = Array.prototype.slice.call(document.querySelectorAll('.js-copytextarea'));
// Loop through the button array and set up event handlers for each element
copyTextareaBtn.forEach(function(btn, idx){
btn.addEventListener("click", function(){
// Get the textarea who's index matches the index of the button
copyTextarea[idx].select();
try {
var msg = document.execCommand('copy') ? 'successful' : 'unsuccessful';
console.log('Copying text command was ' + msg);
} catch (err) {
console.log('Whoops, unable to copy');
}
});
});
}
<div>
<p>Test #1
<textarea class="js-copytextarea" readonly="readonly" style="width:20%;"
rows="5">Hello. This is textarea test bed #1</textarea>
<button class="js-textareacopybtn">Copy Text (works)</button>
</p>
<p>Test #2:
<textarea class="js-copytextarea" readonly="readonly" style="width:20%;"
rows="5">Hi! Welcome to textarea test bed #2 </textarea>
<button class="js-textareacopybtn">Copy Text (broken)</button>
</p>
</div>