JavaScript timer example to set up countdowns

I recently wrote a timer function (to display a countdown on a webpage) with JavaScript which uses the singleton pattern described by Kai Jäger.

The usage is very simple, as you can see here:

HTML

<div id="myTimer"></div>

JavaScript

<script src="./js/timer-singleton.js"></script>
<script>
  // A 12 minutes (12 * 60 seconds = 720) long timer:
  var timer = Timer.getInstance(); 	  
  var callback = function(){
    alert('Time expired. :-)');
  };
  timer.createTimer('myTimer',720,callback);
  timer.startTimer();
</script>

timer-singleton.js

// https://developer.mozilla.org/en/DOM/window.setTimeout
var Timer = (function(){
  var instance = null;
  function PrivateConstructor(){
    var timer = null; // DOM element, that displays the time
    var remainingSeconds = 0; // Remaining seconds
    var initialSeconds = 0; // Time that was initially set
    var ticker = null; // Ticker which ticks every second
    var isRunning = false; // true, when the timer is running
    var timeExpiredAction = function(){
      console.log('Time expired.');
    };
 
    // 0) Method to set and display the timer
    this.createTimer = function(timerId,time,callback){
      if(typeof(callback) == 'function'){
        timeExpiredAction = callback;
      }
      timer = document.getElementById(timerId);
      initialSeconds = time;
      remainingSeconds = time;
      displayTime();
    };
 
    // 1) Starts the timer
    this.startTimer = function(){
      startTicking();
    };
 
    // 2) Internal method to realize the ticks
    var startTicking = function(){            
      if(isRunning == true)
        return;
      else
        isRunning = true;        
 
      function tick(){
        if (remainingSeconds <= 0){
          isRunning = false;
          displayTime();
          timeExpiredAction();
          return;
        }
        else{
          remainingSeconds -= 1;
          displayTime();
        }
        ticker = window.setTimeout(tick, 1000);
      }
      ticker = window.setTimeout(tick, 1000);
    };  
 
    // 3) Internal method to display the time
    var displayTime = function(){
      function addLeadingZero(time){
        return (time < 10) ? '0' + time : + time;
      }
      var seconds = remainingSeconds;
      var days = Math.floor(seconds / 86400);
      seconds -= days * 86400;
      var hours = Math.floor(seconds / 3600);
      seconds -= hours * (3600);
      var minutes = Math.floor(seconds / 60);
      seconds -= minutes * (60);
      var timeString = ((days > 0) ? days + ' days ' : '') 
      + addLeadingZero(hours) 
      + ':' + addLeadingZero(minutes) 
      + ':' + addLeadingZero(seconds)
      timer.innerHTML = timeString;
    };
 
    // 4) Pauses the timer
    this.pauseTimer = function(){
      window.clearTimeout(ticker); 
      ticker = null;
      isRunning = false;
    };
 
    // 5) Continues the timer
    this.resumeTimer = function(){
      ticker = window.setTimeout(startTicking(), 10);
    };
 
    // 6) Pauses the timer, if it is running
    // OR continues the timer, if it is not running
    this.toggleTimer = function(){
      if(ticker != null)
        this.pauseTimer();
      else
        this.resumeTimer();
    };
 
    // 7) Resets the time to the initial time
    this.resetTimer = function(){
      remainingSeconds = initialSeconds;
      displayTime();
    };
 
    // 8) Resets the time to the initial time and starts ticking
    this.resetAndStartTimer = function(){
      this.resetTimer();
      startTicking();
    };
 
    // 9) Returns the remaining seconds of the timer
    this.getRemainingSeconds = function(){
      return remainingSeconds;
    };
 
    // 10) Sets the timer to a different time
    this.setSeconds = function(seconds){
      remainingSeconds = seconds;
      displayTime();
    };
  }
  return new function(){
    // Singleton for the timer
    this.getInstance = function(){
      if (instance == null){
        instance = new PrivateConstructor();
        instance.constructor = null;
      }
      return instance;
    }
  }
})();

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.