Home > front end >  Display each element in array to DOM
Display each element in array to DOM

Time:10-05

I'm making a countdown timer and running into an issue getting it to display the way I want. I wanted to break down the days, hours, and minutes and display each as their own digit. Otherwise it displays as one whole number. This is how I want it to look: enter image description here

The problem is when I am displaying the data to the DOM, I'm only getting the last item in the array. How can I get the whole time to display as individual digits?

let countDownDate = new Date("Jan 5, 2022 7:37:25").getTime();

const x = setInterval(function() {
  let now = new Date().getTime();
  const distance = countDownDate - now;
  let days = Math.floor(distance / (1000 * 60 * 60 * 24));
  let daysNumber = days.toString();
  let daysDigits = [];
  for (var i = 0, len = daysNumber.length; i < len; i  = 1) {
    daysDigits.push( daysNumber.charAt(i));
  };

  Array.prototype.forEach.call(daysDigits, digit => {
    document.querySelector('.days').innerHTML = `<span class="digit">${digit}</span>`
  });

  console.log("days in digits "   daysDigits);

  let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  let hoursNumber = hours.toString();
  let hoursDigits = [];
  for (var i = 0, len = hoursNumber.length; i < len; i  = 1) {
    hoursDigits.push( hoursNumber.charAt(i));
  }

  Array.prototype.forEach.call(hoursDigits, digit => {
    document.querySelector('.hours').innerHTML = `<span class="digit">${digit}</span>`

  });

  console.log("hours in digits "   hoursDigits);

  let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  let minutesNumber = minutes.toString();
  let minutesDigits = [];
  for (var i = 0, len = minutesNumber.length; i < len; i  = 1) {
    minutesDigits.push( minutesNumber.charAt(i));
  }

  Array.prototype.forEach.call(minutesDigits, digit => {
    document.querySelector('.minutes').innerHTML = `<span class="digit">${digit}</span>`
  });
  console.log("minutes in digits "   minutesDigits);


  if (distance < 0) {
    clearInterval(x);
    document.getElementById("timer").innerHTML = "EXPIRED";
  }
}, 1000);
<div class="grid grid--justify-around">
  <div class="grid__col--2 u-textAlignCenter">
    <div class="days">
    </div>
    <p class="u-textWeightBold">days</p>
  </div>
  <div class="grid__col--2 u-textAlignCenter">
    <div class="hours">
    </div>
    <p>hours</p>
  </div>
  <div class="grid__col--2 u-textAlignCenter">
    <div class="minutes">
    </div>
    <p>minutes</p>
  </div>
</div>

CodePudding user response:

You're overwriting the innerHTML each time through the forEach loop, not appending to it.

You need to empty the DIV first, then concatenate each digit.

let countDownDate = new Date("Jan 5, 2022 7:37:25").getTime();

const x = setInterval(function() {
  let now = new Date().getTime();
  const distance = countDownDate - now;
  let days = Math.floor(distance / (1000 * 60 * 60 * 24));
  let daysNumber = days.toString();
  let daysDigits = [];
  for (var i = 0, len = daysNumber.length; i < len; i  = 1) {
    daysDigits.push( daysNumber.charAt(i));
  };

  document.querySelector(".days").innerHTML = "";
  daysDigits.forEach(digit => {
    document.querySelector('.days').innerHTML  = `<span class="digit">${digit}</span>`
  });

  console.log("days in digits "   daysDigits);

  let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
  let hoursNumber = hours.toString();
  let hoursDigits = [];
  for (var i = 0, len = hoursNumber.length; i < len; i  = 1) {
    hoursDigits.push( hoursNumber.charAt(i));
  }

  document.querySelector('.hours').innerHTML = "";
  hoursDigits.forEach(digit => {
    document.querySelector('.hours').innerHTML  = `<span class="digit">${digit}</span>`

  });

  console.log("hours in digits "   hoursDigits);

  let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  let minutesNumber = minutes.toString();
  let minutesDigits = [];
  for (var i = 0, len = minutesNumber.length; i < len; i  = 1) {
    minutesDigits.push( minutesNumber.charAt(i));
  }

  document.querySelector('.minutes').innerHTML = "";
  minutesDigits.forEach(digit => {
    document.querySelector('.minutes').innerHTML  = `<span class="digit">${digit}</span>`
  });
  console.log("minutes in digits "   minutesDigits);


  if (distance < 0) {
    clearInterval(x);
    document.getElementById("timer").innerHTML = "EXPIRED";
  }
}, 1000);
<div class="grid grid--justify-around">
  <div class="grid__col--2 u-textAlignCenter">
    <div class="days">
    </div>
    <p class="u-textWeightBold">days</p>
  </div>
  <div class="grid__col--2 u-textAlignCenter">
    <div class="hours">
    </div>
    <p>hours</p>
  </div>
  <div class="grid__col--2 u-textAlignCenter">
    <div class="minutes">
    </div>
    <p>minutes</p>
  </div>
</div>

CodePudding user response:

Two issues:

  • Make sure you have 2 digits in your string: so prepend a "0" if needed

  • First generate the span elements, and then join them into one string to assign to the innerHTML, instead of overwriting in each iteration innerHTML

So for example for the hours:

let hoursNumber = hours.toString().padStart(2, "0");
                               // ^^^^^^^^^^^^^^^^

And the loop to set innerHTML:

document.querySelector('.hours').innerHTML = hoursDigits.map(digit =>
  `<span class="digit">${digit}<\/span>`
).join("");
  • Related