define("dojo/data/ObjectStore", ["../_base/lang", "../Evented", "../_base/declare", "../_base/Deferred", "../_base/array", "../_base/connect", "../regexp" ], function(lang, Evented, declare, Deferred, array, connect, regexp){ // module: // dojo/data/ObjectStore function convertRegex(character){ return character == '*' ? '.*' : character == '?' ? '.' : character; } return declare("dojo.data.ObjectStore", [Evented],{ // summary: // A Dojo Data implementation that wraps Dojo object stores for backwards // compatibility. objectStore: null, constructor: function(options){ // options: // The configuration information to pass into the data store. // // - options.objectStore: // // The object store to use as the source provider for this data store this._dirtyObjects = []; if(options.labelAttribute){ // accept the old labelAttribute to make it easier to switch from old data stores options.labelProperty = options.labelAttribute; } lang.mixin(this, options); }, labelProperty: "label", getValue: function(/*Object*/ item, /*String*/property, /*value?*/defaultValue){ // summary: // Gets the value of an item's 'property' // item: // The item to get the value from // property: // property to look up value for // defaultValue: // the default value return typeof item.get === "function" ? item.get(property) : property in item ? item[property] : defaultValue; }, getValues: function(item, property){ // summary: // Gets the value of an item's 'property' and returns // it. If this value is an array it is just returned, // if not, the value is added to an array and that is returned. // item: Object // property: String // property to look up value for var val = this.getValue(item,property); return val instanceof Array ? val : val === undefined ? [] : [val]; }, getAttributes: function(item){ // summary: // Gets the available attributes of an item's 'property' and returns // it as an array. // item: Object var res = []; for(var i in item){ if(item.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_')){ res.push(i); } } return res; }, hasAttribute: function(item,attribute){ // summary: // Checks to see if item has attribute // item: Object // The item to check // attribute: String // The attribute to check return attribute in item; }, containsValue: function(item, attribute, value){ // summary: // Checks to see if 'item' has 'value' at 'attribute' // item: Object // The item to check // attribute: String // The attribute to check // value: Anything // The value to look for return array.indexOf(this.getValues(item,attribute),value) > -1; }, isItem: function(item){ // summary: // Checks to see if the argument is an item // item: Object // The item to check // we have no way of determining if it belongs, we just have object returned from // service queries return (typeof item == 'object') && item && !(item instanceof Date); }, isItemLoaded: function(item){ // summary: // Checks to see if the item is loaded. // item: Object // The item to check return item && typeof item.load !== "function"; }, loadItem: function(args){ // summary: // Loads an item and calls the callback handler. Note, that this will call the callback // handler even if the item is loaded. Consequently, you can use loadItem to ensure // that an item is loaded is situations when the item may or may not be loaded yet. // If you access a value directly through property access, you can use this to load // a lazy value as well (doesn't need to be an item). // args: Object // See dojo/data/api/Read.fetch() // example: // | store.loadItem({ // | item: item, // this item may or may not be loaded // | onItem: function(item){ // | // do something with the item // | } // | }); var item; if(typeof args.item.load === "function"){ Deferred.when(args.item.load(), function(result){ item = result; // in synchronous mode this can allow loadItem to return the value var func = result instanceof Error ? args.onError : args.onItem; if(func){ func.call(args.scope, result); } }); }else if(args.onItem){ // even if it is already loaded, we will use call the callback, this makes it easier to // use when it is not known if the item is loaded (you can always safely call loadItem). args.onItem.call(args.scope, args.item); } return item; }, close: function(request){ // summary: // See dojo/data/api/Read.close() return request && request.abort && request.abort(); }, fetch: function(args){ // summary: // See dojo/data/api/Read.fetch() args = lang.delegate(args, args && args.queryOptions); var self = this; var scope = args.scope || self; var query = args.query; if(typeof query == "object"){ // can be null, but that is ignore by for-in query = lang.delegate(query); // don't modify the original for(var i in query){ // find any strings and convert them to regular expressions for wildcard support var required = query[i]; if(typeof required == "string"){ query[i] = RegExp("^" + regexp.escapeString(required, "*?\\").replace(/\\.|\*|\?/g, convertRegex) + "$", args.ignoreCase ? "mi" : "m"); query[i].toString = (function(original){ return function(){ return original; }; })(required); } } } var results = this.objectStore.query(query, args); Deferred.when(results.total, function(totalCount){ Deferred.when(results, function(results){ if(args.onBegin){ args.onBegin.call(scope, totalCount || results.length, args); } if(args.onItem){ for(var i=0; i 0;){ i--; var dirty = dirtyObjects[i]; var object = dirty.object; var old = dirty.old; if(object && old){ // changed for(var j in old){ if(old.hasOwnProperty(j) && object[j] !== old[j]){ this.onSet(object, j, object[j], old[j]); object[j] = old[j]; } } for(j in object){ if(!old.hasOwnProperty(j)){ this.onSet(object, j, object[j]); delete object[j]; } } }else if(!old){ // was an addition, remove it this.onDelete(object); }else{ // was a deletion, we will add it back this.onNew(old); } delete (object || old).__isDirty; dirtyObjects.splice(i, 1); } }, isDirty: function(item){ // summary: // returns true if the item is marked as dirty or true if there are any dirty items // item: Object // The item to check if(!item){ return !!this._dirtyObjects.length; } return item.__isDirty; }, // Notification Support onSet: function(){ // summary: // See dojo/data/api/Notification.onSet() }, onNew: function(){ // summary: // See dojo/data/api/Notification.onNew() }, onDelete: function(){ // summary: // See dojo/data/api/Notification.onDelete() }, // an extra to get result sets onFetch: function(results){ // summary: // Called when a fetch occurs } } ); });