How to write a countdown timer in JavaScript?

722,714

Solution 1

I have two demos, one with jQuery and one without. Neither use date functions and are about as simple as it gets.

Demo with vanilla JavaScript

function startTimer(duration, display) {
    var timer = duration, minutes, seconds;
    setInterval(function () {
        minutes = parseInt(timer / 60, 10);
        seconds = parseInt(timer % 60, 10);

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.textContent = minutes + ":" + seconds;

        if (--timer < 0) {
            timer = duration;
        }
    }, 1000);
}

window.onload = function () {
    var fiveMinutes = 60 * 5,
        display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
};
<body>
    <div>Registration closes in <span id="time">05:00</span> minutes!</div>
</body>

Demo with jQuery

function startTimer(duration, display) {
    var timer = duration, minutes, seconds;
    setInterval(function () {
        minutes = parseInt(timer / 60, 10);
        seconds = parseInt(timer % 60, 10);

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.text(minutes + ":" + seconds);

        if (--timer < 0) {
            timer = duration;
        }
    }, 1000);
}

jQuery(function ($) {
    var fiveMinutes = 60 * 5,
        display = $('#time');
    startTimer(fiveMinutes, display);
});

However if you want a more accurate timer that is only slightly more complicated:

function startTimer(duration, display) {
    var start = Date.now(),
        diff,
        minutes,
        seconds;
    function timer() {
        // get the number of seconds that have elapsed since 
        // startTimer() was called
        diff = duration - (((Date.now() - start) / 1000) | 0);

        // does the same job as parseInt truncates the float
        minutes = (diff / 60) | 0;
        seconds = (diff % 60) | 0;

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.textContent = minutes + ":" + seconds; 

        if (diff <= 0) {
            // add one second so that the count down starts at the full duration
            // example 05:00 not 04:59
            start = Date.now() + 1000;
        }
    };
    // we don't want to wait a full second before the timer starts
    timer();
    setInterval(timer, 1000);
}

window.onload = function () {
    var fiveMinutes = 60 * 5,
        display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
};
<body>
    <div>Registration closes in <span id="time"></span> minutes!</div>
</body>

Now that we have made a few pretty simple timers we can start to think about re-usability and separating concerns. We can do this by asking "what should a count down timer do?"

  • Should a count down timer count down? Yes
  • Should a count down timer know how to display itself on the DOM? No
  • Should a count down timer know to restart itself when it reaches 0? No
  • Should a count down timer provide a way for a client to access how much time is left? Yes

So with these things in mind lets write a better (but still very simple) CountDownTimer

function CountDownTimer(duration, granularity) {
  this.duration = duration;
  this.granularity = granularity || 1000;
  this.tickFtns = [];
  this.running = false;
}

CountDownTimer.prototype.start = function() {
  if (this.running) {
    return;
  }
  this.running = true;
  var start = Date.now(),
      that = this,
      diff, obj;

  (function timer() {
    diff = that.duration - (((Date.now() - start) / 1000) | 0);

    if (diff > 0) {
      setTimeout(timer, that.granularity);
    } else {
      diff = 0;
      that.running = false;
    }

    obj = CountDownTimer.parse(diff);
    that.tickFtns.forEach(function(ftn) {
      ftn.call(this, obj.minutes, obj.seconds);
    }, that);
  }());
};

CountDownTimer.prototype.onTick = function(ftn) {
  if (typeof ftn === 'function') {
    this.tickFtns.push(ftn);
  }
  return this;
};

CountDownTimer.prototype.expired = function() {
  return !this.running;
};

CountDownTimer.parse = function(seconds) {
  return {
    'minutes': (seconds / 60) | 0,
    'seconds': (seconds % 60) | 0
  };
};

So why is this implementation better than the others? Here are some examples of what you can do with it. Note that all but the first example can't be achieved by the startTimer functions.

An example that displays the time in XX:XX format and restarts after reaching 00:00

An example that displays the time in two different formats

An example that has two different timers and only one restarts

An example that starts the count down timer when a button is pressed

Solution 2

You can easily create a timer functionality by using setInterval.Below is the code which you can use it to create the timer.

http://jsfiddle.net/ayyadurai/GXzhZ/1/

window.onload = function() {
  var minute = 5;
  var sec = 60;
  setInterval(function() {
    document.getElementById("timer").innerHTML = minute + " : " + sec;
    sec--;
    if (sec == 00) {
      minute --;
      sec = 60;
      if (minute == 0) {
        minute = 5;
      }
    }
  }, 1000);
}
Registration closes in <span id="timer">05:00<span> minutes!

Solution 3

If you want a real timer you need to use the date object.

Calculate the difference.

Format your string.

window.onload=function(){
      var start=Date.now(),r=document.getElementById('r');
      (function f(){
      var diff=Date.now()-start,ns=(((3e5-diff)/1e3)>>0),m=(ns/60)>>0,s=ns-m*60;
      r.textContent="Registration closes in "+m+':'+((''+s).length>1?'':'0')+s;
      if(diff>3e5){
         start=Date.now()
      }
      setTimeout(f,1e3);
      })();
}

Example

Jsfiddle

not so precise timer

var time=5*60,r=document.getElementById('r'),tmp=time;

setInterval(function(){
    var c=tmp--,m=(c/60)>>0,s=(c-m*60)+'';
    r.textContent='Registration closes in '+m+':'+(s.length>1?'':'0')+s
    tmp!=0||(tmp=time);
},1000);

JsFiddle

Share:
722,714

Related videos on Youtube

Bartek
Author by

Bartek

Updated on March 12, 2021

Comments

  • Bartek
    Bartek about 3 years

    Just wanted to ask how to create the simplest possible countdown timer.

    There'll be a sentence on the site saying:

    "Registration closes in 05:00 minutes!"

    So, what I want to do is to create a simple js countdown timer that goes from "05:00" to "00:00" and then resets to "05:00" once it ends.

    I was going through some answers before, but they all seem too intense (Date objects, etc.) for what I want to do.

    • Sikshya Maharjan
      Sikshya Maharjan over 10 years
      And again, you're leaving out the relevant HTML, though at least you've sort of explained the complexity issue this time. But seriously, you need to look into making a solution yourself, and then come and ask us about problems you're having.
    • bjb568
      bjb568 over 10 years
      Code examples with complaints on how they are too complicated? Anyway, I think you could easily setInterval and make it .innerHTML based, instead of date based.
    • Carlos Rafael Ramirez
      Carlos Rafael Ramirez about 9 years
      Yes, people should look for making the solution themselves. But with javaScript there are plenty examples of doing common tasks. I know how to do a count down timer, but I prefer if I find one in the web (like a component). So thanks to this question and the extensive answer I found what I was looking for. Countdown logic
    • nu everest
      nu everest over 7 years
      I found these solutions to be simpler: stackoverflow.com/questions/32141035/…
    • Erich García
      Erich García over 7 years
  • Bartek
    Bartek over 10 years
    You're the man! That's exactly what I was looking for. Thank you! One more thing: how can I add "0" in front of minutes, so it shows "04:59", instead of "4:59"?
  • robbmj
    robbmj over 10 years
    minutes = minutes < 10 ? "0" + minutes : minutes;
  • timbram
    timbram almost 9 years
    In the very first demo, with Vanilla JavaScript, what kind of variable is timer? I have never seen anything like that! And how can you set it when minutes and seconds are not yet defined?
  • robbmj
    robbmj almost 9 years
    @timbram timer, initially is just a copy of the paramater duration and it is just a number. The reason why it is needed is to keep track of the remaining time, that can't be done with the duration parameter as the timer needs to be reset when it reaches 0. minutes and seconds are calculated based on the value of timer. Hope this helps.
  • abustamam
    abustamam almost 9 years
    @timbram it looked weird to me at first too, until i realized that a comma after a var declaration separates different declarations. so minutes and seconds are simply declared (but un-initialized) variables. so timer is simply just equal the the duration parameter, nothing more, nothing less.
  • Sinan Erdem
    Sinan Erdem about 8 years
    Thank you! What is the best way to add Pause/Resume functionality to the last script?
  • robbmj
    robbmj about 8 years
    @SinanErdem I have written some code that does this. I can add that code to the answer later today. I will ping you when this is done.
  • Savvas Parastatidis
    Savvas Parastatidis about 8 years
    Is there a way to find the current value of the timer or how much time has passed since its start? I could parse the html value but it's a bit silly when the real value is there!
  • Sangamesh Davey
    Sangamesh Davey almost 8 years
    How to call a functions once the timer become 00:00???
  • Santosh Pillai
    Santosh Pillai almost 8 years
    is there any way to stop the js demo from resetting once it reaches 0 ?
  • Santosh Pillai
    Santosh Pillai almost 8 years
    stopped it from resetting by if (--timer < 0) { timer = 0; }
  • Dzung Nguyen
    Dzung Nguyen over 7 years
    How do you add a reset options? And also a pause and resume? I tried adding a field this.reset, and check that in the closure. But the clock keeps going though.
  • Edgar
    Edgar over 7 years
    (diff / 60) | 0; - what is | here? How is it called?
  • Edgar
    Edgar over 7 years
    I found this answer: stackoverflow.com/questions/7487977/… . What I was looking for.
  • robbmj
    robbmj over 7 years
    @Edgar yep that's what it does.
  • Ricky Mason
    Ricky Mason about 7 years
    @robbmj Hey - great post. Thanks - Did you ever implement the pause feature? Could really use that in one of the projects im working on.
  • BornToCode
    BornToCode over 6 years
    In what way is the second version "more accurate"?
  • robbmj
    robbmj over 6 years
    @BornToCode Using a Date object to calculate exactly how much time is remaining or has elapsed is needed as setInterval and setTimeout can't guarantee that they will be called in exactly n milliseconds.
  • Scott Rowley
    Scott Rowley over 6 years
    Does not accurately represent each second, it's counting down much too fast.
  • Scott Rowley
    Scott Rowley over 6 years
    Changing the 500 to 1000 seems to make it accurate.
  • shikiko
    shikiko over 6 years
    anyone know hwo to add ike 2 more minutes after it stops at 0?
  • Mike Pala
    Mike Pala over 6 years
    @robbmj I really like your solution... the first one, the vanilla one :) if you have a moment could you please show me how you would add a reset button to that solution. I mean a button that would NOT stop the timer... just reset it back to 5:00 ... so it would automatically go to 4:59... 4:58 ... etc
  • epascarello
    epascarello about 6 years
    Answer is flawed because of the use of setTimeout/Interval since it does not fire accurately.
  • robbmj
    robbmj about 6 years
    @epascarello please see last section for a more accurate timer that deals with the inaccuracy of setTimeout and setInterval.
  • Zoltán Süle
    Zoltán Süle over 5 years
    there is a bug in the jquery code: displayId.text(minutes + ":" + seconds); The right way is: displayId.html(minutes + ":" + seconds);
  • robbmj
    robbmj over 5 years
    @ZoltánSüle I should probably update the answer so that the normal JS uses innerHTML as well.
  • Zoltán Süle
    Zoltán Süle over 5 years
    @robbmj I was wrong. In this case there is no real difference between the text() and the html() functions
  • robbmj
    robbmj over 5 years
    @ZoltánSüle no worries, better to point something out and be wrong then let a potential bug slip through.
  • Mostafa
    Mostafa over 5 years
    How stop timer after a button clicked...and then start it again after another click?
  • Melu
    Melu about 5 years
    excellent timer, one suggestion is to do something like var objMyInterval = setInterval(function timer() {... now to stop timer after minutes <= 0 & seconds <=0 just call clearInterval(objMyInterval);
  • V1xIII
    V1xIII almost 4 years
    How would you go about making the simple example also display hours?
  • robbmj
    robbmj almost 4 years
    @V1xIII This should do what you want: jsfiddle.net/ejdcwmuy
  • embulldogs99
    embulldogs99 almost 4 years
    Slick solution, hour should be changed to minute though to avoid confusion
  • Shiz
    Shiz over 3 years
    though it doesn't look simplest to me
  • LeCoda
    LeCoda almost 3 years
    If I want to include Hours, so have as output to display a common Hrs:Mins:Sec output, how would I change this code
  • Pedro Joaquín
    Pedro Joaquín almost 3 years
    is there any way to restart the timer? i tried but it just launches several timers at the same time