Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote-tracking branch 'origin/master'

  • Loading branch information...
commit a296c4c94773509392347f17e3a4d9342cc1d4ed 2 parents 78d7d12 + 520984b
@gregjacobs authored
View
9 kevlar.js
@@ -5617,13 +5617,6 @@ Kevlar.persistence.RestProxy = Kevlar.extend( Kevlar.persistence.Proxy, {
urlRoot : "",
/**
- * @cfg {Boolean} appendId
- * True to automatically append the ID of the Model to the {@link #urlRoot} when
- * performing 'read', 'update', and 'delete' actions.
- */
- appendId: true,
-
- /**
* @cfg {Boolean} incremental
* True to have the RestProxy only provide data that has changed to the server when
* updating a model. By using this, it isn't exactly following REST per se, but can
@@ -5897,7 +5890,7 @@ Kevlar.persistence.RestProxy = Kevlar.extend( Kevlar.persistence.Proxy, {
var url = this.urlRoot;
// And now, use the model's ID to set the url.
- if( this.appendId ) {
+ if( action !== 'create' ) {
if( !url.match( /\/$/ ) ) {
url += '/';
}
View
2  kevlar.min.js
@@ -24,4 +24,4 @@ var Class=(function(){function a(f){return !!f&&Object.prototype.toString.call(f
*
* MIT Licensed - http://extjs.com/license/mit.txt
*/
-var Kevlar=function(){var a=window.navigator.userAgent.toLowerCase();this.isIE=/msie/.test(a)&&!(/opera/.test(a))};Kevlar.prototype={constructor:Kevlar,emptyFn:function(){},abstractFn:function(){throw new Error("method must be implemented in subclass")},newId:(function(){var a=0;return function(){return ++a}})(),apply:Class.apply,applyIf:Class.applyIf,extend:Class.extend,bind:function(b,a){return function(){return b.apply(a,arguments)}},namespace:function(){var k,h,f,a,e,b,g,c=arguments;for(f=0,a=c.length;f<a;f++){h=c[f].split(".");k=window[h[0]]=window[h[0]]||{};for(e=1,b=h.length;e<b;e++){g=h[e];k=k[g]=k[g]||{}}}return k},toArray:function(d,g,e,f){if(Kevlar.isIE){f=[];for(var c=0,b=d.length;c<b;c++){f.push(d[c])}return f.slice(g||0,e||f.length)}else{return Array.prototype.slice.call(d,g||0,e||d.length)}},isArray:function(a){return !!a&&Object.prototype.toString.apply(a)==="[object Array]"},isObject:function(a){return !!a&&Object.prototype.toString.call(a)==="[object Object]"},isFunction:function(a){return !!a&&a.constructor===Function},isDate:function(a){return Object.prototype.toString.apply(a)==="[object Date]"},isString:function(a){return typeof a==="string"},isNumber:function(a){return typeof a==="number"&&isFinite(a)},isBoolean:function(a){return typeof a==="boolean"},isRegExp:function(a){return !!a&&a.constructor===RegExp},isElement:function(a){return a?a.nodeType===1:false},isJQuery:function(a){return a instanceof jQuery},isDefined:function(a){return typeof a!=="undefined"},isUndefined:function(a){return typeof a==="undefined"},isPrimitive:function(a){return Kevlar.isString(a)||Kevlar.isNumber(a)||Kevlar.isBoolean(a)},isEmpty:function(b,a){return b===null||b===undefined||((Kevlar.isArray(b)&&!b.length))||(!a?b==="":false)}};Kevlar=new Kevlar();Kevlar.namespace("Kevlar.attribute","Kevlar.data","Kevlar.persistence","Kevlar.util");(function(){var a=Kevlar.util,j=Kevlar.toArray,b=Kevlar.isObject,h=true,i=false;a.Observable=Class.extend(Object,{constructor:function(){var k=this,l=k.events;k.events=l||{};if(k.listeners){k.on(k.listeners);delete k.listeners}this.addEvents("all")},filterOptRe:/^(?:scope|delay|buffer|single)$/,fireEvent:function(){var r=j(arguments),o=r[0].toLowerCase(),t=this,p=h,m=t.events[o],k,n;if(t.eventsSuspended===h){k=t.eventQueue;if(k){k.push(r)}}else{if(b(m)&&m.bubble){if(m.fire.apply(m,r.slice(1))===false){return i}var l=m.bubbleFn,s=m.bubbleFnScope;if(l&&l.call(s,this)===false){return false}n=t.getBubbleTarget&&t.getBubbleTarget();if(n&&n.enableBubble){if(!n.events[o]||!Kevlar.isObject(n.events[o])||!n.events[o].bubble||(!n.events[o].bubbleFn&&l)){n.enableBubble({eventName:o,bubbleFn:l,scope:s})}return n.fireEvent.apply(n,r)}}else{if(b(m)){r.shift();p=m.fire.apply(m,r)}}}if(o!=="all"){this.fireEvent.apply(this,["all"].concat(Array.prototype.slice.call(arguments,0)))}return p},addListener:function(m,q,s,l){var p=this,n,t,r,k;if(b(m)){l=m;for(n in l){t=l[n];if(!p.filterOptRe.test(n)){p.addListener(n,t.fn||t,t.scope||l.scope,t.fn?t:l)}}}else{m=m.toLowerCase();k=p.events[m]||h;if(Kevlar.isBoolean(k)){p.events[m]=k=new a.Event(p,m)}k.addListener(q,s,b(l)?l:{})}return this},removeListener:function(k,n,m){if(typeof k==="object"){var l=k;for(var o in l){this.removeListener(o,l[o],l.scope)}}else{var p=this.events[k.toLowerCase()];if(b(p)){p.removeListener(n,m)}}return this},purgeListeners:function(){var m=this.events,k,l;for(l in m){k=m[l];if(b(k)){k.clearListeners()}}},addEvents:function(n){var m=this;m.events=m.events||{};if(Kevlar.isString(n)){var k=arguments,l=k.length;while(l--){m.events[k[l]]=m.events[k[l]]||h}}else{Kevlar.applyIf(m.events,n)}},hasListener:function(k){var l=this.events[k];return b(l)&&l.listeners.length>0},suspendEvents:function(k){this.eventsSuspended=h;if(k&&!this.eventQueue){this.eventQueue=[]}},resumeEvents:function(){var n=this,o=n.eventQueue||[];n.eventsSuspended=i;delete n.eventQueue;for(var m=0,l=o.length;m<l;m++){var k=n.fireEvent.apply(n,o[m]);if(k===false){return}}},relayEvents:function(r,n){var q=this;function p(o){return function(){return q.fireEvent.apply(q,[o].concat(Array.prototype.slice.call(arguments,0)))}}for(var m=0,k=n.length;m<k;m++){var l=n[m];q.events[l]=q.events[l]||true;r.on(l,p(l),q)}},enableBubble:function(s){var q=this,k,o,l,r;if(!Kevlar.isEmpty(s)){s=Kevlar.isArray(s)?s:Kevlar.toArray(arguments);for(var n=0,p=s.length;n<p;n++){k=s[n];o=l=r=undefined;if(typeof k==="object"){o=k.eventName;l=k.bubbleFn;r=k.scope}else{o=k}o=o.toLowerCase();var m=q.events[o]||true;if(Kevlar.isBoolean(m)){m=new a.Event(q,o);q.events[o]=m}m.bubble=true;if(typeof l==="function"){m.bubbleFn=l;m.bubbleFnScope=r||q}}}},getBubbleTarget:function(){return null}});var f=a.Observable.prototype;f.on=f.addListener;f.un=f.removeListener;f.bind=f.addListener;f.unbind=f.removeListener;f.trigger=f.fireEvent;function g(l,m,k){return function(){if(m.target==arguments[0]){l.apply(k,j(arguments))}}}function d(n,p,k,m){k.task=new a.DelayedTask();return function(){k.task.delay(p.buffer,n,m,j(arguments))}}function e(m,n,l,k){return function(){n.removeListener(l,k);return m.apply(k,arguments)}}function c(n,p,k,m){return function(){var l=new a.DelayedTask();if(!k.tasks){k.tasks=[]}k.tasks.push(l);l.delay(p.delay||10,n,m,j(arguments))}}a.Event=function(l,k){this.name=k;this.obj=l;this.listeners=[]};a.Event.prototype={addListener:function(o,n,m){var p=this,k;n=n||p.obj;if(!p.isListening(o,n)){k=p.createListener(o,n,m);if(p.firing){p.listeners=p.listeners.slice(0)}p.listeners.push(k)}},createListener:function(p,n,q){q=q||{};n=n||this.obj;var k={fn:p,scope:n,options:q},m=p;if(q.target){m=g(m,q,n)}if(q.delay){m=c(m,q,k,n)}if(q.single){m=e(m,this,p,n)}if(q.buffer){m=d(m,q,k,n)}k.fireFn=m;return k},findListener:function(p,o){var q=this.listeners,m=q.length,k,n;while(m--){k=q[m];if(k){n=k.scope;if(k.fn==p&&(n==o||n==this.obj)){return m}}}return -1},isListening:function(l,k){return this.findListener(l,k)!=-1},removeListener:function(r,q){var p,m,n,s=this,o=i;if((p=s.findListener(r,q))!=-1){if(s.firing){s.listeners=s.listeners.slice(0)}m=s.listeners[p];if(m.task){m.task.cancel();delete m.task}n=m.tasks&&m.tasks.length;if(n){while(n--){m.tasks[n].cancel()}delete m.tasks}s.listeners.splice(p,1);o=h}return o},clearListeners:function(){var n=this,k=n.listeners,m=k.length;while(m--){n.removeListener(k[m].fn,k[m].scope)}},fire:function(){var q=this,n=j(arguments),p=q.listeners,k=p.length,o=0,m,r=false;if(k>0){q.firing=h;for(;o<k;o++){m=p[o];if(m&&m.fireFn.apply(m.scope||q.obj||window,n)===i){r=true}}}q.firing=i;return(r)?false:true}}})();Kevlar.attribute.Attribute=Kevlar.extend(Object,{abstractClass:true,name:"",persist:true,statics:{attributeTypes:{},create:function(a){var b=a.type?a.type.toLowerCase():undefined;if(a instanceof Kevlar.attribute.Attribute){return a}else{if(this.hasType(b||"mixed")){return new this.attributeTypes[b||"mixed"](a)}else{throw new Error("Kevlar.attribute.Attribute: Unknown Attribute type: '"+b+"'")}}},registerType:function(b,a){b=b.toLowerCase();if(!this.attributeTypes[b]){this.attributeTypes[b]=a}else{throw new Error("Error: Attribute type '"+b+"' already exists")}},getType:function(a){return this.attributeTypes[a.toLowerCase()]},hasType:function(a){if(!a){return false}else{return !!this.attributeTypes[a.toLowerCase()]}}},constructor:function(b){var c=this;if(typeof b!=="object"){b={name:b}}Kevlar.apply(c,b);var a=c.name;if(a===undefined||a===null||a===""){throw new Error("no 'name' property provided to Kevlar.attribute.Attribute constructor")}else{if(typeof c.name==="number"){c.name=a.toString()}}if(c["default"]){c.defaultValue=c["default"]}},getName:function(){return this.name},getDefaultValue:function(){var a=this.defaultValue;if(typeof a==="function"){a=a()}if(typeof a==="object"){a=Kevlar.util.Object.clone(a);(function b(c){for(var d in c){if(c.hasOwnProperty(d)){if(typeof c[d]==="function"){c[d]=c[d]()}else{if(typeof c[d]==="object"){b(c[d])}}}}})(a)}return a},isPersisted:function(){return this.persist},valuesAreEqual:function(a,b){return Kevlar.util.Object.isEqual(a,b)},beforeSet:function(b,c,a){return c},doSet:function(c,f,b){var e=this,d,a;if(e.hasOwnProperty("set")){d=c._super;c._super=function(g){return e.constructor.prototype.set.apply(e,[c].concat(Array.prototype.slice.call(g||[],0)))};a=e.set.call(c,f,b);c._super=d;return a}else{return e.set(c,f,b)}},set:function(b,c,a){return c},afterSet:function(a,b){return b}});Kevlar.attribute.NumberAttribute=Kevlar.attribute.Attribute.extend({abstractClass:true,useNull:false,stripCharsRegex:/[\$,%]/g});Kevlar.attribute.ObjectAttribute=Kevlar.attribute.Attribute.extend({defaultValue:null,beforeSet:function(b,c,a){if(typeof c!=="object"){c=null}return c}});Kevlar.attribute.Attribute.registerType("object",Kevlar.attribute.ObjectAttribute);Kevlar.attribute.DataComponentAttribute=Kevlar.attribute.ObjectAttribute.extend({abstractClass:true,embedded:false,persistIdOnly:false,isEmbedded:function(){return this.embedded},resolveGlobalPath:function(d){var e=d.split(".");var c;for(var b=0,a=e.length;b<a;b++){c=(c||window)[e[b]]}return c}});Kevlar.persistence.Proxy=Kevlar.extend(Kevlar.util.Observable,{constructor:function(a){Kevlar.apply(this,a)},create:Kevlar.abstractFn,read:Kevlar.abstractFn,update:Kevlar.abstractFn,destroy:Kevlar.abstractFn});Kevlar.apply(Kevlar.persistence.Proxy,{proxies:{},register:function(a,b){var c=Kevlar.persistence.Proxy;a=a.toLowerCase();if(typeof b!=="function"){throw new Error("A Proxy subclass constructor function must be provided to registerProxy()")}if(!c.proxies[a]){c.proxies[a]=b}else{throw new Error("Error: Proxy type '"+a+"' already registered.")}},create:function(a){var c=Kevlar.persistence.Proxy;var b=a.type?a.type.toLowerCase():undefined;if(a instanceof Kevlar.persistence.Proxy){return a}else{if(c.proxies[b]){return new c.proxies[b](a)}else{if(!("type" in a)){throw new Error("Kevlar.persistence.Proxy.create(): No `type` property provided on persistenceProxy config object")}else{throw new Error("Kevlar.persistence.Proxy.create(): Unknown Proxy type: '"+b+"'")}}}}});Kevlar.DataComponent=Kevlar.util.Observable.extend({constructor:function(){this._super(arguments);this.clientId="c"+Kevlar.newId()},getClientId:function(){return this.clientId},getData:Kevlar.abstractFn,isModified:Kevlar.abstractFn,commit:Kevlar.abstractFn,rollback:Kevlar.abstractFn});Kevlar.attribute.BooleanAttribute=Kevlar.attribute.Attribute.extend({useNull:false,beforeSet:function(b,c,a){if(this.useNull&&(c===undefined||c===null||c==="")){return null}return c===true||c==="true"||c==1}});Kevlar.attribute.Attribute.registerType("boolean",Kevlar.attribute.BooleanAttribute);Kevlar.attribute.Attribute.registerType("bool",Kevlar.attribute.BooleanAttribute);Kevlar.attribute.CollectionAttribute=Kevlar.attribute.DataComponentAttribute.extend({embedded:false,persistIdOnly:false,constructor:function(){this._super(arguments);if("collectionClass" in this&&this.collectionClass===undefined){throw new Error("The 'collectionClass' config provided to an Attribute with the name '"+this.getName()+"' either doesn't exist, or doesn't exist just yet. Consider using the String or Function form of the collectionClass config for late binding, if needed")}},valuesAreEqual:function(a,b){return a===b},beforeSet:function(b,d,a){if(this.embedded&&a instanceof Kevlar.Collection){b.unsubscribeEmbeddedCollection(this.getName(),a)}d=this._super(arguments);if(d!==null){var c=this.collectionClass;if(typeof c==="string"){c=this.resolveGlobalPath(c);if(!c){throw new Error("The string value 'collectionClass' config did not resolve to a Collection class for attribute '"+this.getName()+"'")}}else{if(typeof c==="function"&&!Class.isSubclassOf(c,Kevlar.Collection)){this.collectionClass=c=c();if(!c){throw new Error("The function value 'collectionClass' config did not resolve to a Collection class for attribute '"+this.getName()+"'")}}}if(d&&typeof c==="function"&&!(d instanceof c)){d=new c(d)}}return d},afterSet:function(a,b){if(b!==null&&!(b instanceof Kevlar.Collection)){throw new Error("A value set to the attribute '"+this.getName()+"' was not a Kevlar.Collection subclass")}if(this.embedded&&b instanceof Kevlar.Collection){a.subscribeEmbeddedCollection(this.getName(),b)}return b}});Kevlar.attribute.Attribute.registerType("collection",Kevlar.attribute.CollectionAttribute);Kevlar.attribute.DateAttribute=Kevlar.attribute.ObjectAttribute.extend({beforeSet:function(c,d,b){if(!d){return null}if(Kevlar.isDate(d)){return d}var a=Date.parse(d);return(a)?new Date(a):null}});Kevlar.attribute.Attribute.registerType("date",Kevlar.attribute.DateAttribute);Kevlar.attribute.FloatAttribute=Kevlar.attribute.NumberAttribute.extend({beforeSet:function(c,d,b){var a=(this.useNull)?null:0;return(d!==undefined&&d!==null&&d!=="")?parseFloat(String(d).replace(this.stripCharsRegex,""),10):a}});Kevlar.attribute.Attribute.registerType("float",Kevlar.attribute.FloatAttribute);Kevlar.attribute.Attribute.registerType("number",Kevlar.attribute.FloatAttribute);Kevlar.attribute.IntegerAttribute=Kevlar.attribute.NumberAttribute.extend({beforeSet:function(c,d,b){var a=(this.useNull)?null:0;return(d!==undefined&&d!==null&&d!=="")?parseInt(String(d).replace(this.stripCharsRegex,""),10):a}});Kevlar.attribute.Attribute.registerType("int",Kevlar.attribute.IntegerAttribute);Kevlar.attribute.Attribute.registerType("integer",Kevlar.attribute.IntegerAttribute);Kevlar.attribute.MixedAttribute=Kevlar.attribute.Attribute.extend({});Kevlar.attribute.Attribute.registerType("mixed",Kevlar.attribute.MixedAttribute);Kevlar.attribute.ModelAttribute=Kevlar.attribute.DataComponentAttribute.extend({embedded:false,persistIdOnly:false,constructor:function(){this._super(arguments);if("modelClass" in this&&this.modelClass===undefined){throw new Error("The 'modelClass' config provided to an Attribute with the name '"+this.getName()+"' either doesn't exist, or doesn't exist just yet. Consider using the String or Function form of the modelClass config for late binding, if needed")}},valuesAreEqual:function(a,b){return a===b},beforeSet:function(c,d,b){if(this.embedded&&b instanceof Kevlar.Model){c.unsubscribeEmbeddedModel(this.getName(),b)}d=this._super(arguments);if(d!==null){var a=this.modelClass;if(typeof a==="string"){a=this.resolveGlobalPath(a);if(!a){throw new Error("The string value 'modelClass' config did not resolve to a Model class for attribute '"+this.getName()+"'")}}else{if(typeof a==="function"&&!Class.isSubclassOf(a,Kevlar.Model)){this.modelClass=a=a();if(!a){throw new Error("The function value 'modelClass' config did not resolve to a Model class for attribute '"+this.getName()+"'")}}}if(d&&typeof a==="function"&&!(d instanceof a)){d=new a(d)}}return d},afterSet:function(a,b){if(b!==null&&!(b instanceof Kevlar.Model)){throw new Error("A value set to the attribute '"+this.getName()+"' was not a Kevlar.Model subclass")}if(this.embedded&&b instanceof Kevlar.Model){a.subscribeEmbeddedModel(this.getName(),b)}return b}});Kevlar.attribute.Attribute.registerType("model",Kevlar.attribute.ModelAttribute);Kevlar.attribute.StringAttribute=Kevlar.attribute.Attribute.extend({useNull:false,beforeSet:function(c,d,b){var a=(this.useNull)?null:"";return(d===undefined||d===null)?a:String(d)}});Kevlar.attribute.Attribute.registerType("string",Kevlar.attribute.StringAttribute);Kevlar.Collection=Kevlar.DataComponent.extend({modified:false,constructor:function(a){this._super(arguments);this.addEvents("add","addset","reorder","remove","removeset");var b;if(Kevlar.isArray(a)){b=a}else{if(typeof a==="object"){Kevlar.apply(this,a);b=this.models}}if(typeof this.sortBy==="function"){this.sortBy=Kevlar.bind(this.sortBy,this)}this.models=[];this.modelsByClientId={};this.modelsById={};if(b){this.add(b);this.modified=false}this.initialize()},initialize:Kevlar.emptyFn,createModel:function(a){if(!this.model){throw new Error("Cannot instantiate model from anonymous data, 'model' config not provided to Collection.")}return new this.model(a)},add:function(a){this.insert(a)},insert:function(a,f){var c=(typeof f!=="undefined"),d,g,e,j,b=[];if(typeof f!=="number"){f=this.models.length}else{if(f<0){f=0}else{if(f>this.models.length){f=this.models.length}}}if(!Kevlar.isArray(a)){a=[a]}if(a.length===0){return}for(d=0,g=a.length;d<g;d++){e=a[d];if(!(e instanceof Kevlar.Model)){e=this.createModel(e)}if(!this.has(e)){this.modified=true;b.push(e);this.modelsByClientId[e.getClientId()]=e;this.models.splice(f,0,e);f++;if(e.hasIdAttribute()){j=e.getId();if(j!==undefined&&j!==null){this.modelsById[j]=e}e.on("change:"+e.getIdAttribute().getName(),this.onModelIdChange,this)}e.on("all",this.onModelEvent,this);this.fireEvent("add",this,e)}else{if(c){this.modified=true;var h=this.indexOf(e);this.models.splice(h,1);this.models.splice(f,0,e);this.fireEvent("reorder",this,e,f,h);f++}}}if(this.sortBy){this.models.sort(this.sortBy)}if(b.length>0){this.fireEvent("addset",this,b)}},remove:function(g){var b=this.models,e=[],d,a,c,f;if(!Kevlar.isArray(g)){g=[g]}for(d=0,a=g.length;d<a;d++){c=g[d];f=this.indexOf(c);if(f>-1){this.modified=true;delete this.modelsByClientId[c.getClientId()];if(c.hasIdAttribute()){delete this.modelsById[c.getId()];c.un("change:"+c.getIdAttribute().getName(),this.onModelIdChange,this)}c.un("all",this.onModelEvent,this);b.splice(f,1);this.fireEvent("remove",this,c,f);e.push(c)}}if(e.length>0){this.fireEvent("removeset",this,e)}},removeAll:function(){this.remove(Kevlar.util.Object.clone(this.models,false))},onModelIdChange:function(b,c,a){delete this.modelsById[a];if(c!==undefined&&c!==null){this.modelsById[c]=b}},onModelEvent:function(a){if(a==="destroy"){this.remove(arguments[1])}this.fireEvent.apply(this,[a,this].concat(Array.prototype.slice.call(arguments,1)))},getAt:function(a){return this.models[a]||null},getFirst:function(){return this.models[0]||null},getLast:function(){return this.models[this.models.length-1]||null},getRange:function(d,c){var f=this.models,e=f.length,a=[],b;if(e===0){return a}d=Math.max(d||0,0);c=Math.min(typeof c==="undefined"?e-1:c,e-1);for(b=d;b<=c;b++){a.push(f[b])}return a},getModels:function(){return this.getRange()},getData:function(a){return Kevlar.data.NativeObjectConverter.convert(this,a)},getCount:function(){return this.models.length},getByClientId:function(a){return this.modelsByClientId[a]||null},getById:function(a){return this.modelsById[a]||null},has:function(a){return !!this.getByClientId(a.getClientId())},indexOf:function(b){var d=this.models,c,a;if(!this.has(b)){return -1}else{for(c=0,a=d.length;c<a;c++){if(d[c]===b){return c}}}},indexOfId:function(b){var a=this.getById(b);if(a){return this.indexOf(a)}return -1},commit:function(){this.modified=false;var c=this.models;for(var b=0,a=c.length;b<a;b++){c[b].commit()}},rollback:function(){this.modified=false;var c=this.models;for(var b=0,a=c.length;b<a;b++){c[b].rollback()}},isModified:function(){if(this.modified){return true}else{var c=this.models,b,a;for(b=0,a=c.length;b<a;b++){if(c[b].isModified()){return true}}return false}},find:function(c,e,b){b=b||{};var g=this.models,f=b.startIndex||0;for(var d=f,a=g.length;d<a;d++){if(g[d].get(c)===e){return g[d]}}return null},findBy:function(e,b){b=b||{};var g=this.models,d=b.scope||window,f=b.startIndex||0;for(var c=f,a=g.length;c<a;c++){if(e.call(d,g[c],c)===true){return g[c]}}return null}});Kevlar.data.NativeObjectConverter={convert:function(a,e){e=e||{};var b={},d=!!e.persistedOnly,c=!!e.raw,f=(a instanceof Kevlar.Collection)?[]:{};b[a.getClientId()]=f;Kevlar.apply(f,(function g(q){var j,h,n,o,r;if(q instanceof Kevlar.Model){var m=q.getAttributes(),l=e.attributeNames||Kevlar.util.Object.keysToArray(m),s,t;n={};delete e.attributeNames;for(o=0,r=l.length;o<r;o++){s=l[o];if(!d||m[s].isPersisted()===true){t=n[s]=(c)?q.raw(s):q.get(s);if(t instanceof Kevlar.DataComponent){j=t.getClientId();if((h=b[j])){n[s]=h}else{b[j]=n[s]=(t instanceof Kevlar.Collection)?[]:{};Kevlar.apply(b[j],g(t))}}}}}else{if(q instanceof Kevlar.Collection){var k=q.getModels(),p;n=[];for(o=0,r=k.length;o<r;o++){p=k[o];j=p.getClientId();n[o]=b[j]||g(p)}}}return n})(a));return f}};Kevlar.Model=Kevlar.DataComponent.extend({persistenceProxy:null,idAttribute:"id",dirty:false,setCallCount:0,inheritedStatics:{onClassExtended:function(g){g.__Kevlar_modelTypeId=Kevlar.newId();var d=g.prototype,a=g.superclass,j=a.attributes||{},b={},k=[],h,e,f;if(d.hasOwnProperty("attributes")){k=d.attributes}else{if(d.hasOwnProperty("addAttributes")){k=d.addAttributes}}for(e=0,f=k.length;e<f;e++){h=k[e];if(typeof h==="string"){h={name:h}}var c=Kevlar.attribute.Attribute.create(h);b[c.getName()]=c}g.prototype.attributes=Kevlar.apply({},b,j)}},constructor:function(e){var d=this;e=e||{};d=Kevlar.ModelCache.get(d,e[d.idAttribute]);if(d!==this){d.set(e);return d}this._super(arguments);if(d.persistenceProxy&&typeof d.persistenceProxy==="object"&&!(d.persistenceProxy instanceof Kevlar.persistence.Proxy)){d.constructor.prototype.persistenceProxy=Kevlar.persistence.Proxy.create(d.persistenceProxy)}d.addEvents("change","changeset","commit","rollback","destroy");var a=d.attributes,c;for(var b in a){if(e[b]===undefined&&(c=a[b].getDefaultValue())!==undefined){e[b]=c}}d.data={};d.modifiedData={};d.embeddedDataComponentChangeHandlers={};d.embeddedCollectionAddRemoveReorderHandlers={};d.set(e);d.commit();d.initialize()},initialize:Kevlar.emptyFn,getAttributes:function(){return this.attributes},getId:function(){if(!(this.idAttribute in this.attributes)){throw new Error("Error: The `idAttribute` (currently set to an attribute named '"+this.idAttribute+"') was not found on the Model. Set the `idAttribute` config to the name of the id attribute in the Model. The model can't be saved or destroyed without it.")}return this.get(this.idAttribute)},getIdAttribute:function(){return this.attributes[this.idAttribute]||null},getIdAttributeName:function(){return this.idAttribute},hasIdAttribute:function(){return !!this.attributes[this.idAttribute]},set:function(h,c){if(this.setCallCount===0){this.changeSetNewValues={};this.changeSetOldValues={}}this.setCallCount++;var g=this.changeSetNewValues,f=this.changeSetOldValues;if(typeof h==="object"){var i=h;for(var e in i){if(i.hasOwnProperty(e)){this.set(e,i[e])}}}else{var d=this.attributes[h];if(!d){throw new Error("Kevlar.Model.set(): An attribute with the attributeName '"+h+"' was not found.")}var a=this.data[h],b=this.get(h);c=d.beforeSet(this,c,a);c=d.doSet(this,c,a);if(d.hasOwnProperty("set")&&c===undefined){if(!(h in this.data)){this.data[h]=undefined}c=this.get(h);this.changeSetNewValues[h]=c;if(!(h in f)){this.changeSetOldValues[h]=b}this.fireEvent("change:"+h,this,c,b);this.fireEvent("change",this,h,c,b)}c=d.afterSet(this,c);if(!(h in this.data)||!d.valuesAreEqual(a,c)){if(!(h in this.modifiedData)){this.modifiedData[h]=a}this.data[h]=c;this.dirty=true;c=this.get(h);if(h===this.idAttribute){this.id=c}g[h]=c;if(!(h in f)){f[h]=b}this.fireEvent("change:"+h,this,c,b);this.fireEvent("change",this,h,c,b)}}this.setCallCount--;if(this.setCallCount===0){this.fireEvent("changeset",this,g,f)}},get:function(a){if(!(a in this.attributes)){throw new Error("Kevlar.Model::get() error: attribute '"+a+"' was not found on the Model.")}var c=this.data[a],b=this.attributes[a];if(typeof b.get==="function"){c=b.get.call(this,c)}return c},raw:function(a){if(!(a in this.attributes)){throw new Error("Kevlar.Model::raw() error: attribute '"+a+"' was not found on the Model.")}var c=this.data[a],b=this.attributes[a];if(typeof b.raw==="function"){c=b.raw.call(this,c,this)}return c},getDefault:function(a){return this.attributes[a].getDefaultValue()},has:function(a){return !!this.attributes[a]},subscribeEmbeddedModel:function(b,c){var a=function(e,f,g,d,h){this.onEmbeddedDataComponentChange(b,null,e,f,g,d,h)};this.embeddedDataComponentChangeHandlers[b]=a;c.on("change",a,this)},subscribeEmbeddedCollection:function(b,c){var a=function(j,f,g,h,e,i){this.onEmbeddedDataComponentChange(b,j,f,g,h,e,i)};this.embeddedDataComponentChangeHandlers[b]=a;c.on("change",a,this);var d=function(e){this.onEmbeddedCollectionAddRemoveReorder(b,e)};this.embeddedCollectionAddRemoveReorderHandlers[b]=d;c.on({addset:d,removeset:d,reorder:d,scope:this})},unsubscribeEmbeddedModel:function(a,b){this.unsubscribeEmbeddedDataComponent(a,b)},unsubscribeEmbeddedCollection:function(a,b){this.unsubscribeEmbeddedDataComponent(a,b);var c=this.embeddedCollectionAddRemoveReorderHandlers[a];b.un({addset:c,removeset:c,reorder:c,scope:this})},unsubscribeEmbeddedDataComponent:function(c,a){var b=this.embeddedDataComponentChangeHandlers[c];a.un("change",b,this)},onEmbeddedDataComponentChange:function(l,w,o,c,h,k,r){if(!r){r={pathToChangedAttr:c,origNewValue:h,origOldValue:k,embeddedDataComponents:[o]}}if(w){r.embeddedDataComponents.unshift(w)}r.embeddedDataComponents.unshift(this);r.pathToChangedAttr=l+"."+r.pathToChangedAttr;var d=r.pathToChangedAttr,q=r.embeddedDataComponents,e=r.origNewValue,g=r.origOldValue,s=d.split(".");var u=q[q.length-1],t=s.slice(0,s.length-1).join("."),a=s[s.length-1],m=q[q.length-2];if(m instanceof Kevlar.Collection){this.fireEvent("change:"+d,m,u,e,g);this.fireEvent("change:"+t+".*",m,u,a,e,g)}else{this.fireEvent("change:"+d,u,e,g);this.fireEvent("change:"+t+".*",u,a,e,g)}for(var p=s.length-2;p>=0;p--){var b=s.slice(0,p+1).join("."),n=s.slice(0,p).join("."),j=s[p],v=q[p],f=q[p+1];if(v instanceof Kevlar.Collection){this.fireEvent("change:"+b,v,f,f);if(n!==""){this.fireEvent("change:"+n+".*",v,j,f,f)}}else{this.fireEvent("change:"+b,v,f,f);if(n!==""){this.fireEvent("change:"+n+".*",v,j,f,f)}}}if(w){this.fireEvent("change",this,l,w,w,r)}else{this.fireEvent("change",this,l,o,o,r)}},onEmbeddedCollectionAddRemoveReorder:function(a,b){this.fireEvent("change",this,a,b,b)},isNew:function(){if(!this.hasIdAttribute()){return true}else{var a=this.getId();return(typeof a==="undefined"||a===null)}},isDirty:function(){return this.dirty},isModified:function(j){var b=this.attributes,c=this.data;if(!j){var k=!Kevlar.util.Object.isEmpty(this.modifiedData);if(k){return true}var e=this.getEmbeddedDataComponentAttributes(),f;for(var d=0,g=e.length;d<g;d++){var h=e[d].getName();if((f=c[h])&&f.isModified()){return true}}return false}else{var a=this.attributes[j];return(j in this.modifiedData)||(a instanceof Kevlar.attribute.DataComponentAttribute&&a.isEmbedded()&&c[j].isModified())}},getData:function(a){return Kevlar.data.NativeObjectConverter.convert(this,a)},getChanges:function(c){c=c||{};c.attributeNames=Kevlar.util.Object.keysToArray(this.modifiedData);var f=this.getEmbeddedDataComponentAttributes(),g=this.data,b;for(var e=0,a=f.length;e<a;e++){var d=f[e].getName();if((b=g[d])&&b.isModified()){c.attributeNames.push(d)}}return Kevlar.data.NativeObjectConverter.convert(this,c)},commit:function(){this.modifiedData={};this.dirty=false;var e=this.getEmbeddedDataComponentAttributes(),f=this.data,b;for(var d=0,a=e.length;d<a;d++){var c=e[d].getName();if((b=f[c])){b.commit()}}this.fireEvent("commit",this)},rollback:function(){var b=this.modifiedData;for(var a in b){if(b.hasOwnProperty(a)){this.data[a]=b[a]}}this.modifiedData={};this.dirty=false;this.fireEvent("rollback",this)},clone:function(b){var a=Kevlar.util.Object.clone(this.getData());if(typeof b==="undefined"){delete a[this.idAttribute]}else{a[this.idAttribute]=b}return new this.constructor(a)},setProxy:function(a){this.constructor.prototype.persistenceProxy=a},getPersistenceProxy:function(){return this.persistenceProxy},load:function(b){b=b||{};if(!this.persistenceProxy){throw new Error("Kevlar.Model::load() error: Cannot load. No persistenceProxy.")}var a={async:(typeof b.async==="undefined")?true:b.async,success:b.success||Kevlar.emptyFn,failure:b.failure||Kevlar.emptyFn,complete:b.complete||Kevlar.emptyFn,scope:b.scope||window};this.persistenceProxy.read(this,a)},save:function(d){d=d||{};var e=d.scope||d.context||window;if(!this.persistenceProxy){throw new Error("Kevlar.Model::save() error: Cannot save. No persistenceProxy.")}if(!this.hasIdAttribute){throw new Error("Kevlar.Model::save() error: Cannot save. Model does not have an idAttribute that relates to a valid attribute.")}var g=Kevlar.util.Object.clone(this.getData());var a=function(){this.commit();var i=this.getData();for(var h in g){if(g.hasOwnProperty(h)&&!Kevlar.util.Object.isEqual(g[h],i[h])){this.modifiedData[h]=g[h];this.dirty=true}}if(typeof d.success==="function"){d.success.call(e)}};var c=function(){if(typeof d.error==="function"){d.error.call(e)}};var f=function(){if(typeof d.complete==="function"){d.complete.call(e)}};var b={async:(typeof d.async==="undefined")?true:d.async,success:a,error:c,complete:f,scope:this};this.persistenceProxy[this.isNew()?"create":"update"](this,b)},destroy:function(d){d=d||{};var e=d.scope||d.context||window;if(this.isNew()){this.fireEvent("destroy",this);if(typeof d.success==="function"){d.success.call(e)}if(typeof d.complete==="function"){d.complete.call(e)}}else{if(!this.persistenceProxy){throw new Error("Kevlar.Model::destroy() error: Cannot destroy model on server. No persistenceProxy.")}var a=function(){this.fireEvent("destroy",this);if(typeof d.success==="function"){d.success.call(e)}};var c=function(){if(typeof d.error==="function"){d.error.call(e)}};var f=function(){if(typeof d.complete==="function"){d.complete.call(e)}};var b={async:(typeof d.async==="undefined")?true:d.async,success:a,error:c,complete:f,scope:this};this.persistenceProxy.destroy(this,b)}},getEmbeddedDataComponentAttributes:function(){var a=this.attributes,d,e=Kevlar.attribute.DataComponentAttribute,c=[];for(var b in a){if(a.hasOwnProperty(b)&&(d=a[b]) instanceof e&&d.isEmbedded()){c.push(d)}}return c}});Kevlar.Model.prototype.fetch=Kevlar.Model.prototype.load;Kevlar.Model.prototype.toJSON=Kevlar.Model.prototype.getData;Kevlar.Model.prototype.previous=function(a){return undefined};Kevlar.ModelCache={models:{},get:function(c,e){var a=c.constructor,d=a.__Kevlar_modelTypeId,b;if(!this.models[d]){this.models[d]={}}if(typeof e!=="undefined"){b=this.models[d][e];if(!b){this.models[d][e]=c}}return b||c}};Kevlar.persistence.RestProxy=Kevlar.extend(Kevlar.persistence.Proxy,{urlRoot:"",appendId:true,incremental:false,rootProperty:"",actionMethods:{create:"POST",read:"GET",update:"PUT",destroy:"DELETE"},ajax:jQuery.ajax,setRootProperty:function(a){this.rootProperty=a},create:function(e,d){d=d||{};var c=e.getData({persistedOnly:true,raw:true});if(this.rootProperty){var b={};b[this.rootProperty]=c;c=b}var a=function(f){if(f){e.set(f);e.commit()}if(typeof d.success==="function"){d.success.call(d.scope||window)}};return this.ajax({async:(typeof d.async==="undefined")?true:d.async,url:this.buildUrl(e,"create"),type:this.getMethod("create"),dataType:"json",data:JSON.stringify(c),contentType:"application/json",success:a,error:d.error||Kevlar.emptyFn,complete:d.complete||Kevlar.emptyFn,context:d.scope||window})},read:function(c,b){b=b||{};var a=function(d){c.set(d);c.commit();if(typeof b.success==="function"){b.success.call(b.scope||window)}};return this.ajax({async:(typeof b.async==="undefined")?true:b.async,url:this.buildUrl(c,"read"),type:this.getMethod("read"),dataType:"json",success:a,error:b.error||Kevlar.emptyFn,complete:b.complete||Kevlar.emptyFn,context:b.scope||window})},update:function(e,d){d=d||{};var f=d.scope||d.context||window;var c=e.getChanges({persistedOnly:true,raw:true});if(Kevlar.util.Object.isEmpty(c)){if(typeof d.success==="function"){d.success.call(f)}if(typeof d.complete==="function"){d.complete.call(f)}return null}var b;if(this.incremental){b=c}else{b=e.getData({persistedOnly:true,raw:true})}if(this.rootProperty){var a={};a[this.rootProperty]=b;b=a}return this.ajax({async:(typeof d.async==="undefined")?true:d.async,url:this.buildUrl(e,"update"),type:this.getMethod("update"),dataType:"json",data:JSON.stringify(b),contentType:"application/json",success:d.success||Kevlar.emptyFn,error:d.error||Kevlar.emptyFn,complete:d.complete||Kevlar.emptyFn,context:f})},destroy:function(b,a){a=a||{};return this.ajax({async:(typeof a.async==="undefined")?true:a.async,url:this.buildUrl(b,"destroy"),type:this.getMethod("destroy"),success:a.success||Kevlar.emptyFn,error:a.error||Kevlar.emptyFn,complete:a.complete||Kevlar.emptyFn,context:a.scope||window})},buildUrl:function(b,c){var a=this.urlRoot;if(this.appendId){if(!a.match(/\/$/)){a+="/"}a+=encodeURIComponent(b.getId())}return a},getMethod:function(a){return this.actionMethods[a]}});Kevlar.persistence.Proxy.register("rest",Kevlar.persistence.RestProxy);Kevlar.util.DelayedTask=function(d,c,a){var e=this,f,b=function(){clearInterval(f);f=null;d.apply(c,a||[])};e.delay=function(h,j,i,g){e.cancel();d=j||d;c=i||c;a=g||a;f=setInterval(b,h)};e.cancel=function(){if(f){clearInterval(f);f=null}};e.isPending=function(){return !!f}};Kevlar.util.Object={clone:function(d,a){if(typeof a==="undefined"){a=true}if(typeof d!=="object"||d===null){return d}switch(d.constructor){case Date:case RegExp:case String:case Number:case Boolean:return new d.constructor(d)}var e=new d.constructor();for(var b in d){if(d.hasOwnProperty(b)){e[b]=a?Kevlar.util.Object.clone(d[b],true):d[b]}}return e},isEqual:function(e,c,d){if(typeof d==="undefined"){d=true}if(typeof e!==typeof c){return false}if(typeof e!=="object"){if(e!==c){return false}}else{if(e==null||c==null){return e===c}if(Kevlar.isArray(e)!==Kevlar.isArray(c)){return false}var g=Object.prototype.toString.call(e);if(g!=Object.prototype.toString.call(c)){return false}switch(g){case"[object String]":return e===String(c);case"[object Number]":return e!==+e?c!==+c:(e===0?1/e===1/c:e===+c);case"[object Date]":case"[object Boolean]":return +e===+c;case"[object RegExp]":return e.source===c.source&&e.global===c.global&&e.multiline===c.multiline&&e.ignoreCase===c.ignoreCase}var f=Kevlar.util.Object.length;if(f(e)!==f(c)){return false}for(var h in e){if(typeof(e[h])!==typeof(c[h])){return false}if((e[h]===null)!==(c[h]===null)){return false}switch(typeof(e[h])){case"undefined":if(typeof(c[h])!="undefined"){return false}break;case"object":if(e[h]!==null&&c[h]!==null&&(e[h].constructor.toString()!==c[h].constructor.toString()||(d?!Kevlar.util.Object.isEqual(e[h],c[h]):false))){return false}break;case"function":if(e[h].toString()!=c[h].toString()){return false}break;default:if(e[h]!==c[h]){return false}}}}return true},length:function(c){var a=0;for(var b in c){if(c.hasOwnProperty(b)){a++}}return a},isEmpty:function(b){for(var a in b){if(b.hasOwnProperty(a)){return false}}return true},keysToArray:function(c){var a=[],b;for(b in c){if(c.hasOwnProperty(b)){a.push(b)}}return a}};
+var Kevlar=function(){var a=window.navigator.userAgent.toLowerCase();this.isIE=/msie/.test(a)&&!(/opera/.test(a))};Kevlar.prototype={constructor:Kevlar,emptyFn:function(){},abstractFn:function(){throw new Error("method must be implemented in subclass")},newId:(function(){var a=0;return function(){return ++a}})(),apply:Class.apply,applyIf:Class.applyIf,extend:Class.extend,bind:function(b,a){return function(){return b.apply(a,arguments)}},namespace:function(){var k,h,f,a,e,b,g,c=arguments;for(f=0,a=c.length;f<a;f++){h=c[f].split(".");k=window[h[0]]=window[h[0]]||{};for(e=1,b=h.length;e<b;e++){g=h[e];k=k[g]=k[g]||{}}}return k},toArray:function(d,g,e,f){if(Kevlar.isIE){f=[];for(var c=0,b=d.length;c<b;c++){f.push(d[c])}return f.slice(g||0,e||f.length)}else{return Array.prototype.slice.call(d,g||0,e||d.length)}},isArray:function(a){return !!a&&Object.prototype.toString.apply(a)==="[object Array]"},isObject:function(a){return !!a&&Object.prototype.toString.call(a)==="[object Object]"},isFunction:function(a){return !!a&&a.constructor===Function},isDate:function(a){return Object.prototype.toString.apply(a)==="[object Date]"},isString:function(a){return typeof a==="string"},isNumber:function(a){return typeof a==="number"&&isFinite(a)},isBoolean:function(a){return typeof a==="boolean"},isRegExp:function(a){return !!a&&a.constructor===RegExp},isElement:function(a){return a?a.nodeType===1:false},isJQuery:function(a){return a instanceof jQuery},isDefined:function(a){return typeof a!=="undefined"},isUndefined:function(a){return typeof a==="undefined"},isPrimitive:function(a){return Kevlar.isString(a)||Kevlar.isNumber(a)||Kevlar.isBoolean(a)},isEmpty:function(b,a){return b===null||b===undefined||((Kevlar.isArray(b)&&!b.length))||(!a?b==="":false)}};Kevlar=new Kevlar();Kevlar.namespace("Kevlar.attribute","Kevlar.data","Kevlar.persistence","Kevlar.util");(function(){var a=Kevlar.util,j=Kevlar.toArray,b=Kevlar.isObject,h=true,i=false;a.Observable=Class.extend(Object,{constructor:function(){var k=this,l=k.events;k.events=l||{};if(k.listeners){k.on(k.listeners);delete k.listeners}this.addEvents("all")},filterOptRe:/^(?:scope|delay|buffer|single)$/,fireEvent:function(){var r=j(arguments),o=r[0].toLowerCase(),t=this,p=h,m=t.events[o],k,n;if(t.eventsSuspended===h){k=t.eventQueue;if(k){k.push(r)}}else{if(b(m)&&m.bubble){if(m.fire.apply(m,r.slice(1))===false){return i}var l=m.bubbleFn,s=m.bubbleFnScope;if(l&&l.call(s,this)===false){return false}n=t.getBubbleTarget&&t.getBubbleTarget();if(n&&n.enableBubble){if(!n.events[o]||!Kevlar.isObject(n.events[o])||!n.events[o].bubble||(!n.events[o].bubbleFn&&l)){n.enableBubble({eventName:o,bubbleFn:l,scope:s})}return n.fireEvent.apply(n,r)}}else{if(b(m)){r.shift();p=m.fire.apply(m,r)}}}if(o!=="all"){this.fireEvent.apply(this,["all"].concat(Array.prototype.slice.call(arguments,0)))}return p},addListener:function(m,q,s,l){var p=this,n,t,r,k;if(b(m)){l=m;for(n in l){t=l[n];if(!p.filterOptRe.test(n)){p.addListener(n,t.fn||t,t.scope||l.scope,t.fn?t:l)}}}else{m=m.toLowerCase();k=p.events[m]||h;if(Kevlar.isBoolean(k)){p.events[m]=k=new a.Event(p,m)}k.addListener(q,s,b(l)?l:{})}return this},removeListener:function(k,n,m){if(typeof k==="object"){var l=k;for(var o in l){this.removeListener(o,l[o],l.scope)}}else{var p=this.events[k.toLowerCase()];if(b(p)){p.removeListener(n,m)}}return this},purgeListeners:function(){var m=this.events,k,l;for(l in m){k=m[l];if(b(k)){k.clearListeners()}}},addEvents:function(n){var m=this;m.events=m.events||{};if(Kevlar.isString(n)){var k=arguments,l=k.length;while(l--){m.events[k[l]]=m.events[k[l]]||h}}else{Kevlar.applyIf(m.events,n)}},hasListener:function(k){var l=this.events[k];return b(l)&&l.listeners.length>0},suspendEvents:function(k){this.eventsSuspended=h;if(k&&!this.eventQueue){this.eventQueue=[]}},resumeEvents:function(){var n=this,o=n.eventQueue||[];n.eventsSuspended=i;delete n.eventQueue;for(var m=0,l=o.length;m<l;m++){var k=n.fireEvent.apply(n,o[m]);if(k===false){return}}},relayEvents:function(r,n){var q=this;function p(o){return function(){return q.fireEvent.apply(q,[o].concat(Array.prototype.slice.call(arguments,0)))}}for(var m=0,k=n.length;m<k;m++){var l=n[m];q.events[l]=q.events[l]||true;r.on(l,p(l),q)}},enableBubble:function(s){var q=this,k,o,l,r;if(!Kevlar.isEmpty(s)){s=Kevlar.isArray(s)?s:Kevlar.toArray(arguments);for(var n=0,p=s.length;n<p;n++){k=s[n];o=l=r=undefined;if(typeof k==="object"){o=k.eventName;l=k.bubbleFn;r=k.scope}else{o=k}o=o.toLowerCase();var m=q.events[o]||true;if(Kevlar.isBoolean(m)){m=new a.Event(q,o);q.events[o]=m}m.bubble=true;if(typeof l==="function"){m.bubbleFn=l;m.bubbleFnScope=r||q}}}},getBubbleTarget:function(){return null}});var f=a.Observable.prototype;f.on=f.addListener;f.un=f.removeListener;f.bind=f.addListener;f.unbind=f.removeListener;f.trigger=f.fireEvent;function g(l,m,k){return function(){if(m.target==arguments[0]){l.apply(k,j(arguments))}}}function d(n,p,k,m){k.task=new a.DelayedTask();return function(){k.task.delay(p.buffer,n,m,j(arguments))}}function e(m,n,l,k){return function(){n.removeListener(l,k);return m.apply(k,arguments)}}function c(n,p,k,m){return function(){var l=new a.DelayedTask();if(!k.tasks){k.tasks=[]}k.tasks.push(l);l.delay(p.delay||10,n,m,j(arguments))}}a.Event=function(l,k){this.name=k;this.obj=l;this.listeners=[]};a.Event.prototype={addListener:function(o,n,m){var p=this,k;n=n||p.obj;if(!p.isListening(o,n)){k=p.createListener(o,n,m);if(p.firing){p.listeners=p.listeners.slice(0)}p.listeners.push(k)}},createListener:function(p,n,q){q=q||{};n=n||this.obj;var k={fn:p,scope:n,options:q},m=p;if(q.target){m=g(m,q,n)}if(q.delay){m=c(m,q,k,n)}if(q.single){m=e(m,this,p,n)}if(q.buffer){m=d(m,q,k,n)}k.fireFn=m;return k},findListener:function(p,o){var q=this.listeners,m=q.length,k,n;while(m--){k=q[m];if(k){n=k.scope;if(k.fn==p&&(n==o||n==this.obj)){return m}}}return -1},isListening:function(l,k){return this.findListener(l,k)!=-1},removeListener:function(r,q){var p,m,n,s=this,o=i;if((p=s.findListener(r,q))!=-1){if(s.firing){s.listeners=s.listeners.slice(0)}m=s.listeners[p];if(m.task){m.task.cancel();delete m.task}n=m.tasks&&m.tasks.length;if(n){while(n--){m.tasks[n].cancel()}delete m.tasks}s.listeners.splice(p,1);o=h}return o},clearListeners:function(){var n=this,k=n.listeners,m=k.length;while(m--){n.removeListener(k[m].fn,k[m].scope)}},fire:function(){var q=this,n=j(arguments),p=q.listeners,k=p.length,o=0,m,r=false;if(k>0){q.firing=h;for(;o<k;o++){m=p[o];if(m&&m.fireFn.apply(m.scope||q.obj||window,n)===i){r=true}}}q.firing=i;return(r)?false:true}}})();Kevlar.attribute.Attribute=Kevlar.extend(Object,{abstractClass:true,name:"",persist:true,statics:{attributeTypes:{},create:function(a){var b=a.type?a.type.toLowerCase():undefined;if(a instanceof Kevlar.attribute.Attribute){return a}else{if(this.hasType(b||"mixed")){return new this.attributeTypes[b||"mixed"](a)}else{throw new Error("Kevlar.attribute.Attribute: Unknown Attribute type: '"+b+"'")}}},registerType:function(b,a){b=b.toLowerCase();if(!this.attributeTypes[b]){this.attributeTypes[b]=a}else{throw new Error("Error: Attribute type '"+b+"' already exists")}},getType:function(a){return this.attributeTypes[a.toLowerCase()]},hasType:function(a){if(!a){return false}else{return !!this.attributeTypes[a.toLowerCase()]}}},constructor:function(b){var c=this;if(typeof b!=="object"){b={name:b}}Kevlar.apply(c,b);var a=c.name;if(a===undefined||a===null||a===""){throw new Error("no 'name' property provided to Kevlar.attribute.Attribute constructor")}else{if(typeof c.name==="number"){c.name=a.toString()}}if(c["default"]){c.defaultValue=c["default"]}},getName:function(){return this.name},getDefaultValue:function(){var a=this.defaultValue;if(typeof a==="function"){a=a()}if(typeof a==="object"){a=Kevlar.util.Object.clone(a);(function b(c){for(var d in c){if(c.hasOwnProperty(d)){if(typeof c[d]==="function"){c[d]=c[d]()}else{if(typeof c[d]==="object"){b(c[d])}}}}})(a)}return a},isPersisted:function(){return this.persist},valuesAreEqual:function(a,b){return Kevlar.util.Object.isEqual(a,b)},beforeSet:function(b,c,a){return c},doSet:function(c,f,b){var e=this,d,a;if(e.hasOwnProperty("set")){d=c._super;c._super=function(g){return e.constructor.prototype.set.apply(e,[c].concat(Array.prototype.slice.call(g||[],0)))};a=e.set.call(c,f,b);c._super=d;return a}else{return e.set(c,f,b)}},set:function(b,c,a){return c},afterSet:function(a,b){return b}});Kevlar.attribute.NumberAttribute=Kevlar.attribute.Attribute.extend({abstractClass:true,useNull:false,stripCharsRegex:/[\$,%]/g});Kevlar.attribute.ObjectAttribute=Kevlar.attribute.Attribute.extend({defaultValue:null,beforeSet:function(b,c,a){if(typeof c!=="object"){c=null}return c}});Kevlar.attribute.Attribute.registerType("object",Kevlar.attribute.ObjectAttribute);Kevlar.attribute.DataComponentAttribute=Kevlar.attribute.ObjectAttribute.extend({abstractClass:true,embedded:false,persistIdOnly:false,isEmbedded:function(){return this.embedded},resolveGlobalPath:function(d){var e=d.split(".");var c;for(var b=0,a=e.length;b<a;b++){c=(c||window)[e[b]]}return c}});Kevlar.persistence.Proxy=Kevlar.extend(Kevlar.util.Observable,{constructor:function(a){Kevlar.apply(this,a)},create:Kevlar.abstractFn,read:Kevlar.abstractFn,update:Kevlar.abstractFn,destroy:Kevlar.abstractFn});Kevlar.apply(Kevlar.persistence.Proxy,{proxies:{},register:function(a,b){var c=Kevlar.persistence.Proxy;a=a.toLowerCase();if(typeof b!=="function"){throw new Error("A Proxy subclass constructor function must be provided to registerProxy()")}if(!c.proxies[a]){c.proxies[a]=b}else{throw new Error("Error: Proxy type '"+a+"' already registered.")}},create:function(a){var c=Kevlar.persistence.Proxy;var b=a.type?a.type.toLowerCase():undefined;if(a instanceof Kevlar.persistence.Proxy){return a}else{if(c.proxies[b]){return new c.proxies[b](a)}else{if(!("type" in a)){throw new Error("Kevlar.persistence.Proxy.create(): No `type` property provided on persistenceProxy config object")}else{throw new Error("Kevlar.persistence.Proxy.create(): Unknown Proxy type: '"+b+"'")}}}}});Kevlar.DataComponent=Kevlar.util.Observable.extend({constructor:function(){this._super(arguments);this.clientId="c"+Kevlar.newId()},getClientId:function(){return this.clientId},getData:Kevlar.abstractFn,isModified:Kevlar.abstractFn,commit:Kevlar.abstractFn,rollback:Kevlar.abstractFn});Kevlar.attribute.BooleanAttribute=Kevlar.attribute.Attribute.extend({useNull:false,beforeSet:function(b,c,a){if(this.useNull&&(c===undefined||c===null||c==="")){return null}return c===true||c==="true"||c==1}});Kevlar.attribute.Attribute.registerType("boolean",Kevlar.attribute.BooleanAttribute);Kevlar.attribute.Attribute.registerType("bool",Kevlar.attribute.BooleanAttribute);Kevlar.attribute.CollectionAttribute=Kevlar.attribute.DataComponentAttribute.extend({embedded:false,persistIdOnly:false,constructor:function(){this._super(arguments);if("collectionClass" in this&&this.collectionClass===undefined){throw new Error("The 'collectionClass' config provided to an Attribute with the name '"+this.getName()+"' either doesn't exist, or doesn't exist just yet. Consider using the String or Function form of the collectionClass config for late binding, if needed")}},valuesAreEqual:function(a,b){return a===b},beforeSet:function(b,d,a){if(this.embedded&&a instanceof Kevlar.Collection){b.unsubscribeEmbeddedCollection(this.getName(),a)}d=this._super(arguments);if(d!==null){var c=this.collectionClass;if(typeof c==="string"){c=this.resolveGlobalPath(c);if(!c){throw new Error("The string value 'collectionClass' config did not resolve to a Collection class for attribute '"+this.getName()+"'")}}else{if(typeof c==="function"&&!Class.isSubclassOf(c,Kevlar.Collection)){this.collectionClass=c=c();if(!c){throw new Error("The function value 'collectionClass' config did not resolve to a Collection class for attribute '"+this.getName()+"'")}}}if(d&&typeof c==="function"&&!(d instanceof c)){d=new c(d)}}return d},afterSet:function(a,b){if(b!==null&&!(b instanceof Kevlar.Collection)){throw new Error("A value set to the attribute '"+this.getName()+"' was not a Kevlar.Collection subclass")}if(this.embedded&&b instanceof Kevlar.Collection){a.subscribeEmbeddedCollection(this.getName(),b)}return b}});Kevlar.attribute.Attribute.registerType("collection",Kevlar.attribute.CollectionAttribute);Kevlar.attribute.DateAttribute=Kevlar.attribute.ObjectAttribute.extend({beforeSet:function(c,d,b){if(!d){return null}if(Kevlar.isDate(d)){return d}var a=Date.parse(d);return(a)?new Date(a):null}});Kevlar.attribute.Attribute.registerType("date",Kevlar.attribute.DateAttribute);Kevlar.attribute.FloatAttribute=Kevlar.attribute.NumberAttribute.extend({beforeSet:function(c,d,b){var a=(this.useNull)?null:0;return(d!==undefined&&d!==null&&d!=="")?parseFloat(String(d).replace(this.stripCharsRegex,""),10):a}});Kevlar.attribute.Attribute.registerType("float",Kevlar.attribute.FloatAttribute);Kevlar.attribute.Attribute.registerType("number",Kevlar.attribute.FloatAttribute);Kevlar.attribute.IntegerAttribute=Kevlar.attribute.NumberAttribute.extend({beforeSet:function(c,d,b){var a=(this.useNull)?null:0;return(d!==undefined&&d!==null&&d!=="")?parseInt(String(d).replace(this.stripCharsRegex,""),10):a}});Kevlar.attribute.Attribute.registerType("int",Kevlar.attribute.IntegerAttribute);Kevlar.attribute.Attribute.registerType("integer",Kevlar.attribute.IntegerAttribute);Kevlar.attribute.MixedAttribute=Kevlar.attribute.Attribute.extend({});Kevlar.attribute.Attribute.registerType("mixed",Kevlar.attribute.MixedAttribute);Kevlar.attribute.ModelAttribute=Kevlar.attribute.DataComponentAttribute.extend({embedded:false,persistIdOnly:false,constructor:function(){this._super(arguments);if("modelClass" in this&&this.modelClass===undefined){throw new Error("The 'modelClass' config provided to an Attribute with the name '"+this.getName()+"' either doesn't exist, or doesn't exist just yet. Consider using the String or Function form of the modelClass config for late binding, if needed")}},valuesAreEqual:function(a,b){return a===b},beforeSet:function(c,d,b){if(this.embedded&&b instanceof Kevlar.Model){c.unsubscribeEmbeddedModel(this.getName(),b)}d=this._super(arguments);if(d!==null){var a=this.modelClass;if(typeof a==="string"){a=this.resolveGlobalPath(a);if(!a){throw new Error("The string value 'modelClass' config did not resolve to a Model class for attribute '"+this.getName()+"'")}}else{if(typeof a==="function"&&!Class.isSubclassOf(a,Kevlar.Model)){this.modelClass=a=a();if(!a){throw new Error("The function value 'modelClass' config did not resolve to a Model class for attribute '"+this.getName()+"'")}}}if(d&&typeof a==="function"&&!(d instanceof a)){d=new a(d)}}return d},afterSet:function(a,b){if(b!==null&&!(b instanceof Kevlar.Model)){throw new Error("A value set to the attribute '"+this.getName()+"' was not a Kevlar.Model subclass")}if(this.embedded&&b instanceof Kevlar.Model){a.subscribeEmbeddedModel(this.getName(),b)}return b}});Kevlar.attribute.Attribute.registerType("model",Kevlar.attribute.ModelAttribute);Kevlar.attribute.StringAttribute=Kevlar.attribute.Attribute.extend({useNull:false,beforeSet:function(c,d,b){var a=(this.useNull)?null:"";return(d===undefined||d===null)?a:String(d)}});Kevlar.attribute.Attribute.registerType("string",Kevlar.attribute.StringAttribute);Kevlar.Collection=Kevlar.DataComponent.extend({modified:false,constructor:function(a){this._super(arguments);this.addEvents("add","addset","reorder","remove","removeset");var b;if(Kevlar.isArray(a)){b=a}else{if(typeof a==="object"){Kevlar.apply(this,a);b=this.models}}if(typeof this.sortBy==="function"){this.sortBy=Kevlar.bind(this.sortBy,this)}this.models=[];this.modelsByClientId={};this.modelsById={};if(b){this.add(b);this.modified=false}this.initialize()},initialize:Kevlar.emptyFn,createModel:function(a){if(!this.model){throw new Error("Cannot instantiate model from anonymous data, 'model' config not provided to Collection.")}return new this.model(a)},add:function(a){this.insert(a)},insert:function(a,f){var c=(typeof f!=="undefined"),d,g,e,j,b=[];if(typeof f!=="number"){f=this.models.length}else{if(f<0){f=0}else{if(f>this.models.length){f=this.models.length}}}if(!Kevlar.isArray(a)){a=[a]}if(a.length===0){return}for(d=0,g=a.length;d<g;d++){e=a[d];if(!(e instanceof Kevlar.Model)){e=this.createModel(e)}if(!this.has(e)){this.modified=true;b.push(e);this.modelsByClientId[e.getClientId()]=e;this.models.splice(f,0,e);f++;if(e.hasIdAttribute()){j=e.getId();if(j!==undefined&&j!==null){this.modelsById[j]=e}e.on("change:"+e.getIdAttribute().getName(),this.onModelIdChange,this)}e.on("all",this.onModelEvent,this);this.fireEvent("add",this,e)}else{if(c){this.modified=true;var h=this.indexOf(e);this.models.splice(h,1);this.models.splice(f,0,e);this.fireEvent("reorder",this,e,f,h);f++}}}if(this.sortBy){this.models.sort(this.sortBy)}if(b.length>0){this.fireEvent("addset",this,b)}},remove:function(g){var b=this.models,e=[],d,a,c,f;if(!Kevlar.isArray(g)){g=[g]}for(d=0,a=g.length;d<a;d++){c=g[d];f=this.indexOf(c);if(f>-1){this.modified=true;delete this.modelsByClientId[c.getClientId()];if(c.hasIdAttribute()){delete this.modelsById[c.getId()];c.un("change:"+c.getIdAttribute().getName(),this.onModelIdChange,this)}c.un("all",this.onModelEvent,this);b.splice(f,1);this.fireEvent("remove",this,c,f);e.push(c)}}if(e.length>0){this.fireEvent("removeset",this,e)}},removeAll:function(){this.remove(Kevlar.util.Object.clone(this.models,false))},onModelIdChange:function(b,c,a){delete this.modelsById[a];if(c!==undefined&&c!==null){this.modelsById[c]=b}},onModelEvent:function(a){if(a==="destroy"){this.remove(arguments[1])}this.fireEvent.apply(this,[a,this].concat(Array.prototype.slice.call(arguments,1)))},getAt:function(a){return this.models[a]||null},getFirst:function(){return this.models[0]||null},getLast:function(){return this.models[this.models.length-1]||null},getRange:function(d,c){var f=this.models,e=f.length,a=[],b;if(e===0){return a}d=Math.max(d||0,0);c=Math.min(typeof c==="undefined"?e-1:c,e-1);for(b=d;b<=c;b++){a.push(f[b])}return a},getModels:function(){return this.getRange()},getData:function(a){return Kevlar.data.NativeObjectConverter.convert(this,a)},getCount:function(){return this.models.length},getByClientId:function(a){return this.modelsByClientId[a]||null},getById:function(a){return this.modelsById[a]||null},has:function(a){return !!this.getByClientId(a.getClientId())},indexOf:function(b){var d=this.models,c,a;if(!this.has(b)){return -1}else{for(c=0,a=d.length;c<a;c++){if(d[c]===b){return c}}}},indexOfId:function(b){var a=this.getById(b);if(a){return this.indexOf(a)}return -1},commit:function(){this.modified=false;var c=this.models;for(var b=0,a=c.length;b<a;b++){c[b].commit()}},rollback:function(){this.modified=false;var c=this.models;for(var b=0,a=c.length;b<a;b++){c[b].rollback()}},isModified:function(){if(this.modified){return true}else{var c=this.models,b,a;for(b=0,a=c.length;b<a;b++){if(c[b].isModified()){return true}}return false}},find:function(c,e,b){b=b||{};var g=this.models,f=b.startIndex||0;for(var d=f,a=g.length;d<a;d++){if(g[d].get(c)===e){return g[d]}}return null},findBy:function(e,b){b=b||{};var g=this.models,d=b.scope||window,f=b.startIndex||0;for(var c=f,a=g.length;c<a;c++){if(e.call(d,g[c],c)===true){return g[c]}}return null}});Kevlar.data.NativeObjectConverter={convert:function(a,e){e=e||{};var b={},d=!!e.persistedOnly,c=!!e.raw,f=(a instanceof Kevlar.Collection)?[]:{};b[a.getClientId()]=f;Kevlar.apply(f,(function g(q){var j,h,n,o,r;if(q instanceof Kevlar.Model){var m=q.getAttributes(),l=e.attributeNames||Kevlar.util.Object.keysToArray(m),s,t;n={};delete e.attributeNames;for(o=0,r=l.length;o<r;o++){s=l[o];if(!d||m[s].isPersisted()===true){t=n[s]=(c)?q.raw(s):q.get(s);if(t instanceof Kevlar.DataComponent){j=t.getClientId();if((h=b[j])){n[s]=h}else{b[j]=n[s]=(t instanceof Kevlar.Collection)?[]:{};Kevlar.apply(b[j],g(t))}}}}}else{if(q instanceof Kevlar.Collection){var k=q.getModels(),p;n=[];for(o=0,r=k.length;o<r;o++){p=k[o];j=p.getClientId();n[o]=b[j]||g(p)}}}return n})(a));return f}};Kevlar.Model=Kevlar.DataComponent.extend({persistenceProxy:null,idAttribute:"id",dirty:false,setCallCount:0,inheritedStatics:{onClassExtended:function(g){g.__Kevlar_modelTypeId=Kevlar.newId();var d=g.prototype,a=g.superclass,j=a.attributes||{},b={},k=[],h,e,f;if(d.hasOwnProperty("attributes")){k=d.attributes}else{if(d.hasOwnProperty("addAttributes")){k=d.addAttributes}}for(e=0,f=k.length;e<f;e++){h=k[e];if(typeof h==="string"){h={name:h}}var c=Kevlar.attribute.Attribute.create(h);b[c.getName()]=c}g.prototype.attributes=Kevlar.apply({},b,j)}},constructor:function(e){var d=this;e=e||{};d=Kevlar.ModelCache.get(d,e[d.idAttribute]);if(d!==this){d.set(e);return d}this._super(arguments);if(d.persistenceProxy&&typeof d.persistenceProxy==="object"&&!(d.persistenceProxy instanceof Kevlar.persistence.Proxy)){d.constructor.prototype.persistenceProxy=Kevlar.persistence.Proxy.create(d.persistenceProxy)}d.addEvents("change","changeset","commit","rollback","destroy");var a=d.attributes,c;for(var b in a){if(e[b]===undefined&&(c=a[b].getDefaultValue())!==undefined){e[b]=c}}d.data={};d.modifiedData={};d.embeddedDataComponentChangeHandlers={};d.embeddedCollectionAddRemoveReorderHandlers={};d.set(e);d.commit();d.initialize()},initialize:Kevlar.emptyFn,getAttributes:function(){return this.attributes},getId:function(){if(!(this.idAttribute in this.attributes)){throw new Error("Error: The `idAttribute` (currently set to an attribute named '"+this.idAttribute+"') was not found on the Model. Set the `idAttribute` config to the name of the id attribute in the Model. The model can't be saved or destroyed without it.")}return this.get(this.idAttribute)},getIdAttribute:function(){return this.attributes[this.idAttribute]||null},getIdAttributeName:function(){return this.idAttribute},hasIdAttribute:function(){return !!this.attributes[this.idAttribute]},set:function(h,c){if(this.setCallCount===0){this.changeSetNewValues={};this.changeSetOldValues={}}this.setCallCount++;var g=this.changeSetNewValues,f=this.changeSetOldValues;if(typeof h==="object"){var i=h;for(var e in i){if(i.hasOwnProperty(e)){this.set(e,i[e])}}}else{var d=this.attributes[h];if(!d){throw new Error("Kevlar.Model.set(): An attribute with the attributeName '"+h+"' was not found.")}var a=this.data[h],b=this.get(h);c=d.beforeSet(this,c,a);c=d.doSet(this,c,a);if(d.hasOwnProperty("set")&&c===undefined){if(!(h in this.data)){this.data[h]=undefined}c=this.get(h);this.changeSetNewValues[h]=c;if(!(h in f)){this.changeSetOldValues[h]=b}this.fireEvent("change:"+h,this,c,b);this.fireEvent("change",this,h,c,b)}c=d.afterSet(this,c);if(!(h in this.data)||!d.valuesAreEqual(a,c)){if(!(h in this.modifiedData)){this.modifiedData[h]=a}this.data[h]=c;this.dirty=true;c=this.get(h);if(h===this.idAttribute){this.id=c}g[h]=c;if(!(h in f)){f[h]=b}this.fireEvent("change:"+h,this,c,b);this.fireEvent("change",this,h,c,b)}}this.setCallCount--;if(this.setCallCount===0){this.fireEvent("changeset",this,g,f)}},get:function(a){if(!(a in this.attributes)){throw new Error("Kevlar.Model::get() error: attribute '"+a+"' was not found on the Model.")}var c=this.data[a],b=this.attributes[a];if(typeof b.get==="function"){c=b.get.call(this,c)}return c},raw:function(a){if(!(a in this.attributes)){throw new Error("Kevlar.Model::raw() error: attribute '"+a+"' was not found on the Model.")}var c=this.data[a],b=this.attributes[a];if(typeof b.raw==="function"){c=b.raw.call(this,c,this)}return c},getDefault:function(a){return this.attributes[a].getDefaultValue()},has:function(a){return !!this.attributes[a]},subscribeEmbeddedModel:function(b,c){var a=function(e,f,g,d,h){this.onEmbeddedDataComponentChange(b,null,e,f,g,d,h)};this.embeddedDataComponentChangeHandlers[b]=a;c.on("change",a,this)},subscribeEmbeddedCollection:function(b,c){var a=function(j,f,g,h,e,i){this.onEmbeddedDataComponentChange(b,j,f,g,h,e,i)};this.embeddedDataComponentChangeHandlers[b]=a;c.on("change",a,this);var d=function(e){this.onEmbeddedCollectionAddRemoveReorder(b,e)};this.embeddedCollectionAddRemoveReorderHandlers[b]=d;c.on({addset:d,removeset:d,reorder:d,scope:this})},unsubscribeEmbeddedModel:function(a,b){this.unsubscribeEmbeddedDataComponent(a,b)},unsubscribeEmbeddedCollection:function(a,b){this.unsubscribeEmbeddedDataComponent(a,b);var c=this.embeddedCollectionAddRemoveReorderHandlers[a];b.un({addset:c,removeset:c,reorder:c,scope:this})},unsubscribeEmbeddedDataComponent:function(c,a){var b=this.embeddedDataComponentChangeHandlers[c];a.un("change",b,this)},onEmbeddedDataComponentChange:function(l,w,o,c,h,k,r){if(!r){r={pathToChangedAttr:c,origNewValue:h,origOldValue:k,embeddedDataComponents:[o]}}if(w){r.embeddedDataComponents.unshift(w)}r.embeddedDataComponents.unshift(this);r.pathToChangedAttr=l+"."+r.pathToChangedAttr;var d=r.pathToChangedAttr,q=r.embeddedDataComponents,e=r.origNewValue,g=r.origOldValue,s=d.split(".");var u=q[q.length-1],t=s.slice(0,s.length-1).join("."),a=s[s.length-1],m=q[q.length-2];if(m instanceof Kevlar.Collection){this.fireEvent("change:"+d,m,u,e,g);this.fireEvent("change:"+t+".*",m,u,a,e,g)}else{this.fireEvent("change:"+d,u,e,g);this.fireEvent("change:"+t+".*",u,a,e,g)}for(var p=s.length-2;p>=0;p--){var b=s.slice(0,p+1).join("."),n=s.slice(0,p).join("."),j=s[p],v=q[p],f=q[p+1];if(v instanceof Kevlar.Collection){this.fireEvent("change:"+b,v,f,f);if(n!==""){this.fireEvent("change:"+n+".*",v,j,f,f)}}else{this.fireEvent("change:"+b,v,f,f);if(n!==""){this.fireEvent("change:"+n+".*",v,j,f,f)}}}if(w){this.fireEvent("change",this,l,w,w,r)}else{this.fireEvent("change",this,l,o,o,r)}},onEmbeddedCollectionAddRemoveReorder:function(a,b){this.fireEvent("change",this,a,b,b)},isNew:function(){if(!this.hasIdAttribute()){return true}else{var a=this.getId();return(typeof a==="undefined"||a===null)}},isDirty:function(){return this.dirty},isModified:function(j){var b=this.attributes,c=this.data;if(!j){var k=!Kevlar.util.Object.isEmpty(this.modifiedData);if(k){return true}var e=this.getEmbeddedDataComponentAttributes(),f;for(var d=0,g=e.length;d<g;d++){var h=e[d].getName();if((f=c[h])&&f.isModified()){return true}}return false}else{var a=this.attributes[j];return(j in this.modifiedData)||(a instanceof Kevlar.attribute.DataComponentAttribute&&a.isEmbedded()&&c[j].isModified())}},getData:function(a){return Kevlar.data.NativeObjectConverter.convert(this,a)},getChanges:function(c){c=c||{};c.attributeNames=Kevlar.util.Object.keysToArray(this.modifiedData);var f=this.getEmbeddedDataComponentAttributes(),g=this.data,b;for(var e=0,a=f.length;e<a;e++){var d=f[e].getName();if((b=g[d])&&b.isModified()){c.attributeNames.push(d)}}return Kevlar.data.NativeObjectConverter.convert(this,c)},commit:function(){this.modifiedData={};this.dirty=false;var e=this.getEmbeddedDataComponentAttributes(),f=this.data,b;for(var d=0,a=e.length;d<a;d++){var c=e[d].getName();if((b=f[c])){b.commit()}}this.fireEvent("commit",this)},rollback:function(){var b=this.modifiedData;for(var a in b){if(b.hasOwnProperty(a)){this.data[a]=b[a]}}this.modifiedData={};this.dirty=false;this.fireEvent("rollback",this)},clone:function(b){var a=Kevlar.util.Object.clone(this.getData());if(typeof b==="undefined"){delete a[this.idAttribute]}else{a[this.idAttribute]=b}return new this.constructor(a)},setProxy:function(a){this.constructor.prototype.persistenceProxy=a},getPersistenceProxy:function(){return this.persistenceProxy},load:function(b){b=b||{};if(!this.persistenceProxy){throw new Error("Kevlar.Model::load() error: Cannot load. No persistenceProxy.")}var a={async:(typeof b.async==="undefined")?true:b.async,success:b.success||Kevlar.emptyFn,failure:b.failure||Kevlar.emptyFn,complete:b.complete||Kevlar.emptyFn,scope:b.scope||window};this.persistenceProxy.read(this,a)},save:function(d){d=d||{};var e=d.scope||d.context||window;if(!this.persistenceProxy){throw new Error("Kevlar.Model::save() error: Cannot save. No persistenceProxy.")}if(!this.hasIdAttribute){throw new Error("Kevlar.Model::save() error: Cannot save. Model does not have an idAttribute that relates to a valid attribute.")}var g=Kevlar.util.Object.clone(this.getData());var a=function(){this.commit();var i=this.getData();for(var h in g){if(g.hasOwnProperty(h)&&!Kevlar.util.Object.isEqual(g[h],i[h])){this.modifiedData[h]=g[h];this.dirty=true}}if(typeof d.success==="function"){d.success.call(e)}};var c=function(){if(typeof d.error==="function"){d.error.call(e)}};var f=function(){if(typeof d.complete==="function"){d.complete.call(e)}};var b={async:(typeof d.async==="undefined")?true:d.async,success:a,error:c,complete:f,scope:this};this.persistenceProxy[this.isNew()?"create":"update"](this,b)},destroy:function(d){d=d||{};var e=d.scope||d.context||window;if(this.isNew()){this.fireEvent("destroy",this);if(typeof d.success==="function"){d.success.call(e)}if(typeof d.complete==="function"){d.complete.call(e)}}else{if(!this.persistenceProxy){throw new Error("Kevlar.Model::destroy() error: Cannot destroy model on server. No persistenceProxy.")}var a=function(){this.fireEvent("destroy",this);if(typeof d.success==="function"){d.success.call(e)}};var c=function(){if(typeof d.error==="function"){d.error.call(e)}};var f=function(){if(typeof d.complete==="function"){d.complete.call(e)}};var b={async:(typeof d.async==="undefined")?true:d.async,success:a,error:c,complete:f,scope:this};this.persistenceProxy.destroy(this,b)}},getEmbeddedDataComponentAttributes:function(){var a=this.attributes,d,e=Kevlar.attribute.DataComponentAttribute,c=[];for(var b in a){if(a.hasOwnProperty(b)&&(d=a[b]) instanceof e&&d.isEmbedded()){c.push(d)}}return c}});Kevlar.Model.prototype.fetch=Kevlar.Model.prototype.load;Kevlar.Model.prototype.toJSON=Kevlar.Model.prototype.getData;Kevlar.Model.prototype.previous=function(a){return undefined};Kevlar.ModelCache={models:{},get:function(c,e){var a=c.constructor,d=a.__Kevlar_modelTypeId,b;if(!this.models[d]){this.models[d]={}}if(typeof e!=="undefined"){b=this.models[d][e];if(!b){this.models[d][e]=c}}return b||c}};Kevlar.persistence.RestProxy=Kevlar.extend(Kevlar.persistence.Proxy,{urlRoot:"",incremental:false,rootProperty:"",actionMethods:{create:"POST",read:"GET",update:"PUT",destroy:"DELETE"},ajax:jQuery.ajax,setRootProperty:function(a){this.rootProperty=a},create:function(e,d){d=d||{};var c=e.getData({persistedOnly:true,raw:true});if(this.rootProperty){var b={};b[this.rootProperty]=c;c=b}var a=function(f){if(f){e.set(f);e.commit()}if(typeof d.success==="function"){d.success.call(d.scope||window)}};return this.ajax({async:(typeof d.async==="undefined")?true:d.async,url:this.buildUrl(e,"create"),type:this.getMethod("create"),dataType:"json",data:JSON.stringify(c),contentType:"application/json",success:a,error:d.error||Kevlar.emptyFn,complete:d.complete||Kevlar.emptyFn,context:d.scope||window})},read:function(c,b){b=b||{};var a=function(d){c.set(d);c.commit();if(typeof b.success==="function"){b.success.call(b.scope||window)}};return this.ajax({async:(typeof b.async==="undefined")?true:b.async,url:this.buildUrl(c,"read"),type:this.getMethod("read"),dataType:"json",success:a,error:b.error||Kevlar.emptyFn,complete:b.complete||Kevlar.emptyFn,context:b.scope||window})},update:function(e,d){d=d||{};var f=d.scope||d.context||window;var c=e.getChanges({persistedOnly:true,raw:true});if(Kevlar.util.Object.isEmpty(c)){if(typeof d.success==="function"){d.success.call(f)}if(typeof d.complete==="function"){d.complete.call(f)}return null}var b;if(this.incremental){b=c}else{b=e.getData({persistedOnly:true,raw:true})}if(this.rootProperty){var a={};a[this.rootProperty]=b;b=a}return this.ajax({async:(typeof d.async==="undefined")?true:d.async,url:this.buildUrl(e,"update"),type:this.getMethod("update"),dataType:"json",data:JSON.stringify(b),contentType:"application/json",success:d.success||Kevlar.emptyFn,error:d.error||Kevlar.emptyFn,complete:d.complete||Kevlar.emptyFn,context:f})},destroy:function(b,a){a=a||{};return this.ajax({async:(typeof a.async==="undefined")?true:a.async,url:this.buildUrl(b,"destroy"),type:this.getMethod("destroy"),success:a.success||Kevlar.emptyFn,error:a.error||Kevlar.emptyFn,complete:a.complete||Kevlar.emptyFn,context:a.scope||window})},buildUrl:function(b,c){var a=this.urlRoot;if(c!=="create"){if(!a.match(/\/$/)){a+="/"}a+=encodeURIComponent(b.getId())}return a},getMethod:function(a){return this.actionMethods[a]}});Kevlar.persistence.Proxy.register("rest",Kevlar.persistence.RestProxy);Kevlar.util.DelayedTask=function(d,c,a){var e=this,f,b=function(){clearInterval(f);f=null;d.apply(c,a||[])};e.delay=function(h,j,i,g){e.cancel();d=j||d;c=i||c;a=g||a;f=setInterval(b,h)};e.cancel=function(){if(f){clearInterval(f);f=null}};e.isPending=function(){return !!f}};Kevlar.util.Object={clone:function(d,a){if(typeof a==="undefined"){a=true}if(typeof d!=="object"||d===null){return d}switch(d.constructor){case Date:case RegExp:case String:case Number:case Boolean:return new d.constructor(d)}var e=new d.constructor();for(var b in d){if(d.hasOwnProperty(b)){e[b]=a?Kevlar.util.Object.clone(d[b],true):d[b]}}return e},isEqual:function(e,c,d){if(typeof d==="undefined"){d=true}if(typeof e!==typeof c){return false}if(typeof e!=="object"){if(e!==c){return false}}else{if(e==null||c==null){return e===c}if(Kevlar.isArray(e)!==Kevlar.isArray(c)){return false}var g=Object.prototype.toString.call(e);if(g!=Object.prototype.toString.call(c)){return false}switch(g){case"[object String]":return e===String(c);case"[object Number]":return e!==+e?c!==+c:(e===0?1/e===1/c:e===+c);case"[object Date]":case"[object Boolean]":return +e===+c;case"[object RegExp]":return e.source===c.source&&e.global===c.global&&e.multiline===c.multiline&&e.ignoreCase===c.ignoreCase}var f=Kevlar.util.Object.length;if(f(e)!==f(c)){return false}for(var h in e){if(typeof(e[h])!==typeof(c[h])){return false}if((e[h]===null)!==(c[h]===null)){return false}switch(typeof(e[h])){case"undefined":if(typeof(c[h])!="undefined"){return false}break;case"object":if(e[h]!==null&&c[h]!==null&&(e[h].constructor.toString()!==c[h].constructor.toString()||(d?!Kevlar.util.Object.isEqual(e[h],c[h]):false))){return false}break;case"function":if(e[h].toString()!=c[h].toString()){return false}break;default:if(e[h]!==c[h]){return false}}}}return true},length:function(c){var a=0;for(var b in c){if(c.hasOwnProperty(b)){a++}}return a},isEmpty:function(b){for(var a in b){if(b.hasOwnProperty(a)){return false}}return true},keysToArray:function(c){var a=[],b;for(b in c){if(c.hasOwnProperty(b)){a.push(b)}}return a}};
View
9 src/persistence/RestProxy.js
@@ -20,13 +20,6 @@ Kevlar.persistence.RestProxy = Kevlar.extend( Kevlar.persistence.Proxy, {
urlRoot : "",
/**
- * @cfg {Boolean} appendId
- * True to automatically append the ID of the Model to the {@link #urlRoot} when
- * performing 'read', 'update', and 'delete' actions.
- */
- appendId: true,
-
- /**
* @cfg {Boolean} incremental
* True to have the RestProxy only provide data that has changed to the server when
* updating a model. By using this, it isn't exactly following REST per se, but can
@@ -300,7 +293,7 @@ Kevlar.persistence.RestProxy = Kevlar.extend( Kevlar.persistence.Proxy, {
var url = this.urlRoot;
// And now, use the model's ID to set the url.
- if( this.appendId ) {
+ if( action !== 'create' ) {
if( !url.match( /\/$/ ) ) {
url += '/';
}
View
33 tests/kevlarTests.js
@@ -7023,7 +7023,7 @@ tests.unit.persistence.add( new Ext.test.TestSuite( {
name: 'Test buildUrl()',
- "buildUrl() should return simply the configured urlRoot, if the 'appendId' config is false" : function() {
+ "buildUrl() should handle a urlRoot without a trailing slash" : function() {
var mockModel = JsMockito.mock( Kevlar.Model );
JsMockito.when( mockModel ).getId().thenReturn( 42 );
@@ -7032,29 +7032,26 @@ tests.unit.persistence.add( new Ext.test.TestSuite( {
appendId : false
} );
- Y.Assert.areSame( '/testUrl', proxy.buildUrl( mockModel ), "buildUrl() should have simply still returned the url" );
+ Y.Assert.areSame( '/testUrl', proxy.buildUrl( mockModel, 'create' ), "buildUrl() should have returned the urlRoot when doing a 'create'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'read' ), "buildUrl() should have appended the ID when doing a 'read'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'update' ), "buildUrl() should have appended the ID when doing a 'update'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'delete' ), "buildUrl() should have appended the ID when doing a 'delete'" );
},
-
-
- "buildUrl() should return the configured urlRoot with the model's id, if the 'appendId' config is true" : function() {
+
+
+ "buildUrl() should handle a urlRoot with a trailing slash" : function() {
var mockModel = JsMockito.mock( Kevlar.Model );
JsMockito.when( mockModel ).getId().thenReturn( 42 );
- // Try with no trailing slash on the url
- var proxy1 = new Kevlar.persistence.RestProxy( {
- urlRoot : '/testUrl', // note: no trailing slash
- appendId : true
- } );
-
- Y.Assert.areSame( '/testUrl/42', proxy1.buildUrl( mockModel ), "buildUrl() should have returned the url with the id appended" );
-
- // Try with a trailing slash on the url
- var proxy2 = new Kevlar.persistence.RestProxy( {
- urlRoot : '/testUrl/', // note: trailing slash exists
- appendId : true
+ var proxy = new Kevlar.persistence.RestProxy( {
+ urlRoot : '/testUrl/',
+ appendId : false
} );
- Y.Assert.areSame( '/testUrl/42', proxy2.buildUrl( mockModel ), "buildUrl() should have returned the url with the id appended" );
+ Y.Assert.areSame( '/testUrl/', proxy.buildUrl( mockModel, 'create' ), "buildUrl() should have returned the urlRoot when doing a 'create'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'read' ), "buildUrl() should have appended the ID when doing a 'read'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'update' ), "buildUrl() should have appended the ID when doing a 'update'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'delete' ), "buildUrl() should have appended the ID when doing a 'delete'" );
}
}
]
View
2  tests/kevlarTests.min.js
1 addition, 1 deletion not shown
View
33 tests/unit/persistence/RestProxyTest.js
@@ -499,7 +499,7 @@ tests.unit.persistence.add( new Ext.test.TestSuite( {
name: 'Test buildUrl()',
- "buildUrl() should return simply the configured urlRoot, if the 'appendId' config is false" : function() {
+ "buildUrl() should handle a urlRoot without a trailing slash" : function() {
var mockModel = JsMockito.mock( Kevlar.Model );
JsMockito.when( mockModel ).getId().thenReturn( 42 );
@@ -508,29 +508,26 @@ tests.unit.persistence.add( new Ext.test.TestSuite( {
appendId : false
} );
- Y.Assert.areSame( '/testUrl', proxy.buildUrl( mockModel ), "buildUrl() should have simply still returned the url" );
+ Y.Assert.areSame( '/testUrl', proxy.buildUrl( mockModel, 'create' ), "buildUrl() should have returned the urlRoot when doing a 'create'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'read' ), "buildUrl() should have appended the ID when doing a 'read'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'update' ), "buildUrl() should have appended the ID when doing a 'update'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'delete' ), "buildUrl() should have appended the ID when doing a 'delete'" );
},
-
-
- "buildUrl() should return the configured urlRoot with the model's id, if the 'appendId' config is true" : function() {
+
+
+ "buildUrl() should handle a urlRoot with a trailing slash" : function() {
var mockModel = JsMockito.mock( Kevlar.Model );
JsMockito.when( mockModel ).getId().thenReturn( 42 );
- // Try with no trailing slash on the url
- var proxy1 = new Kevlar.persistence.RestProxy( {
- urlRoot : '/testUrl', // note: no trailing slash
- appendId : true
- } );
-
- Y.Assert.areSame( '/testUrl/42', proxy1.buildUrl( mockModel ), "buildUrl() should have returned the url with the id appended" );
-
- // Try with a trailing slash on the url
- var proxy2 = new Kevlar.persistence.RestProxy( {
- urlRoot : '/testUrl/', // note: trailing slash exists
- appendId : true
+ var proxy = new Kevlar.persistence.RestProxy( {
+ urlRoot : '/testUrl/',
+ appendId : false
} );
- Y.Assert.areSame( '/testUrl/42', proxy2.buildUrl( mockModel ), "buildUrl() should have returned the url with the id appended" );
+ Y.Assert.areSame( '/testUrl/', proxy.buildUrl( mockModel, 'create' ), "buildUrl() should have returned the urlRoot when doing a 'create'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'read' ), "buildUrl() should have appended the ID when doing a 'read'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'update' ), "buildUrl() should have appended the ID when doing a 'update'" );
+ Y.Assert.areSame( '/testUrl/42', proxy.buildUrl( mockModel, 'delete' ), "buildUrl() should have appended the ID when doing a 'delete'" );
}
}
]
Please sign in to comment.
Something went wrong with that request. Please try again.