DEV Community

Cover image for Improving my counter
Grant Smith
Grant Smith

Posted on

Improving my counter

I've created a count-up clock that I'd like some help refining if you wouldn't mind. Currently, I have two issues that are bugging (pun intended!) me.

  1. The counter doesn't count up the hours, when it reaches two hours, it goes back to 01:01:01
  2. The numbers jump around

Here is my code so far…

// Counter

if (!!document.getElementById("counter")) {
  var minutesLabel = document.getElementById("minutes");
  var secondsLabel = document.getElementById("seconds");
  var totalSeconds = Number(secondsLabel.textContent);
  var totalMinutes = Number(minutesLabel.textContent);

  setInterval(setTime, 1000);

  function setTime() {
   ++totalSeconds;
   secondsLabel.innerHTML = pad(totalSeconds % 60);
   minutesLabel.innerHTML = pad(parseInt(totalMinutes + totalSeconds / 60));
  }

  function pad(val) {
   var valString = val + "";
   if (valString.length < 2) {
    return "0" + valString;
   } else {
    return valString;
   }
  }
 }

// End Counter
#counter {
  background-color: #ee1a25; // TODO: Change this to a pattern
  color: $white;
  text-align: center;

  .counter_wrapper {
    flex-direction: column;

    @include desktop {
      flex-direction: row;
    }
  }

  .counter_container {
    display: flex;
    align-items: center;
    flex-direction: row;
    justify-content: center;

    .counter_number {
      font-weight: regular;
      font-size: 60px;
      font-family: $family-primary;

      font-feature-settings: "tnum";
      font-variant-numeric: tabular-nums;
      @include widescreen {
        font-size: 133px;
      }
    }

    .divider {
      display: inline-block;
      margin: 0 16px;
      width: 8px;
      height: 30px;

      @include widescreen {
        margin: 0 34px;
        width: 16px;
        height: 60px;
      }
    }
  }
}

I'd apprecitate any help and advice offered please

Top comments (5)

Collapse
 
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan • Edited
  1. Consider using String.prototype.padStart: developer.mozilla.org/en-US/docs/W....

  2. You don't currently do anything with hours in the JavaScript, so that's why it's not changing. You're only setting the minutes and seconds. You'll need to get a reference to the hours label like you did with minutes and seconds and then set it to be parseInt(totalSeconds / 3600).

  3. Why do this? if (!!document.getElementById("counter"). Just do this: if (document.getElementById("counter")). Applying the negation operator twice is the same thing as not applying it at all.

Regarding this concern:

The numbers jump around

What do you mean? It may be helpful to include a link to a jsfiddle with all of your HTML, CSS, and JS so we can run it on our end.

One final thing to note: You don't need totalMinutes. Given a number of seconds, the number of minutes it represents is equal to parseInt(totalSeconds / 60) % 60. Since you're tallying the seconds, you don't need to also tally the minutes.

Improved code: jsfiddle.net/41o7tz3n/6/.

Collapse
 
granttransition profile image
Grant Smith • Edited

This is fantastic, thank you. As for the numbers jumping around, I posted a gif at the top of the post. It is hopefully attached below, although this isn't that important.

One important thing though (customer request), I need the numbers to start from 01:34:06. Using your method, how would you set the starting numbers?

New Timer

Collapse
 
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan

how would you set the starting numbers

Just in the HTML, if it's a fixed start. Otherwise you can just use JS to allow users to enter a start time.

Thread Thread
 
granttransition profile image
Grant Smith • Edited

Yeah, that is exactly what I have done. Page loads with 01:32:20 and then changes the timer to 00:00:20.

<div class="column is-8 counter_container">
 <span id="hours" class="counter_number">01</span>
 <img class="divider" src="dist/svg/counter-divider.svg" alt="Counter divider" width="16" height="60">
 <span id="minutes" class="counter_number">32</span>
 <img class="divider" src="dist/svg/counter-divider.svg" alt="Counter divider" width="16" height="60">
 <span id="seconds" class="counter_number">20</span>
</div>

I'll keep working at it, the help is much appreciated, thank you

Collapse
 
granttransition profile image
Grant Smith • Edited

Here is what I worked out; I never actually used the hours or minutes values in the HTML to start with. I was only using the seconds, calculating all the labels with that. The totalSeconds variable should account for the hours and minutes.

So here is the code I ended up with…

if (document.getElementById("counter")) {
  const hoursLabel = document.getElementById("hours");
  const minutesLabel = document.getElementById("minutes");
  const secondsLabel = document.getElementById("seconds");

    // add all the time values together to give a proper total start point
  let totalSeconds = 
        Number(secondsLabel.textContent)+
        Number(minutesLabel.textContent*60)+
        Number(hoursLabel.textContent*3600);

  setInterval(setTime, 1000);

  function setTime() {
    ++totalSeconds;

      // pull the number of hours out of the total for reference
     const numHours = parseInt(totalSeconds / 3600)

     //remove that number fromt he total because it messes up the /60 math if you have extra 3600's in there
     const secondsLeft = parseInt(totalSeconds - 3600 * numHours)

     // tweak these for new variables available
    secondsLabel.innerHTML = padWithZero(secondsLeft % 60);
    minutesLabel.innerHTML = padWithZero(parseInt(secondsLeft / 60));
    hoursLabel.innerHTML = padWithZero(numHours);
  }

  function padWithZero(num) {
    return Number(num)
      .toString()
      .padStart(2, "0");
  }
}