skip to Main Content

I’ve a few divs with empty span in them and these are meant to start counter that would count up to specified number. I grabbed some code (I’m not very good with JS) from the web and made it work for the first div but I don’t know how to loop(?) over their remaining divs.

let counts = setInterval(updated, 100);
let upto = 0;

function updated() {
  let count = document.getElementById("counter-1");
  count.innerHTML = ++upto;
  if (upto === 100) {
    clearInterval(counts);
  }
}
.various__item--skill-quantity {
  color: black;
  transition: all 0.5s;
  margin: 0 5%;
}
<div class="various__item--skills-quantity" id="counter-1"><span></span></div>
<div class="various__item--skills-quantity" id="counter-2"><span></span></div>
<div class="various__item--skills-quantity" id="counter-3"><span></span></div>
<div class="various__item--skills-quantity" id="counter-14"><span></span></div>

2

Answers


  1. First off, this is THE documentation for js on the web : https://developer.mozilla.org/en-US/docs/Web/JavaScript

    I highly recommend bookmarking it and giving it a good read through.

    One way that you can go about looping through is to collect / define a NodeList by class name and work your way through that:
    https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

    let nodeList = document.querySelectorAll('.various__item--skills-quantity')

    you can use different methods to loop through this. a basic, but great way to do this is a ‘for…of’ loop https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for…of

    for (n of nodeList) {
      n.innerHTML = ++upto;
    }

    when you are looping through, n is your node / element / div

    let counts = setInterval(updated, 100);
    let upto = 0;
    
    function updated() {
      let nodeList = document.querySelectorAll('.various__item--skills-quantity');
      for (n of nodeList) {
        n.innerHTML = ++upto;
        if (upto === 100) {
          clearInterval(counts);
        }
      }
    }
    .various__item--skill-quantity {
      color: black;
      transition: all 0.5s;
      margin: 0 5%;
    }
    <div class="various__item--skills-quantity" id="counter-1"><span></span></div>
    <div class="various__item--skills-quantity" id="counter-2"><span></span></div>
    <div class="various__item--skills-quantity" id="counter-3"><span></span></div>
    <div class="various__item--skills-quantity" id="counter-14"><span></span></div>

    This example works, though it does STOP running when the count reaches 100.

    Hope this helps!

    Login or Signup to reply.
  2. Here is a functional approach to this problem.

    First, you will need to access all the timers at once. After you have the timer elements, you can initialize them. You can use data attributes to keep track of the state of each timer.

    With Math.sign, you can determine the direction of the timer.

    const counters = [...document.querySelectorAll('.counter')];
    let intervalId;
    
    startCounters();
    
    function startCounters() {
      console.log('Starting timers...');
      initializeCounters();
      intervalId = setInterval(updateCounters, 1000);
    }
    
    function initializeCounters() {
      for (let counter of counters) {
        counter.dataset.countStart = getCounterStart(counter);
        counter.dataset.countEnd = getCounterEnd(counter);
        counter.dataset.countValue = counter.textContent = getCounterValue(counter);
      }
    }
    
    function updateCounters() {
      let isDone = true;
      for (let counter of counters) {
        if (counter.dataset.isDone) {
          continue;
        }
        const start = getCounterStart(counter);
        const end = getCounterEnd(counter);
        const direction = Math.sign(end - start);
        const value = getCounterValue(counter) + direction;
        counter.textContent = value;
        if (direction > 0 ? value >= end : value <= end) {
          counter.dataset.isDone = true;
          continue;
        }
        counter.dataset.countValue = value;
        isDone = false;
      }
      if (isDone) {
        clearInterval(intervalId);
        intervalId = undefined;
        console.log('All timers have stopped');
      }
    }
    
    function getCounterStart(counterEl) {
      return +(counterEl.dataset.countStart ?? 0);
    }
    
    function getCounterEnd(counterEl) {
      return +(counterEl.dataset.countEnd ?? 0);
    }
    
    function getCounterValue(counterEl) {
      return +(counterEl.dataset.countValue ?? getCounterStart(counterEl));
    }
    <div class="counter" data-count-start="0" data-count-end="1"></div>
    <div class="counter" data-count-start="0" data-count-end="2"></div>
    <div class="counter" data-count-start="0" data-count-end="3"></div>
    <div class="counter" data-count-start="0" data-count-end="14"></div>
    <div class="counter" data-count-start="10" data-count-end="0"></div>

    Here is a promise version, that may be easier to follow. Each promise encapsulates the entire logic.

    console.log('Starting timers...');
    Promise
      .all([...document.querySelectorAll('.counter')]
        .map(counter => Timer(counter, 1000)))
      .then(() => {
        console.log('All timers have stopped');
      });
    
    function Timer(el, rate) {
      return new Promise(function (resolve) {
        const start = +(el.dataset.countStart ?? 0);
        const end = +(el.dataset.countEnd ?? 0);
        const direction = Math.sign(end - start);
        let value = +(el.dataset.countValue ?? start);
        el.textContent = value;
        let intervalId = setInterval(function() {
          value += direction;
          el.textContent = value;
          if (direction > 0 ? value >= end : value <= end) {
            clearInterval(intervalId);
            intervalId = false;
            resolve(el);
          }
          el.dataset.countValue = value;
        }, rate);
      })
    }
    <div class="counter" data-count-start="0" data-count-end="1"></div>
    <div class="counter" data-count-start="0" data-count-end="2"></div>
    <div class="counter" data-count-start="0" data-count-end="3"></div>
    <div class="counter" data-count-start="0" data-count-end="14"></div>
    <div class="counter" data-count-start="10" data-count-end="0"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search