Skip to content

Instantly share code, notes, and snippets.

@thejefflarson
Created October 13, 2011 17:55
Show Gist options
  • Save thejefflarson/1284940 to your computer and use it in GitHub Desktop.
Save thejefflarson/1284940 to your computer and use it in GitHub Desktop.
// The primary function of a **Model** is to manipulate and query data. For example filtering
// an array-type object should happen in a subclass of Model. Another great candidate
// for a **Model** is any object that requires an external resource such as an ajax call.
//
// Basically, any long running or long blocking operation should happen in a model.
//
// **Models** are bindable as well, so you can subscribe to notifications by calling
// `bind` with a callback and an event to subscribe to recieve events from another object.
//
// **Models** are usually encapsulated in **Views** and rarely, if ever, stand alone.
//
propublica.Model = Base.extend({
// The **init** method copies the passed in attributes to the instance's built in
// **_attrs** object.
MODEL_CHANGED : "changed",
init : function(attrs){
this._attrs = this._attrs || {};
_.extend(this._attrs, attrs);
if('id' in this._attrs) this.id = attrs.id;
this.cid = _.uniqueId(this.name || this.id || "");
},
// Access an attribute by key.
read : function(key){
return this._attrs[key];
},
// Set an attribute by key. Pass in an object for key to assign multiple values.
write : function(key, attr){
attrs = {};
!_.isUndefined(attr) ? attrs[key] = attr : attrs = _.extend(attrs, key);
for(var k in attrs){
var value = attrs[k];
var old = this._attrs[k];
if('id' in attrs) this.id = attrs.id;
if (!_.isEqual(old, value)) {
this._attrs[k] = value;
this._onchange(k, old, value);
}
}
return this;
},
// delete an attribute by key.
remove : function(key){
var oldAttr = this._attrs[key];
delete this._attrs[key];
this._onchange(key, oldAttr, undefined);
return oldAttr;
},
_onchange : function(key, old, value){
this.fire(this.MODEL_CHANGED, this, key, old, value);
this.fire(this.keyPath(key), this, key, old, value);
},
keyPath : function(key){
return [key, this.MODEL_CHANGED].join("_");
},
bind : function(e, cb){
var callbacks = (this._callbacks = this._callbacks || {});
var list = (callbacks[e] = callbacks[e] || []);
list.push(cb);
},
unbind : function(e, cb){
if(!(this._callbacks && this._callbacks[e])) return;
var list = this._callbacks[e];
for(var i = 0; i < list.length; i++){
if(list[i] === cb) {
list.splice(i, 1);
break;
}
}
},
unbindAll : function(){
delete this._callbacks;
},
fire : function(e){
if(!this._callbacks) return;
var list = this._callbacks[e];
if(!list) return;
for(var i = 0; i < list.length; i++) list[i].apply(this, arguments);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment