Reputation: 11
Script that copies information on button click and then returns the original text loses some of the button's content.
missing icon from Font Avesome. Can this be fixed somehow?
I'm a newbie, I'll be glad for a detailed answer.
html:
<p id="battlenet-id">gameid#26737</p>
<p id="xbox-id">gameid#5423</p>
<li><a href="javascript:void(0);" class="link-st battlenet" onclick="copyToClipboard('battlenet-id', this)"><i class="fab fa-battle-net"></i> Battle.net</a></li>
<li><a href="javascript:void(0);" class="link-st xbox" onclick="copyToClipboard('xbox-id', this);"><i class="fa-brands fa-xbox"></i> Xbox</a></li>
js
function copyToClipboard(elementId, thisButton) {
let oldText = thisButton.textContent
thisButton.textContent = '!Copied!'
const timeout = setTimeout(function() { thisButton.textContent = oldText }, 3000);
var aux = document.createElement("input");
aux.setAttribute("value", document.getElementById(elementId).innerHTML);
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
console.log("🎉 Copied to clipboard!");
document.body.removeChild(aux);
}
Upvotes: 1
Views: 64
Reputation: 4783
Only using textContent
won't be suffice to keep the icon
after copying the text. To have the original content (text + icon) reverted after performing the copy, you'd need to use a combination of textContent
and innerHTML
attributes.
Here's a demo:
/** select all the buttons that have the copy feature based on the "link-st" class */
const toBeCopiedElements = document.querySelectorAll('.link-st');
/**
* loop through those buttons and add a click event listener to each one that perform the copy feature
*/
toBeCopiedElements.forEach(el => el.addEventListener('click', e => {
/**
* el: references the current button in the forEach loop
* oldHTML: has the initial HTML content of the button
* aux: the input element that is used to perform the "copy" command
*/
const oldHTML = el.innerHTML,
aux = document.createElement('input');
/** set the buttons text as the newly created input's value */
aux.value = el.textContent;
/** perform the copy command and the cleanups afterwards (the next 4 line) */
document.body.appendChild(aux);
aux.select();
document.execCommand('copy');
document.body.removeChild(aux);
/** replace the buttons HTML content with "!Copied!" text. Must use "innerHTML" here in order to fully remove the old text and icon */
el.innerHTML = '!Copied!';
/** reset the button's HTML content (using ".innerHTML") to the original content after 3s */
setTimeout(() => el.innerHTML = oldHTML, 3000);
}));
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<!-- Removed the inline event listeners and switched to the modern way of atttaching listeners (using "addEventListener" methodd) -->
<li><a href="javascript:void(0);" class="link-st battlenet"><i class="fab fa-battle-net"></i> Battle.net</a></li>
<li><a href="javascript:void(0);" class="link-st xbox"><i class="fa-brands fa-xbox"></i> Xbox</a></li>
The above demo is definitely not the only way to get things done. There might be some other ways most notably using the modern
Clipboard API
to have the copy-to-clipboard feature.
Upvotes: 1
Reputation: 45
According to Node.textContent - MDN Docs
Both
textContent
andinnerText
remove child nodes when altered
A good option would be using a span
tag around the text inside your a
, so that the i
icon element is not altered when modifying the textContent
.
In your case, the resulting HTML code will look like this:
<li><a href="javascript:void(0);" class="link-st xbox" onclick="copyToClipboard('xbox-id', this);"><i class="fa-brands fa-xbox"></i> <span>Xbox</span></a></li>
And I think to copy the whole content of the a
tag you need to use innerHTML
instead, otherwise you would get only the text.
Or you could just save both i
and span
elements saving a copy of them independently and append them again after.
Upvotes: 1