Last active
January 2, 2016 09:59
-
-
Save juandopazo/8287117 to your computer and use it in GitHub Desktop.
ES5-based Y.Model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function assign(dest, source) { | |
for (var prop in source) { | |
if (source.hasOwnProperty(prop)) { | |
dest[prop] = source[prop]; | |
} | |
} | |
return dest; | |
} | |
function createStateClass(superclass, props) { | |
var prop, record; | |
function StateClass() { | |
} | |
StateClass.COMPUTABLE = {}; | |
if (superclass) { | |
StateClass.prototype = Object.create(superclass.prototype, { | |
constructor: { | |
value: StateClass | |
} | |
}); | |
assign(StateClass.COMPUTABLE, superclass.COMPUTABLE); | |
} | |
if (props) { | |
for (prop in props) { | |
if (props.hasOwnProperty(prop)) { | |
record = props[prop]; | |
if (!record.hasOwnProperty('writable')) { | |
record.writable = true; | |
} | |
if (!record.hasOwnProperty('configurable')) { | |
record.configurable = true; | |
} | |
if (!record.hasOwnProperty('enumerable')) { | |
record.configurable = true; | |
} | |
if (record.hasOwnProperty('set') || | |
record.hasOwnProperty('get')) { | |
StateClass.COMPUTABLE[prop] = true; | |
} | |
Object.defineProperty(StateClass.prototype, prop, record); | |
} | |
} | |
Object.defineProperties(StateClass.prototype, props); | |
} | |
return StateClass; | |
} | |
function Model(config) { | |
var prop, | |
state = new this.constructor.__STATE__(); | |
this._state = state; | |
this._changes = null; | |
this._callbacks = []; | |
if (config) { | |
for (prop in config) { | |
if (prop in state) { | |
state[prop] = config[prop]; | |
} | |
} | |
} | |
this._observe(); | |
} | |
assign(Model.prototype, { | |
_observe: function () { | |
var self = this; | |
Object.observe(this._state, function (changes) { | |
self._notify(changes); | |
}); | |
}, | |
_notify: function (changes) { | |
var callbacks = this._callbacks; | |
this._callbacks = []; | |
for (var i = 0, length = callbacks.length; i < length; i++) { | |
callbacks[i](changes); | |
} | |
}, | |
set: function (propName, value) { | |
if (propName in this._state) { | |
this._state[propName] = value; | |
} | |
return this; | |
}, | |
get: function (propName) { | |
if (propName in this._state) { | |
return this._state[propName]; | |
} | |
}, | |
onChanged: function (callback) { | |
this._callbacks.push(callback); | |
return this; | |
}, | |
toJSON: function () { | |
var result = {}, | |
prop; | |
for (prop in this._state) { | |
result[prop] = this._state[prop]; | |
} | |
return result; | |
} | |
}); | |
Model.extend = function extend(proto, attrs) { | |
var superclass = this, | |
prop, | |
subclass = (proto && proto.hasOwnProperty('constructor')) ? | |
proto.constructor : function BuiltModel(config) { | |
superclass.call(this, config); | |
}; | |
subclass.prototype = Object.create(superclass.prototype, { | |
constructor: { | |
value: subclass | |
} | |
}); | |
subclass.extend = extend; | |
if (proto) { | |
assign(subclass.prototype, proto); | |
} | |
if (attrs) { | |
assign(subclass, attrs); | |
} | |
subclass.__STATE__ = createStateClass(superclass.__STATE__, attrs && attrs.PROPS); | |
return subclass; | |
}; | |
Model.__STATE__ = createStateClass(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Model = Y.Model, | |
asap = Y.asap; | |
Model.prototype._observe = function () { | |
this._changes = []; | |
this._observing = false; | |
}; | |
Model.prototype._scheduleChange = function () { | |
var self = this; | |
self._observing = true; | |
asap(function () { | |
var changes = self._changes; | |
self._observing = false; | |
self._changes = []; | |
self._notify(changes); | |
}); | |
}; | |
Model.prototype.set = function (propName, value) { | |
var state = this._state, | |
oldValue, | |
added = false, | |
record = {}; | |
if (!(propName in state)) { | |
added = true; | |
} | |
oldValue = state[propName]; | |
state[propName] = value; | |
if (!(oldValue === value || this.constructor.__STATE__.COMPUTABLE[propName])) { | |
record = { | |
name: propName, | |
object: this | |
}; | |
if (added) { | |
record.type = 'add'; | |
} else { | |
record.oldValue = oldValue; | |
record.type = 'update'; | |
} | |
this._changes.push(record); | |
if (!this._observing) { | |
this._scheduleChange(); | |
} | |
} | |
return this; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment