marbles
Version:
Front-end framework for routing, http, and data handling
124 lines (112 loc) • 3.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
/* @flow weak */
/**
* @memberof Marbles
* @mixin
* @desc Manages a state object. You must define `state` {Object} and `__changeListeners` {Array} on the object this is mixed into.
*/
var State = {
/**
* @method
* @param {function} handler Function to call when the state object changes
*/
addChangeListener: function addChangeListener(handler) {
this.__changeListeners.push(handler);
},
/**
* @method
* @param {function} handler
* @desc Prevents handler from being called for future changes
*/
removeChangeListener: function removeChangeListener(handler) {
this.__changeListeners = this.__changeListeners.filter(function (fn) {
return fn !== handler;
});
},
/**
* @method
* @param {function} changeFn
* @desc Calls `willChange`, the passed in function, `handleChange`, then `didChange`
*/
withChange: function withChange(changeFn) {
this.willChange();
changeFn.call(this);
this.handleChange();
this.didChange();
},
/**
* @method
* @param {Object} newState
* @desc Copies properties of newState to the existing state object
*/
setState: function setState(newState) {
this.withChange(function () {
var state = this.state;
Object.keys(newState).forEach(function (key) {
state[key] = newState[key];
});
});
},
/**
* @method
* @param {Object} newState
* @param {Number} maxTimeout
* @desc Same as setState, but waits up to 10ms for more changes to occur before calling change listeners
*/
setStateWithDelay: function setStateWithDelay(newState, maxTimeout) {
this.willChange();
var state = this.state;
Object.keys(newState).forEach(function (key) {
state[key] = newState[key];
});
this.handleChangeWithDelay(maxTimeout);
},
handleChangeWithDelay: function handleChangeWithDelay(maxTimeout) {
maxTimeout = maxTimeout || 10;
clearTimeout(this.__handleChangeTimeout);
this.__handleChangeTimeout = setTimeout((function () {
this.handleChangeDelayed();
}).bind(this), 2);
if (!this.__handleChangeMaxTimeout) {
this.__handleChangeMaxTimeout = setTimeout((function () {
this.handleChangeDelayed();
}).bind(this), maxTimeout);
}
},
handleChangeDelayed: function handleChangeDelayed() {
clearTimeout(this.__handleChangeMaxTimeout);
clearTimeout(this.__handleChangeTimeout);
this.handleChange();
this.didChange();
},
/**
* @method
* @param {Object} newState
* @desc Replaces the existing state object with newState
*/
replaceState: function replaceState(newState) {
this.withChange(function () {
this.state = newState;
});
},
handleChange: function handleChange() {
this.__changeListeners.forEach(function (handler) {
handler();
});
},
/**
* @method
* @desc Called before state object is mutated
*/
willChange: function willChange() {},
/**
* @method
* @desc Called after state object is mutated
*/
didChange: function didChange() {}
};
exports["default"] = State;
module.exports = exports["default"];