;(function(exports) {
var slice = Array.prototype.slice;
var splice = Array.prototype.splice;
var eventSplitter = /\s+/;
var Events = {
on : function(events, callback, context) {
var calls, event, node, tail, list;
if(!callback)
return this;
events = events.split(eventSplitter);
calls = this._callbacks || (this._callbacks = {});
while( event = events.shift()) {
list = calls[event];
node = list ? list.tail : {};
node.next = tail = {};
node.context = context;
node.callback = callback;
calls[event] = {
tail : tail,
next : list ? list.next : node
};
}
return this;
},
off : function(events, callback, context) {
var event, calls, node, tail, cb, ctx;
if(!( calls = this._callbacks))
return;
if(!(events || callback || context)) {
delete this._callbacks;
return this;
}
events = events ? events.split(eventSplitter) : _.keys(calls);
while( event = events.shift()) {
node = calls[event];
delete calls[event];
if(!node || !(callback || context))
continue;
tail = node.tail;
while(( node = node.next) !== tail) {
cb = node.callback;
ctx = node.context;
if((callback && cb !== callback) || (context && ctx !== context)) {
this.on(event, cb, ctx);
}
}
}
return this;
},
trigger : function(events) {
var event, node, calls, tail, args, all, rest;
if(!( calls = this._callbacks))
return this;
all = calls.all;
events = events.split(eventSplitter);
rest = slice.call(arguments, 1);
while( event = events.shift()) {
if( node = calls[event]) {
tail = node.tail;
while(( node = node.next) !== tail) {
node.callback.apply(node.context || this, rest);
}
}
if( node = all) {
tail = node.tail;
args = [event].concat(rest);
// 遍历并执行"all"事件中的回调函数列表
while(( node = node.next) !== tail) {
node.callback.apply(node.context || this, args);
}
}
}
return this;
}
};
Events.bind = Events.on;
Events.unbind = Events.off;
var viewOptions = ['model','el', 'id', 'attributes', 'name']; //拣选录入this的属性
var View = function(options){
this.cid = _.uniqueId('view');
this._configure(options || {});
this.initialize.apply(this, arguments); //调子类方法
}
_.extend(View.prototype, Events, {
_configure : function(options) {
if(this.options)
options = _.extend({}, this.options, options);
for(var i = 0, l = viewOptions.length; i < l; i++) {
var attr = viewOptions[i];
if(options[attr])
this[attr] = options[attr];
}
this.options = options;
},
// initialization logic.
initialize : function() {
},
render : function() {
return this;
},
remove : function() {
this.el.remove();
return this;
},
getElement : function(privateElKey) {
if(!privateElKey){
return this.el;
}
return this[privateElKey];
},
hideBar : function(elementsKey, show) {
var i=0, len=elementsKey.length;
if(show){
for(i=0; i<len; i++){
this[elementsKey[i]].show();
}
}else{
for(i=0; i<len; i++){
this[elementsKey[i]].hide();
}
}
}
});
var Model = function(attributes, options){
// defaults变量用于存储模型的默认数据
var defaults;
// 如果没有指定attributes参数, 则设置attributes为空对象
attributes || ( attributes = {});
if(options && options.parse)
attributes = this.parse(attributes);
if( defaults = getValue(this, 'defaults')) {
// 如果Model在定义时设置了defaults默认数据, 则初始化数据使用defaults与attributes参数合并后的数据(attributes中的数据会覆盖defaults中的同名数据)
attributes = _.extend({}, defaults, attributes);
}
// attributes属性存储了当前模型的JSON对象化数据, 创建模型时默认为空
this.attributes = {};
// 定义_escapedAttributes缓存对象, 它将缓存通过escape方法处理过的数据
this._escapedAttributes = {};
// 为每一个模型配置一个唯一标识
this.cid = _.uniqueId('c');
this.changed = {};
this._silent = {};
this._pending = {};
//
this.set(attributes, {
silent : true
});
// Reset change tracking.
this.changed = {};
this._silent = {};
this._pending = {};
this._previousAttributes = _.clone(this.attributes);
this.initialize.apply(this, arguments);
}
_.extend(Model.prototype, Events, {
idAttribute : 'id',
initialize : function() {
},
// 根据attr属性名, 获取模型中的数据值
get : function(attr) {
return this.attributes[attr];
},
// 设置模型中的数据, 如果key值不存在, 则作为新的属性添加到模型, 如果key值已经存在, 则修改为新的值
set : function(key, value, options) {
// attrs变量中记录需要设置的数据对象
var attrs, attr, val;
// 参数形式允许key-value对象形式, 或通过key, value两个参数进行单独设置
// 如果key是一个对象, 则认定为使用对象形式设置, 第二个参数将被视为options参数
if(_.isObject(key) || key == null) {
attrs = key;
options = value;
} else {
// 通过key, value两个参数单独设置, 将数据放到attrs对象中方便统一处理
attrs = {};
attrs[key] = value;
}
// options配置项必须是一个对象, 如果没有设置options则默认值为一个空对象
options || ( options = {});
// 没有设置参数时不执行任何动作
if(!attrs)
return this;
// Check for changes of `id`.
if(this.idAttribute in attrs)
this.id = attrs[this.idAttribute];
var changes = options.changes = {};
// now记录当前模型中的数据对象
var now = this.attributes;
// escaped记录当前模型中通过escape缓存过的数据
var escaped = this._escapedAttributes;
var prev = this._previousAttributes || {};
// For each `set` attribute...
// 遍历需要设置的数据对象
for(attr in attrs) {
// attr存储当前属性名称, val存储当前属性的值
val = attrs[attr];
// 如果当前数据在模型中不存在, 或已经发生变化, 或在options中指定了unset属性删除, 则删除该数据被换存在_escapedAttributes中的数据
// 以下代码仅删除通过escape缓存过的数据, 这是为了保证缓存中的数据与模型中的真实数据保持同步
if(!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) {
delete escaped[attr];
(options.silent ? this._silent : changes)[attr] = true;
}
// 如果在options中设置了unset, 则从模型中删除该数据(包括key)
// 如果没有指定unset属性, 则认为将新增或修改数据, 向模型的数据对象中加入新的数据
options.unset ?
delete now[attr] : now[attr] = val;
if(!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
this.changed[attr] = val;
if(!options.silent)
this._pending[attr] = true;
} else {
delete this.changed[attr];
delete this._pending[attr];
}
}
if(!options.silent)
this.change(options);
return this;
},
unset : function(attr, options) {
(options || ( options = {})).unset = true;
return this.set(attr, null, options);
},
change : function(options) {
options || ( options = {});
var changing = this._changing;
this._changing = true;
// Silent changes become pending changes.
for(var attr in this._silent)
this._pending[attr] = true;
// Silent changes are triggered.
var changes = _.extend({}, options.changes, this._silent);
this._silent = {};
for(var attr in changes) {
this.trigger('change:' + attr, this, this.get(attr), options);
}
if(changing)
return this;
// Continue firing `"change"` events while there are pending changes.
while(!_.isEmpty(this._pending)) {
this._pending = {};
this.trigger('change', this, options);
// Pending and silent changes still remain.
for(var attr in this.changed) {
if(this._pending[attr] || this._silent[attr])
continue;
delete this.changed[attr];
}
this._previousAttributes = _.clone(this.attributes);
}
this._changing = false;
return this;
}
});
// ctor是一个共享的空函数, 用于在调用inherits方法实现继承时, 承载父类的原型链以便设置到子类原型中
var ctor = function() {
};
var inherits = function(parent, protoProps, staticProps) {
var child;
if(protoProps && protoProps.hasOwnProperty('constructor')) {
child = protoProps.constructor;
} else {
child = function() {
parent.apply(this, arguments);
};
}
_.extend(child, parent);
ctor.prototype = parent.prototype;
child.prototype = new ctor();
if(protoProps)
_.extend(child.prototype, protoProps);
if(staticProps)
_.extend(child, staticProps);
child.prototype.constructor = child;
child.__super__ = parent.prototype;
return child;
};
// The self-propagating extend function that Backbone classes use.
// 实现对象继承的函数, 该函数内部使用inherits实现继承, 请参考inherits函数
var extend = function(protoProps, classProps) {
var child = inherits(this, protoProps, classProps);
child.extend = this.extend;
return child;
};
// 获取对象prop属性的值, 如果prop属性是一个函数, 则执行并返回该函数的返回值
var getValue = function(object, prop) {
// 如果object为空或object不存在prop属性, 则返回null
if(!(object && object[prop]))
return null;
// 返回prop属性值, 如果prop是一个函数, 则执行并返回该函数的返回值
return _.isFunction(object[prop]) ? object[prop]() : object[prop];
};
// Set up inheritance for the model, collection, and view.
// 为Model, Collection, Router和View类实现继承机制
Model.extend = View.extend = extend;
exports.View = View;
exports.Model = Model;
})(PackTools);