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