I have many divs that contain an data-attribute with a different value for each
I try to print this value by counting using javascript
const numbers = document.querySelectorAll(".number"); console.log(numbers); let counter = 0; setInterval(() => { numbers.forEach((number) => { if(counter === number.dataset.num){ clearInterval(); }else{ counter += 1; number.innerHTML = counter + "%"; } }) }, 20);
<div class="skill-level position-absolute"> <div class="outer"> <div class="inner d-flex align-items-center justify-content-center"> <div class="number" data-num="95"> </div> </div> </div> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="160px" height="160px"> <defs> <linearGradient id="GradientColor"> <stop offset="0%" stop-color="#e91e63" /> <stop offset="100%" stop-color="#673ab7" /> </linearGradient> </defs> <circle cx="80" cy="80" r="70" stroke-linecap="round" /> </svg> </div> <div class="skill-level position-absolute"> <div class="outer"> <div class="inner d-flex align-items-center justify-content-center"> <div class="number" data-num="70"> </div> </div> </div> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="160px" height="160px"> <defs> <linearGradient id="GradientColor"> <stop offset="0%" stop-color="#e91e63" /> <stop offset="100%" stop-color="#673ab7" /> </linearGradient> </defs> <circle cx="80" cy="80" r="70" stroke-linecap="round" /> </svg> </div>
The problem is that the counter doesn’t stop on the data-num value it counts to infinity
How can i stop the counter for each one in the value of data-num for each div?
Advertisement
Answer
What’s happening is that both elements are referencing the same variable counter
, so the variable is actually incremented by two every call of the function. Therefore, you should have counters for each number. Likewise, you should have intervals for each number so you know when to stop incrementing.
Also, you need to replace number.dataset.num
with parseInt(number.dataset.num)
because that attribute is actually a string. As Parsa S said, you should also use classes instead of ids. After implementing all of the changes, here is the code:
const numbers = document.querySelectorAll(".number"); // Change the HTML to use classes const counters = Array(numbers.length); const intervals = Array(numbers.length); counters.fill(0); numbers.forEach((number, index) => { intervals[index] = setInterval(() => { if (counters[index] === parseInt(number.dataset.num)) { clearInterval(intervals[index]); } else { counters[index] += 1; number.innerHTML = counters[index] + "%"; } }, 20) });