todos-contra-el-fuego-web/imports/ui/components/Chronos/Chronos.js

122 lines
3.2 KiB
JavaScript

// Adapted from: https://github.com/remcoder/chronos (MIT License)
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { ReactiveVar } from 'meteor/reactive-var';
import moment from 'moment';
const _timers = {};
function Timer(interval) {
this.interval = interval || 1000;
this.time = new ReactiveVar(0);
}
Timer.prototype.start = function () {
if (this._timer) throw new Error('Trying to start Chronos.Timer but it is already running.');
this.time.set(new Date());
this._timer = setInterval(Meteor.bindEnvironment(() => {
// console.log('tick', this._timer);
this.time.set(new Date());
}), this.interval);
};
Timer.prototype.stop = function () {
// console.log('stopping timer');
clearInterval(this._timer);
this._timer = null;
};
function _update(interval) {
// get current reactive context
const comp = Tracker.currentComputation;
if (!comp) { return; } // no nothing when used outside a reactive context
// only create one timer per reactive context to prevent stacking of timers
const cid = comp && comp._id;
if (!_timers[cid]) {
const timer = new Timer(interval);
_timers[cid] = timer;
// add destroy method that stops the timer and removes itself from the list
timer.destroy = function () {
timer.stop();
delete _timers[cid];
};
timer.start();
}
// make sure to stop and delete the attached timer when the computation is stopped
comp.onInvalidate(() => {
// console.log('onInvalidated',comp);
if (comp.stopped && _timers[cid]) {
// console.log('computation stopped');
_timers[cid].destroy();
}
});
_timers[cid].time.dep.depend(comp); // make dependent on time
// console.log(_timers);
return _timers[cid];
}
// reactive version of moment()
// please install moment separately
// example usage: Chronos.moment(someTimestamp).format('ss');
function _moment(/* arguments */) {
if (!moment) throw new Error('moment not found. Please install it first');
_update();
return moment(...arguments);
}
// reactive version of new Date() get the current date/time
function _date(interval) {
_update(interval);
return new Date();
}
// reactive version of Date.now(). get the current # of milliseconds since the start of the epoch
function _now(interval) {
_update(interval);
return Date.now();
}
// export global
const Chronos = {
// a simple reactive timer
// usage: var timer = new Timer();
// get current time: timer.time.get();
Timer,
// handy util func for making reactive contexts live updating in time
// usage: simply call Chronos.update() in your helper to make it execute
// every interval
update: _update,
// reactive version of new Date() get the current date/time
date: _date,
// reactive version of Date.now(). get the current # of milliseconds since the start of the epoch
now: _now,
// reactive version of moment()
// please install moment separately
// example usage: Chronos.moment(someTimestamp).format('ss');
moment: _moment,
// for debugging and testing
_timers,
// deprecated. but kept for backwards compatibility
liveUpdate: _update,
currentTime: _date,
liveMoment: _moment
};
export default Chronos;