JSFiddle - React, Tailwind, and code Playground

by Tan

HTML

<div id="progress">
  <div id="prog-2m"></div>
  <div id="prog-8m"></div>
</div>
<div id="clock">0:00</div>


<button id="start">Begin</button>

CSS

#progress {
  width: 200px;
  height: 20px;
  border: 2px solid #fff;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  border-radius: 2px;
  position: relative;
  margin: 8px 0;
}
#prog-2m {
  width: 0px;
  height: 20px;
  background-color: #3c9;
  position: absolute;
  left: 0;
  top: 0;
}
#prog-8m {
  width: 0px;
  height: 20px;
  background-color: #c33;
  position: absolute;
  left: 40px;
  top: 0;
}

JavaScript

// CountdownTimer object. Give it a length (ms) to count to, a period (ms)
// to loop updates to the callback, and a callback (function(done:bool)) that
// handles update ticks where done=false and the final tick where done=true.

function CountdownTimer(length, period, callback) {


  this.length = length;
  this.period = period;
  this.callback = callback;
  
  // Assert the callback to be a function to avoid messy error handling, and
  // show we noticed in the console.

  if (typeof this.callback !== 'function') {
    console.warn('Callback was not a function.');
    this.callback = function(){};
  }
  
  // Some publically visible variables for time keeping.

  this.startTime = 0;
  this.elapsed = 0;
  this.remaining = length;
  
  // The _loop scope's 'this' is itself. Give it a handle on the CountdownTimer's
  // 'this' so we can reference the variables inside the loop.
  var scope = this;
  
  // Main loop of the countdown timer.

  this._loop = function() {

    // Get the number of milliseconds since the countdown started.
    scope.elapsed = Date.now() - scope.startTime;

    if (scope.elapsed < scope.length) {

      // Keep looping if the countdown is not yet finished.
      scope.remaining = scope.length - scope.elapsed;
      scope.callback(false);

    } else {

      // Finished looping when the countdown hits or passes the target.
      scope.elapsed = scope.length;
      scope.remaining = 0;
      scope.callback(true);
      // Stop the interval timer from looping again.
      clearInterval(scope._t);

    }
  };
}

// This function starts up the CountdownTimer
CountdownTimer.prototype.start = function() {
  this.startTime = Date.now();
  this._t = setInterval(this._loop, this.period);
}

// Our test elements.
var progress2 = document.getElementById('prog-2m');
var progress8 = document.getElementById('prog-8m');
var clockElement = document.getElementById('clock');
var startButton = document.getElementById('start');

// SET TIME

var tot =...