JSFiddle - React, Tailwind, and code Playground

by Kevin Faulhaber

HTML

<div id="results"></div>
<button id="stop">Stop</button>

JavaScript

(function () {
    var t = function (o) {
        if (!(this instanceof t)) {
            return new t(o);
        }
        this.target = o.target || null;

        this.message = o.message;
        this.endMessage = o.endMessage;

        //setInterval id
        this.si = -1;

        //Initial start and end
        this.startTime = null;
        this.endTime = null;
        this.interTime = null;
        this.duration = o.duration || 1000 * 60 * 5;

        //looping speed miliseconds it is best to put the loop at a faster speed so it doesn't miss out on something
        this.loop = o.loop || 300;

        //showing results miliseconds
        this.show = o.show || 1000;
    };
    t.fn = t.prototype = {
        init: function () {}
    };
    //exporting
    window.t = t;

})();

//Timer Functions --- 
t.fn.start = function () {
    this.startTime = new Date();
    this.interTime = this.startTime.getTime()-this.loop;
    this.endTime = new Date().setMilliseconds(this.startTime.getMilliseconds() + this.duration);
    
    //returns undefined... for some reason.
    console.log(this.startTime + ' ' + this.endTime);

    var $this = this;
    this.writeMessage(this.duration);
    this.si = setInterval(function () {
        var current = new Date(),
            milli = current.getTime();

        if (milli - $this.interTime >= $this.show) {
            var left = $this.endTime- milli;
            if (left <= 0) {
                $this.stop();
            } else {
                $this.interTime = milli;
                $this.writeMessage(left);
            }

        }
    }, this.loop);
    return this;
};

t.fn.writeMessage = function(left){
    this.target.innerHTML = this.message + ' ' + Math.floor(left / 1000);
    return this;
};
t.fn.stop = function () {
    //stopping the timer
    clearInterval(this.si);
    this.si = -1;
    this.target.innerHTML = this.endMessage;
    return this;

};

//Not chainable
t.fn.isRunning = function () {
    return this.si...