Skip to content

Instantly share code, notes, and snippets.

@huafu
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huafu/d62cefaf0f8d412c8fe3 to your computer and use it in GitHub Desktop.
Save huafu/d62cefaf0f8d412c8fe3 to your computer and use it in GitHub Desktop.
A mixin to have a property updated each time a new `tickStep` `tickUnit` is passed
import Ember from 'ember';
var DAYS_IN_YEAR = 365.25;
var DAYS_IN_MONTH = DAYS_IN_YEAR / 12;
var MILLISECONDS_IN = {
millisecond: 1,
second: 1000,
minute: 1000 * 60,
hour: 1000 * 60 * 60,
day: 1000 * 60 * 60 * 24,
week: 1000 * 60 * 60 * 24 * 7,
month: 1000 * 60 * 60 * 24 * DAYS_IN_MONTH,
year: 1000 * 60 * 60 * 24 * DAYS_IN_YEAR
};
function parseUnit(unit) {
var res = (/s$/i.test(unit) ? unit.substr(0, -1) : unit).toLowerCase();
if (!MILLISECONDS_IN[res]) {
throw new ReferenceError('Invalid unit `' + unit + '`');
}
return res;
}
function toMilliseconds(value, unit) {
return value * MILLISECONDS_IN[parseUnit(unit)];
}
export default Ember.Mixin.create({
tickStep: 1,
tickUnit: Ember.required(),
tickProperty: Ember.required(),
_initWithClock: function () {
var meta = this._withClock = {
property: this.get('tickProperty'),
step: toMilliseconds(this.get('tickStep'), this.get('tickUnit')),
current: function () {
return Math.floor(Date.now() / this.step) * this.step;
},
check: function (obj) {
if (!obj || obj.isDestroying || obj.isDestroyed) {
this.cancel();
return;
}
var c = this.current();
if (this.last !== c) {
this.last = c;
Ember.run.next(this, function () {
obj.set(this.property, c);
this.schedule(obj);
});
}
else {
this.schedule(obj);
}
},
schedule: function (obj) {
var self = this;
this.cancel();
this._tiemr = setTimeout(function () {
self._timer = null;
self.check(obj);
}, this.step / 3);
},
cancel: function () {
if (this._timer) {
clearTimeout(this._timer);
this._timer = null;
}
}
};
meta.check(this);
}.on('init'),
_destroyWithClock: function () {
if (this._withClock) {
this._withClock.cancel();
delete this._withClock;
}
}.on('destroy')
});
import Ember from 'ember';
import WithClockMixin from 'app/mixins/with-clock';
export default Ember.Controller.extend(WithClockMixin, {
tickStep: 5,
tickUnit: 'minute',
tickProperty: 'time',
time: null,
currentDateUpdateEvery5Minutes: function () {
return new Date(this.get('time'));
}.property('time').readOnly()
});
/*
The `currentDateUpdateEvery5Minutes` property will be updated every 5 minutes,
to a number of milliseconds floored depending on the tickUnit and tickStep, so
here it'll be always a multiple of 5 minutes, so it can't be a time like '10:22',
it'll be instead here '10:20'.
It'll check for new value 3 times per step, updating only if it needs to be updated.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment