skip to Main Content

I’m encountering an issue with an animated counter on my website. The counter is intended to simulate a statistic and works perfectly on desktop browsers. However, when accessed on mobile devices in a production environment, there seems to be a problem with parsing or conversion that resets any number above 999, consequently resetting the initial number.

Here’s the relevant HTML code snippet:

<span id="counter">4898988</span><br />

Here’s the relevant JavaScript code snippet:

document.addEventListener('DOMContentLoaded', (event) => {
  const counterElement = document.getElementById('counter');
  console.log('counterElement:', counterElement); // log the counterElement
  counterElement.textContent = `${parseInt(counterElement.textContent, 10).toLocaleString()} USD`; // format the initial number
  console.log('counterElement.textContent after formatting:', counterElement.textContent); // log the textContent after formatting
  animateCount(counterElement);
  
  // Animate the counter
  function animateCount(targetElement) {
    console.log('targetElement in animateCount:', targetElement); // log the targetElement in animateCount
    let count = parseInt(targetElement.textContent.replace(/,/g, ''), 10);
    console.log('count after parsing:', count); // log the count after parsing
    const finalCount = count + Math.floor(Math.random() * 31); // generate a random number between 0 and 30
    const interval = setInterval(() => {
      if (count < finalCount) {
        count++;
        targetElement.textContent = `${count.toLocaleString()} USD`;
      } else {
        clearInterval(interval);
        setTimeout(() => animateCount(targetElement), Math.random() * 9000 + 5000); // wait for a random period between 5 and 14 seconds before starting the next cycle
      }
    }, 100);
  }
});

Console log:

[Log] counterElement:
<span id="counter">4 898 988 USD</span>
[Log] after formatting: – "4 898 988 USD"
[Log] animateCount: 
<span id="counter">4 898 988 USD</span>
[Log] count after parsing: – 4 

As you can see, the ‘let count =’ line seems to not parse correctly a number above 999.

2

Answers


  1. The behavior of toLocaleString changes based on the user’s local, which makes parsing it much more complicated than it should be.
    A solution is to keep track of the count in a variable, rather than parsing it from the DOM every time:
    Working example: https://codepen.io/jacob_124/pen/JjVbjoL

    document.addEventListener("DOMContentLoaded", (event) => {
      const counterElement = document.getElementById("counter");
      // Initialize number based off of text
      const num = parseInt(counterElement.textContent, 10);
    
      counterElement.textContent = `${num.toLocaleString()} USD`; // format the initial number
      console.log(
        "counterElement.textContent after formatting:",
        counterElement.textContent
      ); // log the textContent after formatting
      animateCount(counterElement, num);
    
      // Animate the counter
      function animateCount(targetElement, count) {
        const finalCount = count + Math.floor(Math.random() * 31); // generate a random number between 0 and 30
        const interval = setInterval(() => {
          if (count < finalCount) {
            count++;
            targetElement.textContent = `${count.toLocaleString()} USD`;
          } else {
            clearInterval(interval);
            setTimeout(
              () => animateCount(targetElement, count),
              Math.random() * 9000 + 5000
            ); // wait for a random period between 5 and 14 seconds before starting the next cycle
          }
        }, 100);
      }
    });
    
    Login or Signup to reply.
  2. document.addEventListener('DOMContentLoaded', (event) => {
      const counterElement = document.getElementById('counter');
      console.log('counterElement:', counterElement);
      counterElement.textContent = formatNumber(counterElement.textContent) + ' USD';
      console.log('counterElement.textContent after formatting:', counterElement.textContent);
      animateCount(counterElement);
    
      // Format number with commas for thousands
      function formatNumber(number) {
        return number.replace(/B(?=(d{3})+(?!d))/g, ",");
      }
    
      // Animate the counter
      function animateCount(targetElement) {
        console.log('targetElement in animateCount:', targetElement);
        let count = parseInt(targetElement.textContent.replace(/,/g, ''), 10);
        console.log('count after parsing:', count);
        const finalCount = count + Math.floor(Math.random() * 31);
        const interval = setInterval(() => {
          if (count < finalCount) {
            count++;
            targetElement.textContent = formatNumber(count.toString()) + ' USD';
          } else {
            clearInterval(interval);
            setTimeout(() => animateCount(targetElement), Math.random() * 9000 + 5000);
          }
        }, 100);
      }
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search