var AloTimer = (function (TIME_CHAIN, floor, Date, Error) {
// Note that this is not global if require()'d in NodeJS, only plain Javascript
/**
* Creates the timer
* @author Art <a.molcanovas@gmail.com>
* @param {number} [timeout=0] How many milliseconds to have the timeout for
* @param {string[]} [timeChain=["days", "hours", "minutes", "seconds"]] Which units to include in toString().
* Valid values are "days", "hours", "minutes", "seconds", and "ms". With the default setting the output for 1
* hour 53 minutes 11 seconds and 6 milliseconds would be 00:01:53:11.
* @class
* @global
*/
var AloTimer = function (timeout, timeChain) {
/**
* How long the timeout is set for
* @type {number}
*/
this.timeout = timeout || 0;
/**
* When the timeout started
* @type {number}
* @readonly
*/
this.timeStart = new Date().getTime();
/**
* Which units to include in toString()
* @type {string[]}
*/
this.timeChain = timeChain || TIME_CHAIN;
/**
* When the timer was paused. Will hold false if the timer isn't currently paused.
* @type {Date|boolean}
*/
this.pauseTime = false;
}, padLeft = function (str, char, length) {
while (str.length < length) {
str = char + str;
}
return str;
};
/** @global */
AloTimer.prototype = {
/**
* Adds milliseconds to the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
addMS: function (val) {
this.timeout += val;
return this;
},
get timeout() {
return this._timeout;
},
set timeout(num) {
if (!isNaN(num)) {
this._timeout = parseInt(num);
} else {
throw new Error("The timeout must be numeric!");
}
},
/**
* Pauses the timer
* @author Art <a.molcanovas@gmail.com>
* @returns {AloTimer}
*/
pause: function () {
if (this.isPaused) {
console.warn("The timer is already paused");
} else {
this.pauseTime = new Date();
}
return this;
},
/**
* Checks if the timer is currently paused
* @author Art <a.molcanovas@gmail.com>
* @returns {boolean}
*/
get isPaused() {
return this.pauseTime instanceof Date;
},
/**
* Unpauses the timer
* @author Art <a.molcanovas@gmail.com>
* @returns {AloTimer}
*/
unpause: function () {
if (!this.isPaused) {
console.warn("The timer isn't paused");
} else {
this.addMS(this.msSincePause);
this.pauseTime = false;
}
return this;
},
/**
* Returns the number of milliseconds that have passed since the timer was paused
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get msSincePause() {
if (this.isPaused) {
return new Date().getTime() - this.pauseTime;
} else {
return 0;
}
},
/**
* Adds seconds to the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
addSeconds: function (val) {
this.timeout += val * 1000;
return this;
},
/**
* Adds minutes to the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
addMinutes: function (val) {
this.timeout += val * 60000;
return this;
},
/**
* Adds hours to the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
addHours: function (val) {
this.timeout += val * 3600000;
return this;
},
/**
* Adds days to the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
addDays: function (val) {
this.timeout += val * 86400000;
return this;
},
/**
* Subtracts milliseconds from the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
subMS: function (val) {
this.timeout -= val;
return this;
},
/**
* Subtracts seconds from the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
subSeconds: function (val) {
this.timeout -= val * 1000;
return this;
},
/**
* Subtracts minutes from the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
subMinutes: function (val) {
this.timeout -= val * 60000;
return this;
},
/**
* Subtracts hours from the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
subHours: function (val) {
this.timeout -= val * 3600000;
return this;
},
/**
* Subtracts days from the timer
* @author Art <a.molcanovas@gmail.com>
* @param val The amount to add
* @returns {AloTimer}
*/
subDays: function (val) {
this.timeout -= val * 86400000;
return this;
},
/**
* Checks whether the timeout has finished
* @author Art <a.molcanovas@gmail.com>
* @returns {boolean}
*/
get hasFinished() {
return (new Date().getTime() - this.timeStart) >= this.timeout;
},
/**
* Returns the amount of milliseconds remaining
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get msLeft() {
var diff = this.diff;
return diff < this.timeout ? (this.timeout - diff) % 1000 : 0;
},
/**
* Returns the difference between timeStart and now, taking pause time into account
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get diff() {
return new Date().getTime() - this.timeStart - this.msSincePause;
},
/**
* Returns the amount of seconds remaining
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get secondsLeft() {
var diff = this.diff;
return diff < this.timeout ? floor(((this.timeout - diff) / 1000) % 60) : 0;
},
/**
* Returns the amount of minutes remaining
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get minutesLeft() {
var diff = this.diff;
return diff < this.timeout ? floor(((this.timeout - diff) / 60000) % 60) : 0;
},
/**
* Returns the amount of hours remaining
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get hoursLeft() {
var diff = this.diff;
return diff < this.timeout ? floor(((this.timeout - diff) / 3600000) % 24) : 0;
},
/**
* Returns the amount of days remaining
* @author Art <a.molcanovas@gmail.com>
* @returns {number}
*/
get daysLeft() {
var diff = this.diff;
return diff < this.timeout ? floor((this.timeout - diff) / 86400000) : 0;
},
/**
* Returns a string representation of the amount of time remaining
* @author Art <a.molcanovas@gmail.com>
* @returns {string}
*/
toString: function () {
var arr = [], tmp, i;
for (i = 0; i < this.timeChain.length; i++) {
tmp = this[this.timeChain[i] + "Left"];
arr.push(padLeft(this[this.timeChain[i] + "Left"].toString(), "0", this.timeChain[i] === "ms" ? 3 : 2));
}
return arr.join(":");
}
};
return AloTimer;
})(['days', 'hours', 'minutes', 'seconds'], Math.floor, Date, Error);
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
module.exports = AloTimer;
}