Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Bind timeout to specific HTML element

I have multiple buttons. When clicking on one of the buttons, I want to add a small checkmark after the button text and remove it after 1 second with a timeout.

This works fine as long as I don’t click 2 or more buttons within the 1 second time frame.

To see the issue, just click 2 or 3 buttons within 1 second. The checkmark will only be removed on the last clicked button.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

How can I solve this issue? I would think the timeout could be bound to the clicked element but I don’t know how to achieve that.

// Get all .copy-clip buttons
let copyEls = document.querySelectorAll('.copy-clip');
let timeoutHandle;

// For each button
copyEls.forEach(el => {

  // Register click event listener
  el.addEventListener('click', (e) => {

    // Reset the inner HTML to avoid multiple copy checkmarks
    e.target.innerHTML = 'Copy';

    // Reset timeout
    window.clearTimeout(timeoutHandle);

    // Add copy checkmark in button inner HTML
    e.target.innerHTML += '<span class="copy-check"> &#x2713;</span>';

    // Remove copy checkmark after 1 sec
    timeoutHandle = setTimeout(function() {
      e.target.innerHTML = 'Copy'
    }, 1000);
  })
})
button {
  margin-bottom: 5px;
}
<button class="copy-clip">Copy</button><br>
<button class="copy-clip">Copy</button><br>
<button class="copy-clip">Copy</button><br>

>Solution :

Because there’s only one timeoutHandle. So as soon as a second value is assigned to it, the previous value is lost. Instead, create a new one in each iteration of the loop. For example:

// Copy to clipboard
let copyEls = document.querySelectorAll('.copy-clip');

// For each copy button
copyEls.forEach(el => {

  let timeoutHandle; // <-- here

  // Register click event listener
  el.addEventListener('click', (e) => {

    // Reset the inner HTML to avoid multiple copy checkmarks
    e.target.innerHTML = 'Copy';

    // Reset timeout
    window.clearTimeout(timeoutHandle);

    // Add copy checkmark in button inner HTML
    e.target.innerHTML += '<span class="copy-check"> &#x2713;</span>';

    // Remove copy checkmark after 1 sec
    timeoutHandle = setTimeout(function() {
      e.target.innerHTML = 'Copy'
    }, 1000);
  })
})
button {
  margin-bottom: 5px;
}
<button class="copy-clip">Copy</button><br>
<button class="copy-clip">Copy</button><br>
<button class="copy-clip">Copy</button><br>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading