UNPKG

easytimer.js

Version:

Timer/Chronometer/Countdown compatible with AMD and NodeJS

600 lines (571 loc) 19.9 kB
/** * easytimer.js * Generated: 2023-08-28 * Version: 4.6.0 */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.easytimer = {})); })(this, (function (exports) { 'use strict'; function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } function leftPadding(string, padLength, character) { var i; var characters = ''; string = typeof string === 'number' ? String(string) : string; if (string.length > padLength) { return string; } for (i = 0; i < padLength; i = i + 1) { characters += String(character); } return (characters + string).slice(-characters.length); } function TimeCounter() { this.reset(); } /** * [toString convert the counted values on a string] * @param {array} units [array with the units to display] * @param {string} separator [separator of the units] * @param {number} leftZeroPadding [number of zero padding] * @return {string} [result string] */ TimeCounter.prototype.toString = function () { var units = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['hours', 'minutes', 'seconds']; var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ':'; var leftZeroPadding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 2; units = units || ['hours', 'minutes', 'seconds']; separator = separator || ':'; leftZeroPadding = leftZeroPadding || 2; var arrayTime = []; var i; for (i = 0; i < units.length; i = i + 1) { if (this[units[i]] !== undefined) { if (units[i] === 'secondTenths') { arrayTime.push(this[units[i]]); } else { arrayTime.push(leftPadding(this[units[i]], leftZeroPadding, '0')); } } } return arrayTime.join(separator); }; /** * [reset reset counter] */ TimeCounter.prototype.reset = function () { this.secondTenths = 0; this.seconds = 0; this.minutes = 0; this.hours = 0; this.days = 0; }; function EventEmitter() { this.events = {}; } EventEmitter.prototype.on = function (event, listener) { var _this = this; if (!Array.isArray(this.events[event])) { this.events[event] = []; } this.events[event].push(listener); return function () { return _this.removeListener(event, listener); }; }; EventEmitter.prototype.removeListener = function (event, listener) { if (Array.isArray(this.events[event])) { var eventIndex = this.events[event].indexOf(listener); if (eventIndex > -1) { this.events[event].splice(eventIndex, 1); } } }; EventEmitter.prototype.removeAllListeners = function (event) { if (!event) { this.events = {}; } else if (Array.isArray(this.events[event])) { this.events[event] = []; } }; EventEmitter.prototype.emit = function (event) { var _this2 = this; for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } if (Array.isArray(this.events[event])) { this.events[event].forEach(function (listener) { return listener.apply(_this2, args); }); } }; /* * General functions, variables and constants */ var SECOND_TENTHS_PER_SECOND = 10; var SECONDS_PER_MINUTE = 60; var MINUTES_PER_HOUR = 60; var HOURS_PER_DAY = 24; var SECOND_TENTHS_POSITION = 0; var SECONDS_POSITION = 1; var MINUTES_POSITION = 2; var HOURS_POSITION = 3; var DAYS_POSITION = 4; var SECOND_TENTHS = 'secondTenths'; var SECONDS = 'seconds'; var MINUTES = 'minutes'; var HOURS = 'hours'; var DAYS = 'days'; var VALID_INPUT_VALUES = [SECOND_TENTHS, SECONDS, MINUTES, HOURS, DAYS]; var unitsInMilliseconds = { secondTenths: 100, seconds: 1000, minutes: 60000, hours: 3600000, days: 86400000 }; var groupedUnits = { secondTenths: SECOND_TENTHS_PER_SECOND, seconds: SECONDS_PER_MINUTE, minutes: MINUTES_PER_HOUR, hours: HOURS_PER_DAY }; function mod(number, module) { return (number % module + module) % module; } /** * [Timer Timer/Chronometer/Countdown compatible with AMD and NodeJS. * Can update time values with different time intervals: tenth of seconds, * seconds, minutes and hours.] */ function Timer() { var defaultParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; /* * PRIVATE variables and Functions */ var counters = new TimeCounter(); var totalCounters = new TimeCounter(); var intervalId; var eventEmitter = new EventEmitter(); var running = false; var paused = false; var precision; var timerTypeFactor; var customCallback; var timerConfig = {}; var currentParams; var targetValues; var startValues; var countdown; var startingDate; var targetDate; var eventData = { detail: { timer: this } }; setParams(defaultParams); function updateCounters(precision, roundedValue) { var unitsPerGroup = groupedUnits[precision]; totalCounters[precision] = roundedValue; if (precision === DAYS) { counters[precision] = Math.abs(roundedValue); } else if (roundedValue >= 0) { counters[precision] = mod(roundedValue, unitsPerGroup); } else { counters[precision] = mod(unitsPerGroup - mod(roundedValue, unitsPerGroup), unitsPerGroup); } } function updateDays(value) { return updateUnitByPrecision(value, DAYS); } function updateHours(value) { return updateUnitByPrecision(value, HOURS); } function updateMinutes(value) { return updateUnitByPrecision(value, MINUTES); } function updateSeconds(value) { return updateUnitByPrecision(value, SECONDS); } function updateSecondTenths(value) { return updateUnitByPrecision(value, SECOND_TENTHS); } function updateUnitByPrecision(value, precision) { var previousValue = totalCounters[precision]; updateCounters(precision, calculateIntegerUnitQuotient(value, unitsInMilliseconds[precision])); return totalCounters[precision] !== previousValue; } function stopTimerAndResetCounters() { stopTimer(); resetCounters(); } function stopTimer() { clearInterval(intervalId); intervalId = undefined; running = false; paused = false; } function setParamsAndStartTimer(params) { if (!isPaused()) { setParams(params); } else { startingDate = calculateStartingDate(); targetValues = setTarget(currentParams.target); } startTimer(); } function startTimer() { var interval = unitsInMilliseconds[precision]; if (isTargetAchieved(roundTimestamp(Date.now()))) { return; } intervalId = setInterval(updateTimerAndDispatchEvents, interval); running = true; paused = false; } function calculateStartingDate() { return roundTimestamp(Date.now()) - totalCounters.secondTenths * unitsInMilliseconds[SECOND_TENTHS] * timerTypeFactor; } function updateTimerAndDispatchEvents() { var currentTime = roundTimestamp(Date.now()); var valuesUpdated = updateTimer(); dispatchEvents(valuesUpdated); customCallback(eventData.detail.timer); if (isTargetAchieved(currentTime)) { stop(); dispatchEvent('targetAchieved', eventData); } } function updateTimer() { var currentTime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : roundTimestamp(Date.now()); var elapsedTime = timerTypeFactor > 0 ? currentTime - startingDate : startingDate - currentTime; var valuesUpdated = {}; valuesUpdated[SECOND_TENTHS] = updateSecondTenths(elapsedTime); valuesUpdated[SECONDS] = updateSeconds(elapsedTime); valuesUpdated[MINUTES] = updateMinutes(elapsedTime); valuesUpdated[HOURS] = updateHours(elapsedTime); valuesUpdated[DAYS] = updateDays(elapsedTime); return valuesUpdated; } function roundTimestamp(timestamp) { return Math.floor(timestamp / unitsInMilliseconds[precision]) * unitsInMilliseconds[precision]; } function dispatchEvents(valuesUpdated) { if (valuesUpdated[SECOND_TENTHS]) { dispatchEvent('secondTenthsUpdated', eventData); } if (valuesUpdated[SECONDS]) { dispatchEvent('secondsUpdated', eventData); } if (valuesUpdated[MINUTES]) { dispatchEvent('minutesUpdated', eventData); } if (valuesUpdated[HOURS]) { dispatchEvent('hoursUpdated', eventData); } if (valuesUpdated[DAYS]) { dispatchEvent('daysUpdated', eventData); } } function isTargetAchieved(currentDate) { return targetValues instanceof Array && currentDate >= targetDate; } function resetCounters() { counters.reset(); totalCounters.reset(); } function setParams(params) { params = params || {}; precision = checkPrecision(params.precision); customCallback = typeof params.callback === 'function' ? params.callback : function () {}; countdown = params.countdown === true; timerTypeFactor = countdown === true ? -1 : 1; if (_typeof(params.startValues) === 'object') { setStartValues(params.startValues); } else { startValues = null; } startingDate = calculateStartingDate(); updateTimer(); if (_typeof(params.target) === 'object') { targetValues = setTarget(params.target); } else if (countdown) { params.target = { seconds: 0 }; targetValues = setTarget(params.target); } else { targetValues = null; } timerConfig = { precision: precision, callback: customCallback, countdown: _typeof(params) === 'object' && params.countdown === true, target: targetValues, startValues: startValues }; currentParams = params; } function checkPrecision(precision) { precision = typeof precision === 'string' ? precision : SECONDS; if (!isValidInputValue(precision)) { throw new Error("Error in precision parameter: ".concat(precision, " is not a valid value")); } return precision; } function isValidInputValue(value) { return VALID_INPUT_VALUES.indexOf(value) >= 0; } function configInputValues(inputValues) { var values; if (_typeof(inputValues) === 'object') { if (inputValues instanceof Array) { if (inputValues.length !== 5) { throw new Error('Array size not valid'); } values = inputValues; } else { for (var value in inputValues) { if (VALID_INPUT_VALUES.indexOf(value) < 0) { throw new Error("Error in startValues or target parameter: ".concat(value, " is not a valid input value")); } } values = [inputValues.secondTenths || 0, inputValues.seconds || 0, inputValues.minutes || 0, inputValues.hours || 0, inputValues.days || 0]; } } values = values.map(function (value) { return parseInt(value, 10); }); var secondTenths = values[SECOND_TENTHS_POSITION]; var seconds = values[SECONDS_POSITION] + calculateIntegerUnitQuotient(secondTenths, SECOND_TENTHS_PER_SECOND); var minutes = values[MINUTES_POSITION] + calculateIntegerUnitQuotient(seconds, SECONDS_PER_MINUTE); var hours = values[HOURS_POSITION] + calculateIntegerUnitQuotient(minutes, MINUTES_PER_HOUR); var days = values[DAYS_POSITION] + calculateIntegerUnitQuotient(hours, HOURS_PER_DAY); values[SECOND_TENTHS_POSITION] = secondTenths % SECOND_TENTHS_PER_SECOND; values[SECONDS_POSITION] = seconds % SECONDS_PER_MINUTE; values[MINUTES_POSITION] = minutes % MINUTES_PER_HOUR; values[HOURS_POSITION] = hours % HOURS_PER_DAY; values[DAYS_POSITION] = days; return values; } function calculateIntegerUnitQuotient(unit, divisor) { var quotient = unit / divisor; return quotient < 0 ? Math.ceil(quotient) : Math.floor(quotient); } function setTarget(inputTarget) { if (!inputTarget) { return; } targetValues = configInputValues(inputTarget); var targetCounter = calculateTotalCounterFromValues(targetValues); targetDate = startingDate + targetCounter.secondTenths * unitsInMilliseconds[SECOND_TENTHS] * timerTypeFactor; return targetValues; } function setStartValues(inputStartValues) { startValues = configInputValues(inputStartValues); counters.secondTenths = startValues[SECOND_TENTHS_POSITION]; counters.seconds = startValues[SECONDS_POSITION]; counters.minutes = startValues[MINUTES_POSITION]; counters.hours = startValues[HOURS_POSITION]; counters.days = startValues[DAYS_POSITION]; totalCounters = calculateTotalCounterFromValues(startValues, totalCounters); } function calculateTotalCounterFromValues(values, outputCounter) { var total = outputCounter || {}; total.days = values[DAYS_POSITION]; total.hours = total.days * HOURS_PER_DAY + values[HOURS_POSITION]; total.minutes = total.hours * MINUTES_PER_HOUR + values[MINUTES_POSITION]; total.seconds = total.minutes * SECONDS_PER_MINUTE + values[SECONDS_POSITION]; total.secondTenths = total.seconds * SECOND_TENTHS_PER_SECOND + values[[SECOND_TENTHS_POSITION]]; return total; } /* * PUBLIC functions */ /** * [stop stops the timer and resets the counters. Dispatch stopped event] */ function stop() { stopTimerAndResetCounters(); dispatchEvent('stopped', eventData); } /** * [stop stops and starts the timer. Dispatch stopped event] */ function reset() { stopTimerAndResetCounters(); setParamsAndStartTimer(currentParams); dispatchEvent('reset', eventData); } /** * [start starts the timer configured by the params object. Dispatch started event] * @param {object} params [Configuration parameters] */ function start() { var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; params = _objectSpread2(_objectSpread2({}, defaultParams), params); if (isRunning()) { return; } setParamsAndStartTimer(params); dispatchEvent('started', eventData); } /** * [pause stops the timer without resetting the counters. The timer it can be restarted with start function. * Dispatch paused event] * @return {type} [description] */ function pause() { stopTimer(); paused = true; dispatchEvent('paused', eventData); } /** * [addEventListener Adds event listener to the timer] * @param {string} eventType [event to listen] * @param {function} listener [the event listener function] */ function addEventListener(eventType, listener) { eventEmitter.on(eventType, listener); } /** * [removeEventListener Removes event listener to the timer] * @param {string} eventType [event to remove listener] * @param {function} listener [listener to remove] */ function removeEventListener(eventType, listener) { eventEmitter.removeListener(eventType, listener); } /** * [removeAllEventListeners Removes all events listeners for the given type, no type to remove all types] * @param {string} [eventType] [event to remove listener] */ function removeAllEventListeners(eventType) { eventEmitter.removeAllListeners(eventType); } /** * [dispatchEvent dispatches an event] * @param {string} eventType [event to dispatch] * @param data */ function dispatchEvent(eventType, data) { eventEmitter.emit(eventType, data); } /** * [isRunning return true if the timer is running] * @return {Boolean} */ function isRunning() { return running; } /** * [isPaused returns true if the timer is paused] * @return {Boolean} */ function isPaused() { return paused; } /** * [getTimeValues returns the counter with the current timer values] * @return {TimeCounter} */ function getTimeValues() { return counters; } /** * [getTotalTimeValues returns the counter with the current timer total values] * @return {TimeCounter} */ function getTotalTimeValues() { return totalCounters; } /** * [getConfig returns the configuration parameters] * @return {type} */ function getConfig() { return timerConfig; } /** * Public API * Definition of Timer instance public functions */ if (typeof this !== 'undefined') { this.start = start; this.pause = pause; this.stop = stop; this.reset = reset; this.isRunning = isRunning; this.isPaused = isPaused; this.getTimeValues = getTimeValues; this.getTotalTimeValues = getTotalTimeValues; this.getConfig = getConfig; this.addEventListener = addEventListener; this.on = addEventListener; this.removeEventListener = removeEventListener; this.removeAllEventListeners = removeAllEventListeners; this.off = removeEventListener; } } exports.Timer = Timer; exports.default = Timer; Object.defineProperty(exports, '__esModule', { value: true }); }));