(function(){return function(factory){if(typeof exports=="object"){module.exports=module.exports=factory.call(this,require)}else if(typeof define=="function"&&define.amd){define(["require","underscore","backbone","knockout"],factory)}else{this.kb=factory.call(this,typeof require!=="undefined"?require:undefined)}}(function(require){var COMPARE_ASCENDING,COMPARE_DESCENDING,COMPARE_EQUAL,KB_TYPE_ARRAY,KB_TYPE_COLLECTION,KB_TYPE_MODEL,KB_TYPE_SIMPLE,KB_TYPE_UNKNOWN,ORM,ORMAdapter_BackboneAssociations,ORMAdapter_BackboneRelational,ORMAdapter_Supermodel,copyProps,kb,ko,onReady,_,_argumentsAddKey,_arraySplice,_collapseOptions,_i,_key,_keyArrayToObject,_ko_applyBindings,_legacyWarning,_len,_mergeArray,_mergeObject,_peekObservable,_publishMethods,_ref,_throwMissing,_throwUnexpected,_unwrapModels,_unwrapObservable,_wrappedKey,__bind=function(fn,me){return function(){return fn.apply(me,arguments)}},__indexOf=[].indexOf||function(item){for(var i=0,l=this.length;i=0){info.unbind_fn=kb.orm.bind(this.ee,info.key,info.update,info.path)}info.emitter(this.ee)&&info.emitter}};EventWatcher.prototype.releaseCallbacks=function(obj){var callbacks,event_name,index,info,_ref1,_ref2;if(!this.__kb.callbacks||!this.ee){return}_ref1=this.__kb.callbacks;for(event_name in _ref1){callbacks=_ref1[event_name];_ref2=callbacks.list;for(index in _ref2){info=_ref2[index];if(info.obj!==obj){continue}callbacks.list.splice(index,1);if(info.unbind_fn){info.unbind_fn();info.unbind_fn=null}if(!kb.wasReleased(obj)&&info.emitter){info.emitter(null)}return}}};EventWatcher.prototype._onModelLoaded=function(model){var callbacks,event_name,info,_j,_len1,_ref1,_ref2;this.ee=model;_ref1=this.__kb.callbacks;for(event_name in _ref1){callbacks=_ref1[event_name];model.bind(event_name,callbacks.fn);_ref2=callbacks.list;for(_j=0,_len1=_ref2.length;_j<_len1;_j++){info=_ref2[_j];info.unbind_fn=kb.orm.bind(model,info.key,info.update,info.path);if(info.emitter){info.emitter(model)}}}};EventWatcher.prototype._onModelUnloaded=function(model){var callbacks,event_name,info,list,_j,_len1,_ref1;this.ee=null;_ref1=this.__kb.callbacks;for(event_name in _ref1){callbacks=_ref1[event_name];model.unbind(event_name,callbacks.fn);list=callbacks.list;for(_j=0,_len1=list.length;_j<_len1;_j++){info=list[_j];if(info.unbind_fn){info.unbind_fn();info.unbind_fn=null}if(info.emitter){info.emitter(null)}}}};return EventWatcher}();kb.emitterObservable=function(emitter,observable){return new kb.EventWatcher(emitter,observable)};kb.Observable=function(){function Observable(model,options,_vm){var _this=this;this._vm=_vm!=null?_vm:{};return kb.ignore(function(){var create_options,event_watcher,observable;options||_throwMissing(_this,"options");if(_.isString(options)||ko.isObservable(options)){create_options=_this.create_options={key:options}}else{create_options=_this.create_options=_collapseOptions(options)}_this.key=create_options.key;delete create_options.key;_this.key||_throwMissing(_this,"key");!create_options.args||(_this.args=create_options.args,delete create_options.args);!create_options.read||(_this.read=create_options.read,delete create_options.read);!create_options.write||(_this.write=create_options.write,delete create_options.write);event_watcher=create_options.event_watcher;delete create_options.event_watcher;_this._vo=ko.observable(null);_this._model=ko.observable();observable=kb.utils.wrappedObservable(_this,ko.dependentObservable({read:function(){var arg,args,_j,_len1,_model,_ref1;_model=_this._model();_ref1=args=[_this.key].concat(_this.args||[]);for(_j=0,_len1=_ref1.length;_j<_len1;_j++){arg=_ref1[_j];_unwrapObservable(arg)}if(_this.read){_this.update(_this.read.apply(_this,args))}else if(!_.isUndefined(_model)){kb.ignore(function(){return _this.update(kb.getValue(_model,_peekObservable(_this.key),_this.args))})}return _unwrapObservable(_this._vo())},write:function(new_value){return kb.ignore(function(){var unwrapped_new_value,_model;unwrapped_new_value=_unwrapModels(new_value);_model=_peekObservable(_this._model);if(_this.write){_this.write.call(_this._vm,unwrapped_new_value);new_value=kb.getValue(_model,_peekObservable(_this.key),_this.args)}else if(_model){kb.setValue(_model,_peekObservable(_this.key),unwrapped_new_value)}return _this.update(new_value)})},owner:_this._vm}));observable.__kb_is_o=true;create_options.store=kb.utils.wrappedStore(observable,create_options.store);create_options.path=kb.utils.pathJoin(create_options.path,_this.key);if(create_options.factories&&(typeof create_options.factories==="function"||create_options.factories.create)){create_options.factory=kb.utils.wrappedFactory(observable,new kb.Factory(create_options.factory));create_options.factory.addPathMapping(create_options.path,create_options.factories)}else{create_options.factory=kb.Factory.useOptionsOrCreate(create_options,observable,create_options.path)}delete create_options.factories;_publishMethods(observable,_this,["value","valueType","destroy"]);observable.model=_this.model=ko.dependentObservable({read:function(){return _unwrapObservable(_this._model)},write:function(new_model){return kb.ignore(function(){var new_value;if(_this.__kb_released||_peekObservable(_this._model)===new_model){return}new_value=kb.getValue(new_model,_peekObservable(_this.key),_this.args);_this._model(new_model);if(!new_model){return _this.update(null)}else if(!_.isUndefined(new_value)){return _this.update(new_value)}})}});kb.EventWatcher.useOptionsOrCreate({event_watcher:event_watcher},model,_this,{emitter:_this.model,update:_.bind(_this.update,_this),key:_this.key,path:create_options.path});_this.__kb_value||_this.update();if(kb.LocalizedObservable&&create_options.localizer){observable=new create_options.localizer(observable);delete create_options.localizer}if(kb.DefaultObservable&&create_options.hasOwnProperty("default")){observable=kb.defaultObservable(observable,create_options["default"]);delete create_options["default"]}return observable})}Observable.prototype.destroy=function(){var observable;observable=kb.utils.wrappedObservable(this);this.__kb_released=true;kb.release(this.__kb_value);this.__kb_value=null;this.model.dispose();this.model=observable.model=null;return kb.utils.wrappedDestroy(this)};Observable.prototype.value=function(){return this.__kb_value};Observable.prototype.valueType=function(){var new_value;new_value=kb.getValue(_peekObservable(this._model),_peekObservable(this.key));this.value_type||this._updateValueObservable(new_value);return this.value_type};Observable.prototype.update=function(new_value){var new_type,value;if(this.__kb_released){return}if(!arguments.length){new_value=kb.getValue(_peekObservable(this._model),_peekObservable(this.key))}new_value!==void 0||(new_value=null);new_type=kb.utils.valueType(new_value);if(!this.__kb_value||(this.__kb_value.__kb_released||this.__kb_value.__kb_null&&new_value)){this.__kb_value=void 0;this.value_type=void 0}value=this.__kb_value;if(_.isUndefined(this.value_type)||this.value_type!==new_type&&new_type!==KB_TYPE_UNKNOWN){if(this.value_type===KB_TYPE_COLLECTION&&new_type===KB_TYPE_ARRAY){return value(new_value)}else{return this._updateValueObservable(new_value)}}else if(this.value_type===KB_TYPE_MODEL){if(typeof value.model==="function"){if(value.model()!==new_value){return value.model(new_value) }}else if(kb.utils.wrappedObject(value)!==new_value){return this._updateValueObservable(new_value)}}else if(this.value_type===KB_TYPE_COLLECTION){if(value.collection()!==new_value){return value.collection(new_value)}}else{if(value()!==new_value){return value(new_value)}}};Observable.prototype._updateValueObservable=function(new_value){var create_options,creator,previous_value,value;create_options=this.create_options;create_options.creator=kb.utils.inferCreator(new_value,create_options.factory,create_options.path,_peekObservable(this._model),this.key);this.value_type=KB_TYPE_UNKNOWN;creator=create_options.creator;previous_value=this.__kb_value;this.__kb_value=void 0;if(previous_value){kb.release(previous_value)}if(creator){if(create_options.store){value=create_options.store.findOrCreate(new_value,create_options)}else{if(creator.models_only){value=new_value;this.value_type=KB_TYPE_SIMPLE}else if(creator.create){value=creator.create(new_value,create_options)}else{value=new creator(new_value,create_options)}}}else{if(_.isArray(new_value)){this.value_type=KB_TYPE_ARRAY;value=ko.observableArray(new_value)}else{this.value_type=KB_TYPE_SIMPLE;value=ko.observable(new_value)}}if(this.value_type===KB_TYPE_UNKNOWN){if(!ko.isObservable(value)){this.value_type=KB_TYPE_MODEL;if(typeof value.model!=="function"){kb.utils.wrappedObject(value,new_value)}}else if(value.__kb_is_co){this.value_type=KB_TYPE_COLLECTION}else{this.value_type=KB_TYPE_SIMPLE}}this.__kb_value=value;return this._vo(value)};return Observable}();kb.observable=function(model,options,view_model){return new kb.Observable(model,options,view_model)};kb.ViewModel=function(){ViewModel.extend=kb.extend;function ViewModel(model,options,view_model){var _this=this;return kb.ignore(function(){var attribute_keys,bb_model,event_watcher,keys,mapped_keys,mapping_info,rel_keys,vm_key,_mdl,_ref1;!model||model instanceof kb.Model||typeof model.get==="function"&&typeof model.bind==="function"||_throwUnexpected(_this,"not a model");options||(options={});view_model||(view_model={});if(_.isArray(options)){options={keys:options}}else{options=_collapseOptions(options)}_this.__kb||(_this.__kb={});_this.__kb.vm_keys={};_this.__kb.model_keys={};_this.__kb.view_model=_.isUndefined(view_model)?_this:view_model;!options.internals||(_this.__kb.internals=options.internals);!options.excludes||(_this.__kb.excludes=options.excludes);!options.statics||(_this.__kb.statics=options.statics);!options.static_defaults||(_this.__kb.static_defaults=options.static_defaults);kb.Store.useOptionsOrCreate(options,model,_this);_this.__kb.path=options.path;kb.Factory.useOptionsOrCreate(options,_this,options.path);_mdl=_wrappedKey(_this,"_mdl",ko.observable());_this.model=ko.dependentObservable({read:function(){_mdl();return kb.utils.wrappedObject(_this)},write:function(new_model){return kb.ignore(function(){var event_watcher,keys,missing,rel_keys;if(kb.utils.wrappedObject(_this)===new_model){return}if(_this.__kb_null){!new_model||_throwUnexpected(_this,"model set on shared null");return}kb.utils.wrappedObject(_this,new_model);event_watcher=kb.utils.wrappedEventWatcher(_this);if(!event_watcher){_mdl(new_model);return}event_watcher.emitter(new_model);if(!(_this.__kb.keys||!new_model||!new_model.attributes)){keys=_.keys(new_model.attributes);if(new_model&&(rel_keys=kb.orm.keys(new_model))){keys=_.union(keys,rel_keys)}missing=_.difference(keys,_.keys(_this.__kb.model_keys));if(missing){_this._createObservables(new_model,missing)}}_mdl(new_model)})}});event_watcher=kb.utils.wrappedEventWatcher(_this,new kb.EventWatcher(model,_this,{emitter:_this.model}));keys=options.requires;if(_this.__kb.internals){keys=_.union(keys||[],_this.__kb.internals)}if(model&&(rel_keys=kb.orm.keys(model))){keys=_.union(keys||[],rel_keys)}if(options.keys){if(_.isObject(options.keys)&&!_.isArray(options.keys)){mapped_keys={};_ref1=options.keys;for(vm_key in _ref1){mapping_info=_ref1[vm_key];mapped_keys[_.isString(mapping_info)?mapping_info:mapping_info.key?mapping_info.key:vm_key]=true}_this.__kb.keys=_.keys(mapped_keys)}else{_this.__kb.keys=options.keys;keys=keys?_.union(keys,_this.__kb.keys):_.clone(_this.__kb.keys)}}else{bb_model=event_watcher.emitter();if(bb_model&&bb_model.attributes){attribute_keys=_.keys(bb_model.attributes);keys=keys?_.union(keys,attribute_keys):attribute_keys}}if(keys&&_this.__kb.excludes){keys=_.difference(keys,_this.__kb.excludes)}if(keys&&_this.__kb.statics){keys=_.difference(keys,_this.__kb.statics)}if(_.isObject(options.keys)&&!_.isArray(options.keys)){_this._mapObservables(model,options.keys)}if(_.isObject(options.requires)&&!_.isArray(options.requires)){_this._mapObservables(model,options.requires)}!options.mappings||_this._mapObservables(model,options.mappings);!keys||_this._createObservables(model,keys);!_this.__kb.statics||_this._createObservables(model,_this.__kb.statics,true);!kb.statistics||kb.statistics.register("ViewModel",_this);return _this})}ViewModel.prototype.destroy=function(){var vm_key;if(this.__kb.view_model!==this){for(vm_key in this.__kb.vm_keys){this.__kb.view_model[vm_key]=null}}this.__kb.view_model=null;kb.releaseKeys(this);kb.utils.wrappedDestroy(this);return!kb.statistics||kb.statistics.unregister("ViewModel",this)};ViewModel.prototype.shareOptions=function(){return{store:kb.utils.wrappedStore(this),factory:kb.utils.wrappedFactory(this)}};ViewModel.prototype._createObservables=function(model,keys,is_static){var create_options,key,static_defaults,vm_key,_j,_len1;if(is_static){static_defaults=this.__kb.static_defaults||{}}else{create_options={store:kb.utils.wrappedStore(this),factory:kb.utils.wrappedFactory(this),path:this.__kb.path,event_watcher:kb.utils.wrappedEventWatcher(this)}}for(_j=0,_len1=keys.length;_j<_len1;_j++){key=keys[_j];vm_key=this.__kb.internals&&_.contains(this.__kb.internals,key)?"_"+key:key;if(this[vm_key]){continue}this.__kb.vm_keys[vm_key]=this.__kb.model_keys[key]=true;if(is_static){if(model.has(vm_key)){this[vm_key]=this.__kb.view_model[vm_key]=model.get(vm_key)}else if(vm_key in static_defaults){this[vm_key]=this.__kb.view_model[vm_key]=static_defaults[vm_key]}}else{create_options.key=key;this[vm_key]=this.__kb.view_model[vm_key]=kb.observable(model,create_options,this)}}};ViewModel.prototype._mapObservables=function(model,mappings){var create_options,mapping_info,vm_key;create_options={store:kb.utils.wrappedStore(this),factory:kb.utils.wrappedFactory(this),path:this.__kb.path,event_watcher:kb.utils.wrappedEventWatcher(this)};for(vm_key in mappings){mapping_info=mappings[vm_key];if(this[vm_key]){continue}mapping_info=_.isString(mapping_info)?{key:mapping_info}:_.clone(mapping_info);mapping_info.key||(mapping_info.key=vm_key);this.__kb.vm_keys[vm_key]=this.__kb.model_keys[mapping_info.key]=true;this[vm_key]=this.__kb.view_model[vm_key]=kb.observable(model,_.defaults(mapping_info,create_options),this)}};return ViewModel}();kb.viewModel=function(model,options,view_model){return new kb.ViewModel(model,options,view_model)};COMPARE_EQUAL=0;COMPARE_ASCENDING=-1;COMPARE_DESCENDING=1;kb.compare=function(value_a,value_b){if(_.isString(value_a)){return value_a.localeCompare(""+value_b)}if(_.isString(value_b)){return value_b.localeCompare(""+value_a)}if(value_a===value_b){return COMPARE_EQUAL}else{if(value_a