Copy text to clipboard with JS
Asked Answered
H

4

5

I am a JS beginner and I have the following problem: I want that as soon as someone clicks on the URL icon inside the accordion the respective link is copied to the clipboard. Unfortunately (always) only the first link is copied to the clipboard, even if one clicks on the other two URL icons only the first link is copied. Although in the clipboard should be link 2 (from the value field) when i click on URL icon 2 (and the same for number 3 of course). I hope I have described the problem clearly enough.

Where is the error and what do I need to change on the JS code to make it work? Thanks a lot for the help in advance!

```
<!DOCTYPE html>
<html>
<head>
  <title>My example Website</title>
<style>
body {
  font-size: 21px;
  font-family: Tahoma, Geneva, sans-serif;
  max-width: 550px;
  margin: 0 auto;
  background-color: black;
}
input {
  display: none;
}
label {
  display: block;    
  padding: 8px 22px;
  margin: 0 0 1px 0;
  cursor: pointer;
  background: #181818;
  border: 1px solid white;
  border-radius: 5px;
  color: #FFF;
  position: relative;
}
label:hover {
  background: white;
  border: 1px solid white;
  color:black;
}
label::after {
  content: '+';
  font-size: 22px;
  font-weight: bold;
  position: absolute;
  right: 10px;
  top: 2px;
}
input:checked + label::after {
  content: '-';
  right: 14px;
  top: 3px;
}
.content {
  background: #DBEECD;
  background: -webkit-linear-gradient(bottom right, #DBEECD, #EBD1CD);
  background: -moz-linear-gradient(bottom right, #DBEECD, #EBD1CD);
  background: linear-gradient(to top left, #DBEECD, #EBD1CD);
  padding: 10px 25px 10px 25px;
  border: 1px solid #A7A7A7;
  margin: 0 0 1px 0;
  border-radius: 1px;
}
input + label + .content {
  display: none;
}
input:checked + label + .content {
  display: block;
}
.whitepaper {
cursor: pointer;
text-align: center;
background-color: white;
border: 2px solid black;
border-radius: 3px;
float: left;
margin: 5px 5px 5px 0;
height: 40px;
width: 30px;
}
.blackframe {
text-align: center;
background-color: black;
cursor: pointer;
font-family: Tahoma, Geneva, sans-serif;
font-size:12px;
font-weight:bold;
margin: 12px 0 12px 0;
color: white;
width: 30px;
}
.whitepaper:hover {
cursor: pointer;
text-align: center;
background-color: black;
border: 2px solid white;
border-radius: 3px;
float: left;
margin: 5px 5px 5px 0;
height: 40px;
width: 30px;
}
 /* Tooltip container */
.tooltip {
  position: relative;
  display: inline-block;
}

/* Tooltip text */
.tooltip .tooltiptext {
  visibility: hidden;
  width: 120px;
  background-color: #555;
  color: #fff;
  text-align: center;
  padding: 5px 0;
  border-radius: 6px;

  /* Position the tooltip text */
  position: absolute;
  z-index: 1;
  bottom: 125%;
  left: 50%;
  margin-left: -60px;

  /* Fade in tooltip */
  opacity: 0;
  transition: opacity 0.3s;
}

/* Tooltip arrow */
.tooltip .tooltiptext::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: #555 transparent transparent transparent;
}

/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
  visibility: visible;
  opacity: 1;
} 
</style>
</head>
<body>

<input type="checkbox" id="title1" name="contentbox" />
<label for="title1">Content 1</label>

<div class="content">

<div class="tooltip"><div class="whitepaper" onclick="myFunction()"><div class="blackframe"><span class="tooltiptext">Copy link 1 to clipboard</span>URL</div></div><input type="text" value="https://mywebsite.com/#title1" id="myInput"></div>

</div>

<input type="checkbox" id="title2" name="contentbox" />
<label for="title2">Content 2</label>

<div class="content">

<div class="tooltip"><div class="whitepaper" onclick="myFunction()"><div class="blackframe"><span class="tooltiptext">Copy link 2 to clipboard</span>URL</div></div><input type="text" value="https://mywebsite.com/#title2" id="myInput"></div>

</div>

<input type="checkbox" id="title3" name="contentbox" />
<label for="title3">Content 3</label>

<div class="content">

<div class="tooltip"><div class="whitepaper" onclick="myFunction()"><div class="blackframe"><span class="tooltiptext">Copy link 3 to clipboard</span>URL</div></div><input type="text" value="https://mywebsite.com/#title3" id="myInput"></div>

</div>

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

  /* Select the text field */
  copyText.select();
  copyText.setSelectionRange(0, 99999); /* For mobile devices */

   /* Copy the text inside the text field */
  navigator.clipboard.writeText(copyText.value);

  /* Alert the copied text */
  alert("Copied: " + copyText.value);
} 
</script>

</body>
</html>
```
Hurtful answered 12/6, 2022 at 19:39 Comment(3)
Well, the values of the inputs (I don't know, why you use them, it seems unnecessary here, but maybe there is a reason) are all the sameWitmer
The Clipboard API has been blocked because of a permissions policy applied to the current document. See link for more details. @HurtfulExpendable
@Witmer Yes, that was a typo on my part. I am sorry about that but now the issue is solved. Have a great evening :)Hurtful
B
4

UPDATE MAR 2023

seems that the codepen broke at some point due to event.target returning the first child element instead of the clicked target. The solution for this was to use event.currentTarget to get the actual clicked element. Here's the new solution which is pretty similar to the older one but with some adjustments.

function myFunction(event) {
  /* Get the text field */
  var copyText = event.currentTarget.firstElementChild.nextElementSibling.value
    
   /* Copy the text inside the text field */
  navigator.clipboard.writeText(copyText);

  /* Alert the copied text */
  alert("Copied: " + copyText);
} 

=========================================

I found a few issues with your code

  1. You didn't change the id number on the inputs so they all would alert to the same URL which made it difficult to tell which is being clicked on.
  2. You are doing a query selection on an id that appears multiple times. This means it is not being fired on the clicked element.

My approach includes taking advantage of the clicked element by passing it in your click handler.

    <div class="tooltip">
        <div class="whitepaper" onclick="myFunction(event)">
            <div class="blackframe"><span class="tooltiptext">Copy link 3 to clipboard</span>URL</div>
        </div><input type="text" value="https://mywebsite.com/#title3" id="myInput">
    </div>

This lets me pass that event to the function call which will give us access to the current target node.

function myFunction(event) {
  /* Get the text field */
    var copyText = event.target.parentNode.nextSibling.nextSibling.value

   /* Copy the text inside the text field */
  navigator.clipboard.writeText(copyText);

  /* Alert the copied text */
  alert("Copied: " + copyText);
} 

In the above case, I had to do some weird traversing because your input is outside the scope of the clicked element. I removed the code related to mobile stuff because that wasn't relevant to this issue (feel free to put that back in).

here's the codepen with my example.

Boyd answered 12/6, 2022 at 20:27 Comment(5)
I noticed this morning that with your code I have the exact opposite problem than with the solution above. With your code, the link is only copied to the clipboard when I click on the letters/characters "URL". But if I click on the white border of the icon above or below the URL letters, nothing happens. Do you have a solution for this? I have already tried to create another div element all around it with the onclick function, also I have tried to place the onclick element in other places but everything without success. :(Hurtful
no problem.. I fixed this by moving the function call to the parent node rather than the text node where you previously had it. This also simplifies the traversal since we just need to grab the value from the last child codepen.io/LTFoReal/pen/KKQbMev?editors=1010Boyd
Thanks but I solved the problem a little differently. Your first code works great as soon as I re-modelled the CSS a bit. Read here my second post where I present my solution with your code and a new CSS. #72605067 So thanks again for the help and have a great day! :)Hurtful
Both your codepen examples give me "copied: undefined"Key
@Key yeah The issue seemed to be that "target" was bubbling down rather than returning what it should so I replaced it with "currentTarget" and just tossed in some sibling traversal. Here's the newer solution - codepen.io/LTFoReal/pen/KKQbMevBoyd
G
15

Replace function myFunction like this:

function myFunction(event) {
    var target = event.target;
    var copyText = target.nextElementSibling;

    navigator.clipboard.writeText(copyText.value);

    alert("Copied: " + copyText.value);
}

then update all onclick attributes like this

onclick="myFunction(event)"
Gylys answered 12/6, 2022 at 19:50 Comment(3)
Thank you very much! Now it works as it should. Have a great evening! :)Hurtful
I just noticed that the initial problem is now solved but a new problem appeared. When I now click on the letters "URL", nothing happens. I have to click on the white border above or below that the text is loaded into the clipboard. Is there a way to include the letters so that when I click on the letters "URL", the text is also copied to the clipboard like i would click on the white border? I have already tried to insert the onclick on all <div> elements (and also to insert them on all elements at once), but unfortunately without success. Do you have an idea there as well? :)Hurtful
Ok, the post below solved the problem without causing further problems. But thanks for the help anyway!Hurtful
B
4

UPDATE MAR 2023

seems that the codepen broke at some point due to event.target returning the first child element instead of the clicked target. The solution for this was to use event.currentTarget to get the actual clicked element. Here's the new solution which is pretty similar to the older one but with some adjustments.

function myFunction(event) {
  /* Get the text field */
  var copyText = event.currentTarget.firstElementChild.nextElementSibling.value
    
   /* Copy the text inside the text field */
  navigator.clipboard.writeText(copyText);

  /* Alert the copied text */
  alert("Copied: " + copyText);
} 

=========================================

I found a few issues with your code

  1. You didn't change the id number on the inputs so they all would alert to the same URL which made it difficult to tell which is being clicked on.
  2. You are doing a query selection on an id that appears multiple times. This means it is not being fired on the clicked element.

My approach includes taking advantage of the clicked element by passing it in your click handler.

    <div class="tooltip">
        <div class="whitepaper" onclick="myFunction(event)">
            <div class="blackframe"><span class="tooltiptext">Copy link 3 to clipboard</span>URL</div>
        </div><input type="text" value="https://mywebsite.com/#title3" id="myInput">
    </div>

This lets me pass that event to the function call which will give us access to the current target node.

function myFunction(event) {
  /* Get the text field */
    var copyText = event.target.parentNode.nextSibling.nextSibling.value

   /* Copy the text inside the text field */
  navigator.clipboard.writeText(copyText);

  /* Alert the copied text */
  alert("Copied: " + copyText);
} 

In the above case, I had to do some weird traversing because your input is outside the scope of the clicked element. I removed the code related to mobile stuff because that wasn't relevant to this issue (feel free to put that back in).

here's the codepen with my example.

Boyd answered 12/6, 2022 at 20:27 Comment(5)
I noticed this morning that with your code I have the exact opposite problem than with the solution above. With your code, the link is only copied to the clipboard when I click on the letters/characters "URL". But if I click on the white border of the icon above or below the URL letters, nothing happens. Do you have a solution for this? I have already tried to create another div element all around it with the onclick function, also I have tried to place the onclick element in other places but everything without success. :(Hurtful
no problem.. I fixed this by moving the function call to the parent node rather than the text node where you previously had it. This also simplifies the traversal since we just need to grab the value from the last child codepen.io/LTFoReal/pen/KKQbMev?editors=1010Boyd
Thanks but I solved the problem a little differently. Your first code works great as soon as I re-modelled the CSS a bit. Read here my second post where I present my solution with your code and a new CSS. #72605067 So thanks again for the help and have a great day! :)Hurtful
Both your codepen examples give me "copied: undefined"Key
@Key yeah The issue seemed to be that "target" was bubbling down rather than returning what it should so I replaced it with "currentTarget" and just tossed in some sibling traversal. Here's the newer solution - codepen.io/LTFoReal/pen/KKQbMevBoyd
U
0

Here is how to copy text to clipboard

Example: https://codepen.io/gmkhussain/pen/gOjaRzY

    function copyFunc(elemId) {

        let that = document.querySelector(elemId);

        navigator.clipboard.writeText(that?.innerText).then(res => {
          console.log("Copeid to clipboard: " + that.innerText );
          
          that.classList.add("copied")
          setTimeout(()=> that.classList.remove("copied"), 2000)
          
        });
    }
    <span class='box'>
       <span id="c1">Something One</span>
       <button class="btn" onclick="copyFunc('#c1')">Copy</button>
    </span>
         
     <span class='box'>
       <span id="c2">Amoos John Wick</span>
       <button class="btn" onclick="copyFunc('#c2')">Copy</button>
    </span>
Unkindly answered 4/6, 2023 at 6:40 Comment(0)
A
0
<!--The text field-->
<input type="text" value="Hello World" id="helloWorld">

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


function copyText() {
   var text = document.getElementById("helloWorld");
   text.select();
   text.setSelectionRange(0, 99999);
   navigator.clipboard.writeText(text.value);
}
Aristocrat answered 15/2 at 18:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.