0

I m trying to create multiples counters on a same page using javascript and setInterval.

The problem in my code is it only update for the last element.

var newvalue;
var counterworld = document.getElementsByClassName('counterworld');
for (var i = 0; i < counterworld.length; ++i) {
    var item = counterworld[i];
    var counterId = setInterval(function () { item.innerHTML = i + '=>' + countUp(item.getAttribute('data-start'), item.getAttribute('data-increment')) }, 100);
}
function countUp(start, increment) {
    if (newvalue == null) {
        newvalue = parseFloat(start) + parseFloat(increment);
    }
    else {
        newvalue = newvalue + parseFloat(increment);
    }
    if (increment < 1) {
       return newvalue.toLocaleString(undefined, { maximumFractionDigits: 2 });
}
else {
    return newvalue.toLocaleString(undefined, { maximumFractionDigits: 0 });

    }
}
<span class="counterworld" data-increment="1.5" data-start="100">100</span><br />
<span class="counterworld" data-increment="1.28600823045268" data-start="19216060382458.4">19216060382458.4</span><br />
<span class="counterworld" data-increment="0.0317532880531423" data-start="4629347058.7918">4629347058.7918</span>
Yanga
  • 2,885
  • 1
  • 29
  • 32

2 Answers2

1

Change var i to let i and var item to let item for lexical scoping:

var counterworld = document.getElementsByClassName('counterworld');

for (let i = 0; i < counterworld.length; ++i) {
  let item = counterworld[i];
  let value = parseFloat(item.getAttribute('data-start'));
  let increment = parseFloat(item.getAttribute('data-increment'));

  setInterval(function() {
    value += increment;

    item.innerHTML = i + '=>' + value.toLocaleString(undefined, {
      maximumFractionDigits: increment < 1 ? 2 : 0
    });
  }, 100);
}
<span class="counterworld" data-increment="1.5" data-start="100">100</span><br />
<span class="counterworld" data-increment="1.28600823045268" data-start="19216060382458.4">19216060382458.4</span><br />
<span class="counterworld" data-increment="0.0317532880531423" data-start="4629347058.7918">4629347058.7918</span>

Update

I also fixed your code. I expect you intended to produce the behavior above.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • Well your code add the same counter for each elements. It should take the 'data-start' element and add the 'data-increment' for each class 'counterworld' – Yanga Jun 19 '17 at 16:11
  • @Yanga there were a lot of issues with your code, I had to change several things in order to do that. But you're welcome. – Patrick Roberts Jun 19 '17 at 16:12
  • Thank you for your time on this, the code is working as expected. – Yanga Jun 20 '17 at 02:10
1

You need to wrap your item objects inside a closure, like so:

var newvalue;
var counterworld = document.getElementsByClassName('counterworld');
for (var i = 0; i < counterworld.length; ++i) {
    var item = counterworld[i];
    var counterId = setInterval((function (item, i) { 
        return function () {
            item.innerHTML = i + '=>' + countUp(item.getAttribute('data-start'), item.getAttribute('data-increment')); 
        }; 
    })(item, i), 100);
}
function countUp(start, increment) {
    if (newvalue == null) {
        newvalue = parseFloat(start) + parseFloat(increment);
    }
    else {
        newvalue = newvalue + parseFloat(increment);
    }
    if (increment < 1) {
       return newvalue.toLocaleString(undefined, { maximumFractionDigits: 2 });
}
else {
    return newvalue.toLocaleString(undefined, { maximumFractionDigits: 0 });

    }
}
<span class="counterworld" data-increment="1.5" data-start="100">100</span><br />
<span class="counterworld" data-increment="1.28600823045268" data-start="19216060382458.4">19216060382458.4</span><br />
<span class="counterworld" data-increment="0.0317532880531423" data-start="4629347058.7918">4629347058.7918</span>
Chitharanjan Das
  • 1,283
  • 10
  • 15