user1752759
user1752759

Reputation: 635

Countdown Timer With Class

I have the following lines of code on my web page - example/demo.

HTML:

<p class="countdown-timer">10:00</p>

<p class="countdown-timer">10:00</p>

JavaScript:

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);
}

$(document).ready(function(){
    // set the time (60 seconds times the amount of minutes)
    var tenMinutes = 60 * 10,
        display = document.querySelector('.countdown-timer');
    startTimer(tenMinutes, display);
}); 

As I'm relatively new to JavaScript/jQuery, how would I be able to make the timer stop on 0 and so that the second clock also works?

I have tried replacing document.querySelector('.countdown-timer'); with $('.countdown-timer');

Upvotes: 0

Views: 3031

Answers (4)

blex
blex

Reputation: 25634

I created a class to do that a while ago, for one of my projects. It allows you to have multiple counters, with different settings. It can also be configured to be paused or reset with a button, using the available functions. Have a look at how it's done, it might give you some hints:

/******************
 * STOPWATCH CLASS
 *****************/

function Stopwatch(config) {
  // If no config is passed, create an empty set
  config = config || {};
  // Set the options (passed or default)
  this.element = config.element || {};
  this.previousTime = config.previousTime || new Date().getTime();
  this.paused = config.paused && true;
  this.elapsed = config.elapsed || 0;
  this.countingUp = config.countingUp && true;
  this.timeLimit = config.timeLimit || (this.countingUp ? 60 * 10 : 0);
  this.updateRate = config.updateRate || 100;
  this.onTimeUp = config.onTimeUp || function() {
    this.stop();
  };
  this.onTimeUpdate = config.onTimeUpdate || function() {
    console.log(this.elapsed)
  };
  if (!this.paused) {
    this.start();
  }
}


Stopwatch.prototype.start = function() {
  // Unlock the timer
  this.paused = false;
  // Update the current time
  this.previousTime = new Date().getTime();
  // Launch the counter
  this.keepCounting();
};

Stopwatch.prototype.keepCounting = function() {
  // Lock the timer if paused
  if (this.paused) {
    return true;
  }
  // Get the current time
  var now = new Date().getTime();
  // Calculate the time difference from last check and add/substract it to 'elapsed'
  var diff = (now - this.previousTime);
  if (!this.countingUp) {
    diff = -diff;
  }
  this.elapsed = this.elapsed + diff;
  // Update the time
  this.previousTime = now;
  // Execute the callback for the update
  this.onTimeUpdate();
  // If we hit the time limit, stop and execute the callback for time up
  if ((this.elapsed >= this.timeLimit && this.countingUp) || (this.elapsed <= this.timeLimit && !this.countingUp)) {
    this.stop();
    this.onTimeUp();
    return true;
  }
  // Execute that again in 'updateRate' milliseconds
  var that = this;
  setTimeout(function() {
    that.keepCounting();
  }, this.updateRate);
};

Stopwatch.prototype.stop = function() {
  // Change the status
  this.paused = true;
};



/******************
 * MAIN SCRIPT
 *****************/

$(document).ready(function() {
  /*
   * First example, producing 2 identical counters (countdowns)
   */
  $('.countdown-timer').each(function() {
    var stopwatch = new Stopwatch({
      'element': $(this),               // DOM element
      'paused': false,                  // Status
      'elapsed': 1000 * 60 * 10,        // Current time in milliseconds
      'countingUp': false,              // Counting up or down
      'timeLimit': 0,                   // Time limit in milliseconds
      'updateRate': 100,                // Update rate, in milliseconds
      'onTimeUp': function() {          // onTimeUp callback
        this.stop();
        $(this.element).html('Go home, it\'s closing time.');
      },
      'onTimeUpdate': function() {      // onTimeUpdate callback
        var t = this.elapsed,
            h = ('0' + Math.floor(t / 3600000)).slice(-2),
            m = ('0' + Math.floor(t % 3600000 / 60000)).slice(-2),
            s = ('0' + Math.floor(t % 60000 / 1000)).slice(-2);
        var formattedTime = h + ':' + m + ':' + s;
        $(this.element).html(formattedTime);
      }
    });
  });
  /*
   * Second example, producing 1 counter (counting up to 6 seconds)
   */
  var stopwatch = new Stopwatch({
    'element': $('.countdown-timer-up'),// DOM element
    'paused': false,                    // Status
    'elapsed': 0,                       // Current time in milliseconds
    'countingUp': true,                 // Counting up or down
    'timeLimit': 1000 * 6,              // Time limit in milliseconds
    'updateRate': 100,                  // Update rate, in milliseconds
    'onTimeUp': function() {            // onTimeUp callback
      this.stop();
      $(this.element).html('Countdown finished!');
    },
    'onTimeUpdate': function() {        // onTimeUpdate callback
      var t = this.elapsed,
          h = ('0' + Math.floor(t / 3600000)).slice(-2),
          m = ('0' + Math.floor(t % 3600000 / 60000)).slice(-2),
          s = ('0' + Math.floor(t % 60000 / 1000)).slice(-2);
      var formattedTime = h + ':' + m + ':' + s;
      $(this.element).html(formattedTime);
    }
  });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
These 2 timers should count down from 10 minutes to 0 seconds:
<p class="countdown-timer">00:10:00</p>
<p class="countdown-timer">00:10:00</p>
But this one will count from 0 to 6 seconds:
<p class="countdown-timer-up">00:00:00</p>

Upvotes: 1

user4164128
user4164128

Reputation:

Here we go, jsfiddle

just changed the querySelector to getElementsByClassName to get all p elements with the same class. You can than start your timer on the different elements by using it's index. No need for a queue :D

$(document).ready(function(){
   // set the time (60 seconds times the amount of minutes)
    var tenMinutes = 60 * 10,
        display = document.getElementsByClassName('countdown-timer');

    startTimer(tenMinutes, display[0]);
    startTimer(tenMinutes, display[1]);
});

Upvotes: 0

DekiChan
DekiChan

Reputation: 385

document.querySelector('.class') will only find first element with .class. If you're already using jQuery I would recommend to do this:

var display = $('.countdown-timer');
for (var i = 0; i < display.length; i++) {
    startTimer(tenMinutes, display[i]);
}

This way it will work for any number of countdown timers.

Upvotes: 0

Pete
Pete

Reputation: 58432

I think your problem is you are passing an array into the startTimer function so it is just doing it for the first item.

If you change the document ready so that you initiate a timer for each instance of .countdown-timer, it should work:

// set the time (60 seconds times the amount of minutes)
var tenMinutes = 60 * 10;

$('.countdown-timer').each(function () {
  startTimer(tenMinutes, this);
});

Example

Upvotes: 1

Related Questions