diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dojo/data | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dojo/data')
-rw-r--r-- | lib/dojo/data/ItemFileReadStore.js | 195 | ||||
-rw-r--r-- | lib/dojo/data/ItemFileWriteStore.js | 85 | ||||
-rw-r--r-- | lib/dojo/data/ObjectStore.js | 487 | ||||
-rw-r--r-- | lib/dojo/data/api/Identity.js | 31 | ||||
-rw-r--r-- | lib/dojo/data/api/Notification.js | 33 | ||||
-rw-r--r-- | lib/dojo/data/api/Read.js | 161 | ||||
-rw-r--r-- | lib/dojo/data/api/Request.js | 13 | ||||
-rw-r--r-- | lib/dojo/data/api/Write.js | 41 | ||||
-rw-r--r-- | lib/dojo/data/util/filter.js | 10 | ||||
-rw-r--r-- | lib/dojo/data/util/simpleFetch.js | 26 | ||||
-rw-r--r-- | lib/dojo/data/util/sorter.js | 22 |
11 files changed, 802 insertions, 302 deletions
diff --git a/lib/dojo/data/ItemFileReadStore.js b/lib/dojo/data/ItemFileReadStore.js index 1faed3c7d..9d175ca2c 100644 --- a/lib/dojo/data/ItemFileReadStore.js +++ b/lib/dojo/data/ItemFileReadStore.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -8,11 +8,11 @@ if(!dojo._hasResource["dojo.data.ItemFileReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. dojo._hasResource["dojo.data.ItemFileReadStore"] = true; dojo.provide("dojo.data.ItemFileReadStore"); - dojo.require("dojo.data.util.filter"); dojo.require("dojo.data.util.simpleFetch"); dojo.require("dojo.date.stamp"); + dojo.declare("dojo.data.ItemFileReadStore", null,{ // summary: // The ItemFileReadStore implements the dojo.data.api.Read API and reads @@ -22,7 +22,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ // { name:'Fozzie Bear', wears:['hat', 'tie']}, // { name:'Miss Piggy', pets:'Foo-Foo'} // ]} - // Note that it can also contain an 'identifer' property that specified which attribute on the items + // Note that it can also contain an 'identifer' property that specified which attribute on the items // in the array of items that acts as the unique identifier for that item. // constructor: function(/* Object */ keywordParameters){ @@ -37,7 +37,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ // ... // typeN: function || object // } - // Where if it is a function, it is assumed to be an object constructor that takes the + // Where if it is a function, it is assumed to be an object constructor that takes the // value of _value as the initialization parameters. If it is an object, then it is assumed // to be an object of general form: // { @@ -103,7 +103,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ //all item handles will become invalid and a new fetch must be issued. clearOnClose: false, - //Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url. + //Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url. //Note this does not mean the store calls the server on each fetch, only that the data load has preventCache set as an option. //Added for tracker: #6072 urlPreventCache: false, @@ -111,19 +111,19 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ //Parameter for specifying that it is OK for the xhrGet call to fail silently. failOk: false, - //Parameter to indicate to process data from the url as hierarchical - //(data items can contain other data items in js form). Default is true - //for backwards compatibility. False means only root items are processed - //as items, all child objects outside of type-mapped objects and those in + //Parameter to indicate to process data from the url as hierarchical + //(data items can contain other data items in js form). Default is true + //for backwards compatibility. False means only root items are processed + //as items, all child objects outside of type-mapped objects and those in //specific reference format, are left straight JS data objects. hierarchical: true, _assertIsItem: function(/* item */ item){ // summary: // This function tests whether the item passed in is indeed an item in the store. - // item: + // item: // The item to test for being contained by the store. - if(!this.isItem(item)){ + if(!this.isItem(item)){ throw new Error("dojo.data.ItemFileReadStore: Invalid item argument."); } }, @@ -131,25 +131,25 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ _assertIsAttribute: function(/* attribute-name-string */ attribute){ // summary: // This function tests whether the item passed in is indeed a valid 'attribute' like type for the store. - // attribute: + // attribute: // The attribute to test for being contained by the store. - if(typeof attribute !== "string"){ + if(typeof attribute !== "string"){ throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument."); } }, - getValue: function( /* item */ item, - /* attribute-name-string */ attribute, + getValue: function( /* item */ item, + /* attribute-name-string */ attribute, /* value? */ defaultValue){ - // summary: + // summary: // See dojo.data.api.Read.getValue() var values = this.getValues(item, attribute); return (values.length > 0)?values[0]:defaultValue; // mixed }, - getValues: function(/* item */ item, + getValues: function(/* item */ item, /* attribute-name-string */ attribute){ - // summary: + // summary: // See dojo.data.api.Read.getValues() this._assertIsItem(item); @@ -159,7 +159,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, getAttributes: function(/* item */ item){ - // summary: + // summary: // See dojo.data.api.Read.getAttributes() this._assertIsItem(item); var attributes = []; @@ -174,17 +174,17 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ hasAttribute: function( /* item */ item, /* attribute-name-string */ attribute){ - // summary: + // summary: // See dojo.data.api.Read.hasAttribute() this._assertIsItem(item); this._assertIsAttribute(attribute); return (attribute in item); }, - containsValue: function(/* item */ item, - /* attribute-name-string */ attribute, + containsValue: function(/* item */ item, + /* attribute-name-string */ attribute, /* anything */ value){ - // summary: + // summary: // See dojo.data.api.Read.containsValue() var regexp = undefined; if(typeof value === "string"){ @@ -193,22 +193,22 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ return this._containsValue(item, attribute, value, regexp); //boolean. }, - _containsValue: function( /* item */ item, - /* attribute-name-string */ attribute, + _containsValue: function( /* item */ item, + /* attribute-name-string */ attribute, /* anything */ value, /* RegExp?*/ regexp){ - // summary: + // summary: // Internal function for looking at the values contained by the item. - // description: - // Internal function for looking at the values contained by the item. This + // description: + // Internal function for looking at the values contained by the item. This // function allows for denoting if the comparison should be case sensitive for // strings or not (for handling filtering cases where string case should not matter) - // + // // item: // The data item to examine for attribute values. // attribute: // The attribute to inspect. - // value: + // value: // The value to match. // regexp: // Optional regular expression generated off value if value was of string type to handle wildcarding. @@ -225,7 +225,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, isItem: function(/* anything */ something){ - // summary: + // summary: // See dojo.data.api.Read.isItem() if(something && something[this._storeRefPropName] === this){ if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){ @@ -236,25 +236,25 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, isItemLoaded: function(/* anything */ something){ - // summary: + // summary: // See dojo.data.api.Read.isItemLoaded() return this.isItem(something); //boolean }, loadItem: function(/* object */ keywordArgs){ - // summary: + // summary: // See dojo.data.api.Read.loadItem() this._assertIsItem(keywordArgs.item); }, getFeatures: function(){ - // summary: + // summary: // See dojo.data.api.Read.getFeatures() return this._features; //Object }, getLabel: function(/* item */ item){ - // summary: + // summary: // See dojo.data.api.Read.getLabel() if(this._labelAttr && this.isItem(item)){ return this.getValue(item,this._labelAttr); //String @@ -263,7 +263,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, getLabelAttributes: function(/* item */ item){ - // summary: + // summary: // See dojo.data.api.Read.getLabelAttributes() if(this._labelAttr){ return [this._labelAttr]; //array @@ -271,10 +271,10 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ return null; //null }, - _fetchItems: function( /* Object */ keywordArgs, - /* Function */ findCallback, + _fetchItems: function( /* Object */ keywordArgs, + /* Function */ findCallback, /* Function */ errorCallback){ - // summary: + // summary: // See dojo.data.util.simpleFetch.fetch() var self = this, filter = function(requestArgs, arrayOfItems){ @@ -314,8 +314,8 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ } findCallback(items, requestArgs); }else{ - // We want a copy to pass back in case the parent wishes to sort the array. - // We shouldn't allow resort of the internal list, so that multiple callers + // We want a copy to pass back in case the parent wishes to sort the array. + // We shouldn't allow resort of the internal list, so that multiple callers // can get lists and sort without affecting each other. We also need to // filter out any null values that have been left as a result of deleteItem() // calls in ItemFileWriteStore. @@ -335,11 +335,11 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ //Do a check on the JsonFileUrl and crosscheck it. //If it doesn't match the cross-check, it needs to be updated //This allows for either url or _jsonFileUrl to he changed to - //reset the store load location. Done this way for backwards + //reset the store load location. Done this way for backwards //compatibility. People use _jsonFileUrl (even though officially //private. if(this._jsonFileUrl !== this._ccUrl){ - dojo.deprecated("dojo.data.ItemFileReadStore: ", + dojo.deprecated("dojo.data.ItemFileReadStore: ", "To change the url, set the url property of the store," + " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0"); this._ccUrl = this._jsonFileUrl; @@ -350,21 +350,21 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ } //See if there was any forced reset of data. - if(this.data != null && this._jsonData == null){ + if(this.data != null){ this._jsonData = this.data; this.data = null; } if(this._jsonFileUrl){ //If fetches come in before the loading has finished, but while - //a load is in progress, we have to defer the fetching to be + //a load is in progress, we have to defer the fetching to be //invoked in the callback. if(this._loadInProgress){ this._queuedFetches.push({args: keywordArgs, filter: filter}); }else{ this._loadInProgress = true; var getArgs = { - url: self._jsonFileUrl, + url: self._jsonFileUrl, handleAs: "json-comment-optional", preventCache: this.urlPreventCache, failOk: this.failOk @@ -424,7 +424,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, _handleQueuedFetches: function(){ - // summary: + // summary: // Internal function to execute delayed request in the store. //Execute any deferred fetches now. if(this._queuedFetches.length > 0){ @@ -433,7 +433,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ delayedQuery = fData.args, delayedFilter = fData.filter; if(delayedFilter){ - delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions)); + delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions)); }else{ this.fetchItemByIdentity(delayedQuery); } @@ -443,31 +443,31 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, _getItemsArray: function(/*object?*/queryOptions){ - // summary: + // summary: // Internal function to determine which list of items to search over. // queryOptions: The query options parameter, if any. if(queryOptions && queryOptions.deep){ - return this._arrayOfAllItems; + return this._arrayOfAllItems; } return this._arrayOfTopLevelItems; }, close: function(/*dojo.data.api.Request || keywordArgs || null */ request){ - // summary: + // summary: // See dojo.data.api.Read.close() - if(this.clearOnClose && - this._loadFinished && + if(this.clearOnClose && + this._loadFinished && !this._loadInProgress){ //Reset all internalsback to default state. This will force a reload - //on next fetch. This also checks that the data or url param was set + //on next fetch. This also checks that the data or url param was set //so that the store knows it can get data. Without one of those being set, //the next fetch will trigger an error. - if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) && + if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) && (this.url == "" || this.url == null) ) && this.data == null){ console.debug("dojo.data.ItemFileReadStore: WARNING! Data reload " + - " information has not been provided." + + " information has not been provided." + " Please set 'url' or 'data' to the appropriate value before" + " the next fetch"); } @@ -505,7 +505,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ // | false == valueIsAnItem("Kermit"); // | false == valueIsAnItem(42); // | false == valueIsAnItem(new Date()); - // | false == valueIsAnItem({_type:'Date', _value:'May 14, 1802'}); + // | false == valueIsAnItem({_type:'Date', _value:'1802-05-14'}); // | false == valueIsAnItem({_reference:'Kermit'}); // | true == valueIsAnItem({name:'Kermit', color:'green'}); // | true == valueIsAnItem({iggy:'pop'}); @@ -516,8 +516,8 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ (!dojo.isArray(aValue) || addingArrays) && (!dojo.isFunction(aValue)) && (aValue.constructor == Object || dojo.isArray(aValue)) && - (typeof aValue._reference === "undefined") && - (typeof aValue._type === "undefined") && + (typeof aValue._reference === "undefined") && + (typeof aValue._type === "undefined") && (typeof aValue._value === "undefined") && self.hierarchical ); @@ -567,13 +567,13 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ item[this._rootItemPropName]=true; } - // Step 2: Walk through all the attribute values of all the items, + // Step 2: Walk through all the attribute values of all the items, // and replace single values with arrays. For example, we change this: // { name:'Miss Piggy', pets:'Foo-Foo'} // into this: // { name:['Miss Piggy'], pets:['Foo-Foo']} - // - // We also store the attribute names so we can validate our store + // + // We also store the attribute names so we can validate our store // reference and item id special properties for the O(1) isItem var allAttributeNames = {}, key; @@ -607,9 +607,9 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ this._reverseRefMap += "_"; } - // Step 4: Some data files specify an optional 'identifier', which is - // the name of an attribute that holds the identity of each item. - // If this data file specified an identifier attribute, then build a + // Step 4: Some data files specify an optional 'identifier', which is + // the name of an attribute that holds the identity of each item. + // If this data file specified an identifier attribute, then build a // hash table of items keyed by the identity of the items. var arrayOfValues; @@ -621,7 +621,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ item = this._arrayOfAllItems[i]; arrayOfValues = item[identifier]; var identity = arrayOfValues[0]; - if(!this._itemsByIdentity[identity]){ + if(!Object.hasOwnProperty.call(this._itemsByIdentity, identity)){ this._itemsByIdentity[identity] = item; }else{ if(this._jsonFileUrl){ @@ -635,7 +635,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ this._features['dojo.data.api.Identity'] = Number; } - // Step 5: Walk through all the items, and set each item's properties + // Step 5: Walk through all the items, and set each item's properties // for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true. for(i = 0; i < this._arrayOfAllItems.length; ++i){ item = this._arrayOfAllItems[i]; @@ -649,13 +649,13 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ // We replace item-references with pointers to items. For example, we change: // { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] } // into this: - // { name:['Kermit'], friends:[miss_piggy] } + // { name:['Kermit'], friends:[miss_piggy] } // (where miss_piggy is the object representing the 'Miss Piggy' item). // // We replace type/value pairs with typed-literals. For example, we change: - // { name:['Nelson Mandela'], born:[{_type:'Date', _value:'July 18, 1918'}] } + // { name:['Nelson Mandela'], born:[{_type:'Date', _value:'1918-07-18'}] } // into this: - // { name:['Kermit'], born:(new Date('July 18, 1918')) } + // { name:['Kermit'], born:(new Date(1918, 6, 18)) } // // We also generate the associate map for all items for the O(1) isItem function. for(i = 0; i < this._arrayOfAllItems.length; ++i){ @@ -668,7 +668,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ if(("_type" in value) && ("_value" in value)){ var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber' var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}} - if(!mappingObj){ + if(!mappingObj){ throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'"); }else if(dojo.isFunction(mappingObj)){ arrayOfValues[j] = new mappingObj(value._value); @@ -691,12 +691,12 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ var candidateItem = this._arrayOfAllItems[k], found = true; for(var refKey in referenceDescription){ - if(candidateItem[refKey] != referenceDescription[refKey]){ - found = false; + if(candidateItem[refKey] != referenceDescription[refKey]){ + found = false; } } - if(found){ - arrayOfValues[j] = candidateItem; + if(found){ + arrayOfValues[j] = candidateItem; } } } @@ -707,7 +707,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ } } }else if(this.isItem(value)){ - //It's a child item (not one referenced through _reference). + //It's a child item (not one referenced through _reference). //We need to treat this as a referenced item, so it can be cleaned up //in a write store easily. if(this.referenceIntegrity){ @@ -736,7 +736,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, getIdentity: function(/* item */ item){ - // summary: + // summary: // See dojo.data.api.Identity.getIdentity() var identifier = this._features['dojo.data.api.Identity']; if(identifier === Number){ @@ -751,7 +751,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, fetchItemByIdentity: function(/* Object */ keywordArgs){ - // summary: + // summary: // See dojo.data.api.Identity.fetchItemByIdentity() // Hasn't loaded yet, we have to trigger the load. @@ -762,11 +762,11 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ //Do a check on the JsonFileUrl and crosscheck it. //If it doesn't match the cross-check, it needs to be updated //This allows for either url or _jsonFileUrl to he changed to - //reset the store load location. Done this way for backwards + //reset the store load location. Done this way for backwards //compatibility. People use _jsonFileUrl (even though officially //private. if(this._jsonFileUrl !== this._ccUrl){ - dojo.deprecated("dojo.data.ItemFileReadStore: ", + dojo.deprecated("dojo.data.ItemFileReadStore: ", "To change the url, set the url property of the store," + " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0"); this._ccUrl = this._jsonFileUrl; @@ -789,7 +789,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }else{ this._loadInProgress = true; var getArgs = { - url: self._jsonFileUrl, + url: self._jsonFileUrl, handleAs: "json-comment-optional", preventCache: this.urlPreventCache, failOk: this.failOk @@ -832,7 +832,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ scope = keywordArgs.scope?keywordArgs.scope:dojo.global; keywordArgs.onItem.call(scope, item); } - } + } }else{ // Already loaded. We can just look it up and call back. item = this._getItemByIdentity(keywordArgs.identity); @@ -847,9 +847,10 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ // summary: // Internal function to look an item up by its identity map. var item = null; - if(this._itemsByIdentity){ + if(this._itemsByIdentity && + Object.hasOwnProperty.call(this._itemsByIdentity, identity)){ item = this._itemsByIdentity[identity]; - }else{ + }else if (Object.hasOwnProperty.call(this._arrayOfAllItems, identity)){ item = this._arrayOfAllItems[identity]; } if(item === undefined){ @@ -859,15 +860,15 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, getIdentityAttributes: function(/* item */ item){ - // summary: - // See dojo.data.api.Identity.getIdentifierAttributes() + // summary: + // See dojo.data.api.Identity.getIdentityAttributes() var identifier = this._features['dojo.data.api.Identity']; if(identifier === Number){ // If (identifier === Number) it means getIdentity() just returns // an integer item-number for each item. The dojo.data.api.Identity - // spec says we need to return null if the identity is not composed - // of attributes + // spec says we need to return null if the identity is not composed + // of attributes return null; // null }else{ return [identifier]; // Array @@ -875,18 +876,18 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ }, _forceLoad: function(){ - // summary: + // summary: // Internal function to force a load of the store if it hasn't occurred yet. This is required - // for specific functions to work properly. + // for specific functions to work properly. var self = this; //Do a check on the JsonFileUrl and crosscheck it. //If it doesn't match the cross-check, it needs to be updated //This allows for either url or _jsonFileUrl to he changed to - //reset the store load location. Done this way for backwards + //reset the store load location. Done this way for backwards //compatibility. People use _jsonFileUrl (even though officially //private. if(this._jsonFileUrl !== this._ccUrl){ - dojo.deprecated("dojo.data.ItemFileReadStore: ", + dojo.deprecated("dojo.data.ItemFileReadStore: ", "To change the url, set the url property of the store," + " not _jsonFileUrl. _jsonFileUrl support will be removed in 2.0"); this._ccUrl = this._jsonFileUrl; @@ -897,14 +898,14 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ } //See if there was any forced reset of data. - if(this.data != null && this._jsonData == null){ + if(this.data != null){ this._jsonData = this.data; this.data = null; } if(this._jsonFileUrl){ var getArgs = { - url: this._jsonFileUrl, + url: this._jsonFileUrl, handleAs: "json-comment-optional", preventCache: this.urlPreventCache, failOk: this.failOk, @@ -913,7 +914,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ var getHandler = dojo.xhrGet(getArgs); getHandler.addCallback(function(data){ try{ - //Check to be sure there wasn't another load going on concurrently + //Check to be sure there wasn't another load going on concurrently //So we don't clobber data that comes in on it. If there is a load going on //then do not save this data. It will potentially clobber current data. //We mainly wanted to sync/wait here. @@ -926,7 +927,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ //Okay, we hit an error state we can't recover from. A forced load occurred //while an async load was occurring. Since we cannot block at this point, the best //that can be managed is to throw an error. - throw new Error("dojo.data.ItemFileReadStore: Unable to perform a synchronous load, an async load is in progress."); + throw new Error("dojo.data.ItemFileReadStore: Unable to perform a synchronous load, an async load is in progress."); } }catch(e){ console.log(e); @@ -940,7 +941,7 @@ dojo.declare("dojo.data.ItemFileReadStore", null,{ self._getItemsFromLoadedData(self._jsonData); self._jsonData = null; self._loadFinished = true; - } + } } }); //Mix in the simple fetch implementation to this class. diff --git a/lib/dojo/data/ItemFileWriteStore.js b/lib/dojo/data/ItemFileWriteStore.js index 8782dce05..2c0f3b326 100644 --- a/lib/dojo/data/ItemFileWriteStore.js +++ b/lib/dojo/data/ItemFileWriteStore.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -10,6 +10,7 @@ dojo._hasResource["dojo.data.ItemFileWriteStore"] = true; dojo.provide("dojo.data.ItemFileWriteStore"); dojo.require("dojo.data.ItemFileReadStore"); + dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { constructor: function(/* object */ keywordParameters){ // keywordParameters: {typeMap: object) @@ -20,7 +21,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { // ... // typeN: function || object // } - // Where if it is a function, it is assumed to be an object constructor that takes the + // Where if it is a function, it is assumed to be an object constructor that takes the // value of _value as the initialization parameters. It is serialized assuming object.toString() // serialization. If it is an object, then it is assumed // to be an object of general form: @@ -36,8 +37,8 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { // For keeping track of changes so that we can implement isDirty and revert this._pending = { - _newItems:{}, - _modifiedItems:{}, + _newItems:{}, + _modifiedItems:{}, _deletedItems:{} }; @@ -100,8 +101,8 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { } } - // make sure this identity is not already in use by another item, if identifiers were - // defined in the file. Otherwise it would be the item count, + // make sure this identity is not already in use by another item, if identifiers were + // defined in the file. Otherwise it would be the item count, // which should always be unique in this case. if(this._itemsByIdentity){ this._assert(typeof this._itemsByIdentity[newIdentity] === "undefined"); @@ -110,7 +111,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { this._assert(typeof this._pending._deletedItems[newIdentity] === "undefined"); var newItem = {}; - newItem[this._storeRefPropName] = this; + newItem[this._storeRefPropName] = this; newItem[this._itemNumPropName] = this._arrayOfAllItems.length; if(this._itemsByIdentity){ this._itemsByIdentity[newIdentity] = newItem; @@ -163,14 +164,14 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { // Bummer, the user is trying to do something like // newItem({_S:"foo"}). Unfortunately, our superclass, // ItemFileReadStore, is already using _S in each of our items - // to hold private info. To avoid a naming collision, we - // need to move all our private info to some other property + // to hold private info. To avoid a naming collision, we + // need to move all our private info to some other property // of all the items/objects. So, we need to iterate over all - // the items and do something like: + // the items and do something like: // item.__S = item._S; // item._S = undefined; - // But first we have to make sure the new "__S" variable is - // not in use, which means we have to iterate over all the + // But first we have to make sure the new "__S" variable is + // not in use, which means we have to iterate over all the // items checking for that. throw new Error("encountered bug in ItemFileWriteStore.newItem"); } @@ -207,17 +208,17 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { this._assertIsItem(item); // Remove this item from the _arrayOfAllItems, but leave a null value in place - // of the item, so as not to change the length of the array, so that in newItem() + // of the item, so as not to change the length of the array, so that in newItem() // we can still safely do: newIdentity = this._arrayOfAllItems.length; var indexInArrayOfAllItems = item[this._itemNumPropName]; var identity = this.getIdentity(item); //If we have reference integrity on, we need to do reference cleanup for the deleted item if(this.referenceIntegrity){ - //First scan all the attributes of this items for references and clean them up in the map + //First scan all the attributes of this items for references and clean them up in the map //As this item is going away, no need to track its references anymore. - //Get the attributes list before we generate the backup so it + //Get the attributes list before we generate the backup so it //doesn't pollute the attributes list. var attributes = this.getAttributes(item); @@ -263,7 +264,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { return !(this.isItem(possibleItem) && this.getIdentity(possibleItem) == identity); }, this); //Remove the note of the reference to the item and set the values on the modified attribute. - this._removeReferenceFromMap(item, containingItem, attribute); + this._removeReferenceFromMap(item, containingItem, attribute); if(newValues.length < oldValues.length){ this._setValueOrValues(containingItem, attribute, newValues, true); } @@ -325,11 +326,11 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { var identity = this.getIdentity(item); if(!this._pending._modifiedItems[identity]){ - // Before we actually change the item, we make a copy of it to - // record the original state, so that we'll be able to revert if + // Before we actually change the item, we make a copy of it to + // record the original state, so that we'll be able to revert if // the revert method gets called. If the item has already been // modified then there's no need to do this now, since we already - // have a record of the original state. + // have a record of the original state. var copyOfItemState = {}; for(var key in item){ if((key === this._storeRefPropName) || (key === this._itemNumPropName) || (key === this._rootItemPropName)){ @@ -350,7 +351,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { if(dojo.isArray(newValueOrValues) && newValueOrValues.length === 0){ // If we were passed an empty array as the value, that counts - // as "unsetting" the attribute, so we need to remove this + // as "unsetting" the attribute, so we need to remove this // attribute from the item. success = delete item[attribute]; newValueOrValues = undefined; // used in the onSet Notification call below @@ -374,7 +375,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { // Unfortunately, it's not safe to just do this: // newValueArray = newValues; // Instead, we need to copy the array, which slice() does very nicely. - // This is so that our internal data structure won't + // This is so that our internal data structure won't // get corrupted if the user mucks with the values array *after* // calling setValues(). newValueArray = newValueOrValues.slice(0, newValueOrValues.length); @@ -382,7 +383,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { newValueArray = [newValueOrValues]; } - //We need to handle reference integrity if this is on. + //We need to handle reference integrity if this is on. //In the case of set, we need to see if references were added or removed //and update the reference tracking map accordingly. if(this.referenceIntegrity){ @@ -409,7 +410,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { if(map[id.toString()]){ delete map[id.toString()]; }else{ - this._addReferenceToMap(possibleItem, item, attribute); + this._addReferenceToMap(possibleItem, item, attribute); } } }, this); @@ -439,7 +440,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { // Now we make the dojo.data.api.Notification call if(callOnSet){ - this.onSet(item, attribute, oldValueOrValues, newValueOrValues); + this.onSet(item, attribute, oldValueOrValues, newValueOrValues); } return success; // boolean }, @@ -474,7 +475,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { // Method to remove an reference map entry for an item and attribute. // description: // Method to remove an reference map entry for an item and attribute. This will - // also perform cleanup on the map such that if there are no more references at all to + // also perform cleanup on the map such that if there are no more references at all to // the item, its reference object and entry are removed. // // refItem: @@ -531,7 +532,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { _flatten: function(/* anything */ value){ if(this.isItem(value)){ var item = value; - // Given an item, return an serializable object that provides a + // Given an item, return an serializable object that provides a // reference to the item. // For example, given kermit: // var kermit = store.newItem({id:2, name:"Kermit"}); @@ -562,7 +563,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { }, _getNewFileContentString: function(){ - // summary: + // summary: // Generate a string that can be saved to a file. // The result should look similar to: // http://trac.dojotoolkit.org/browser/dojo/trunk/tests/data/countries.json @@ -603,7 +604,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { }, _isEmpty: function(something){ - // summary: + // summary: // Function to determine if an array or object has no properties or values. // something: // The array or object to examine. @@ -632,7 +633,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { var self = this; var saveCompleteCallback = function(){ self._pending = { - _newItems:{}, + _newItems:{}, _modifiedItems:{}, _deletedItems:{} }; @@ -681,7 +682,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { modifiedItem = this._arrayOfAllItems[identity]; } - // Restore the original item into a full-fledged item again, we want to try to + // Restore the original item into a full-fledged item again, we want to try to // keep the same object instance as if we don't it, causes bugs like #9022. copyOfItemState[this._storeRefPropName] = this; for(key in modifiedItem){ @@ -722,7 +723,7 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { } this._addReferenceToMap(refItem, deletedItem, reference.attr); }, this); - delete deletedItem["backupRefs_" + this._reverseRefMap]; + delete deletedItem["backupRefs_" + this._reverseRefMap]; } } @@ -741,8 +742,8 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { } this._pending = { - _newItems:{}, - _modifiedItems:{}, + _newItems:{}, + _modifiedItems:{}, _deletedItems:{} }; return true; // boolean @@ -753,13 +754,13 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { if(item){ // return true if the item is dirty var identity = this.getIdentity(item); - return new Boolean(this._pending._newItems[identity] || + return new Boolean(this._pending._newItems[identity] || this._pending._modifiedItems[identity] || this._pending._deletedItems[identity]).valueOf(); // boolean }else{ // return true if the store is dirty -- which means return true // if there are any new items, dirty items, or modified items - if(!this._isEmpty(this._pending._newItems) || + if(!this._isEmpty(this._pending._newItems) || !this._isEmpty(this._pending._modifiedItems) || !this._isEmpty(this._pending._deletedItems)){ return true; @@ -770,28 +771,28 @@ dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, { /* dojo.data.api.Notification */ - onSet: function(/* item */ item, - /*attribute-name-string*/ attribute, + onSet: function(/* item */ item, + /*attribute-name-string*/ attribute, /*object | array*/ oldValue, /*object | array*/ newValue){ // summary: See dojo.data.api.Notification.onSet() - // No need to do anything. This method is here just so that the + // No need to do anything. This method is here just so that the // client code can connect observers to it. }, onNew: function(/* item */ newItem, /*object?*/ parentInfo){ // summary: See dojo.data.api.Notification.onNew() - // No need to do anything. This method is here just so that the - // client code can connect observers to it. + // No need to do anything. This method is here just so that the + // client code can connect observers to it. }, onDelete: function(/* item */ deletedItem){ // summary: See dojo.data.api.Notification.onDelete() - // No need to do anything. This method is here just so that the - // client code can connect observers to it. + // No need to do anything. This method is here just so that the + // client code can connect observers to it. }, close: function(/* object? */ request){ diff --git a/lib/dojo/data/ObjectStore.js b/lib/dojo/data/ObjectStore.js new file mode 100644 index 000000000..8ccc4f853 --- /dev/null +++ b/lib/dojo/data/ObjectStore.js @@ -0,0 +1,487 @@ +/* + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. + Available via Academic Free License >= 2.1 OR the modified BSD license. + see: http://dojotoolkit.org/license for details +*/ + + +if(!dojo._hasResource["dojo.data.ObjectStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.data.ObjectStore"] = true; +dojo.provide("dojo.data.ObjectStore"); +dojo.require("dojo.regexp"); + + + +dojo.declare("dojo.data.ObjectStore", null,{ + objectStore: null, + constructor: function(options){ + // summary: + // A Dojo Data implementation that wraps Dojo object stores for backwards + // compatibility. + // 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 + dojo.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 */ + // attribute: /* string */ + return attribute in item; + }, + + containsValue: function(item, attribute, value){ + // summary: + // Checks to see if 'item' has 'value' at 'attribute' + // + // item: /* object */ + // attribute: /* string */ + // value: /* anything */ + return dojo.indexOf(this.getValues(item,attribute),value) > -1; + }, + + + isItem: function(item){ + // summary: + // Checks to see if the argument is an item + // + // item: /* object */ + // attribute: /* string */ + + // 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 */ + + 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). + // + // 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"){ + dojo.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){ + return request && request.abort && request.abort(); + }, + fetch: function(args){ + // summary: + // See dojo.data.api.Read.fetch + // + + args = args || {}; + 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 = dojo.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("^" + dojo.regexp.escapeString(required, "*?").replace(/\*/g, '.*').replace(/\?/g, '.') + "$", args.queryOptions && args.queryOptions.ignoreCase ? "mi" : "m"); + query[i].toString = (function(original){ + return function(){ + return original; + } + })(required); + } + } + } + + var results = this.objectStore.query(query, args); + dojo.when(results.total, function(totalCount){ + dojo.when(results, function(results){ + if(args.onBegin){ + args.onBegin.call(scope, totalCount || results.length, args); + } + if(args.onItem){ + for(var i=0; i<results.length;i++){ + args.onItem.call(scope, results[i], args); + } + } + if(args.onComplete){ + args.onComplete.call(scope, args.onItem ? null : results, args); + } + return results; + }, errorHandler); + }, errorHandler); + function errorHandler(error){ + if(args.onError){ + args.onError.call(scope, error, args); + } + } + args.abort = function(){ + // abort the request + if(results.cancel){ + results.cancel(); + } + }; + args.store = this; + return args; + }, + getFeatures: function(){ + // summary: + // return the store feature set + + return { + "dojo.data.api.Read": !!this.objectStore.get, + "dojo.data.api.Identity": true, + "dojo.data.api.Write": !!this.objectStore.put, + "dojo.data.api.Notification": true + }; + }, + + getLabel: function(/* item */ item){ + // summary: + // See dojo.data.api.Read.getLabel() + if(this.isItem(item)){ + return this.getValue(item,this.labelProperty); //String + } + return undefined; //undefined + }, + + getLabelAttributes: function(/* item */ item){ + // summary: + // See dojo.data.api.Read.getLabelAttributes() + return [this.labelProperty]; //array + }, + + //Identity API Support + + + getIdentity: function(item){ + return item.getId ? item.getId() : item[this.objectStore.idProperty || "id"]; + }, + + getIdentityAttributes: function(item){ + // summary: + // returns the attributes which are used to make up the + // identity of an item. Basically returns this.objectStore.idProperty + + return [this.objectStore.idProperty]; + }, + + fetchItemByIdentity: function(args){ + // summary: + // fetch an item by its identity, by looking in our index of what we have loaded + var item; + dojo.when(this.objectStore.get(args.identity), + function(result){ + item = result; + args.onItem.call(args.scope, result); + }, + function(error){ + args.onError.call(args.scope, error); + } + ); + return item; + }, + + newItem: function(data, parentInfo){ + // summary: + // adds a new item to the store at the specified point. + // Takes two parameters, data, and options. + // + // data: /* object */ + // The data to be added in as an item. + if(parentInfo){ + // get the previous value or any empty array + var values = this.getValue(parentInfo.parent,parentInfo.attribute,[]); + // set the new value + values = values.concat([data]); + data.__parent = values; + this.setValue(parentInfo.parent, parentInfo.attribute, values); + } + this._dirtyObjects.push({object:data, save: true}); + this.onNew(data); + return data; + }, + deleteItem: function(item){ + // summary: + // deletes item and any references to that item from the store. + // + // item: + // item to delete + // + + // If the desire is to delete only one reference, unsetAttribute or + // setValue is the way to go. + this.changing(item, true); + + this.onDelete(item); + }, + setValue: function(item, attribute, value){ + // summary: + // sets 'attribute' on 'item' to 'value' + + var old = item[attribute]; + this.changing(item); + item[attribute]=value; + this.onSet(item,attribute,old,value); + }, + setValues: function(item, attribute, values){ + // summary: + // sets 'attribute' on 'item' to 'value' value + // must be an array. + + + if(!dojo.isArray(values)){ + throw new Error("setValues expects to be passed an Array object as its value"); + } + this.setValue(item,attribute,values); + }, + + unsetAttribute: function(item, attribute){ + // summary: + // unsets 'attribute' on 'item' + + this.changing(item); + var old = item[attribute]; + delete item[attribute]; + this.onSet(item,attribute,old,undefined); + }, + + _dirtyObjects: [], + + changing: function(object,_deleting){ + // summary: + // adds an object to the list of dirty objects. This object + // contains a reference to the object itself as well as a + // cloned and trimmed version of old object for use with + // revert. + object.__isDirty = true; + //if an object is already in the list of dirty objects, don't add it again + //or it will overwrite the premodification data set. + for(var i=0; i<this._dirtyObjects.length; i++){ + var dirty = this._dirtyObjects[i]; + if(object==dirty.object){ + if(_deleting){ + // we are deleting, no object is an indicator of deletiong + dirty.object = false; + if(!this._saveNotNeeded){ + dirty.save = true; + } + } + return; + } + } + var old = object instanceof Array ? [] : {}; + for(i in object){ + if(object.hasOwnProperty(i)){ + old[i] = object[i]; + } + } + this._dirtyObjects.push({object: !_deleting && object, old: old, save: !this._saveNotNeeded}); + }, + + save: function(kwArgs){ + // summary: + // Saves the dirty data using object store provider. See dojo.data.api.Write for API. + // + // kwArgs.global: + // This will cause the save to commit the dirty data for all + // ObjectStores as a single transaction. + // + // kwArgs.revertOnError + // This will cause the changes to be reverted if there is an + // error on the save. By default a revert is executed unless + // a value of false is provide for this parameter. + + kwArgs = kwArgs || {}; + var result, actions = []; + var alreadyRecorded = {}; + var savingObjects = []; + var self; + var dirtyObjects = this._dirtyObjects; + var left = dirtyObjects.length;// this is how many changes are remaining to be received from the server + try{ + dojo.connect(kwArgs,"onError",function(){ + if(kwArgs.revertOnError !== false){ + var postCommitDirtyObjects = dirtyObjects; + dirtyObjects = savingObjects; + var numDirty = 0; // make sure this does't do anything if it is called again + jr.revert(); // revert if there was an error + self._dirtyObjects = postCommitDirtyObjects; + } + else{ + self._dirtyObjects = dirtyObject.concat(savingObjects); + } + }); + if(this.objectStore.transaction){ + var transaction = this.objectStore.transaction(); + } + for(var i = 0; i < dirtyObjects.length; i++){ + var dirty = dirtyObjects[i]; + var object = dirty.object; + var old = dirty.old; + delete object.__isDirty; + if(object){ + result = this.objectStore.put(object, {overwrite: !!old}); + } + else{ + result = this.objectStore.remove(this.getIdentity(old)); + } + savingObjects.push(dirty); + dirtyObjects.splice(i--,1); + dojo.when(result, function(value){ + if(!(--left)){ + if(kwArgs.onComplete){ + kwArgs.onComplete.call(kwArgs.scope, actions); + } + } + },function(value){ + + // on an error we want to revert, first we want to separate any changes that were made since the commit + left = -1; // first make sure that success isn't called + kwArgs.onError.call(kwArgs.scope, value); + }); + + } + if(transaction){ + transaction.commit(); + } + }catch(e){ + kwArgs.onError.call(kwArgs.scope, value); + } + + + }, + + revert: function(kwArgs){ + // summary + // returns any modified data to its original state prior to a save(); + // + var dirtyObjects = this._dirtyObjects; + for(var i = dirtyObjects.length; 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 + if(!item){ + return !!this._dirtyObjects.length; + } + return item.__isDirty; + }, + //Notifcation Support + + onSet: function(){}, + onNew: function(){}, + onDelete: function(){} + } +); + +} diff --git a/lib/dojo/data/api/Identity.js b/lib/dojo/data/api/Identity.js index 7a1caeb53..9d99f3d64 100644 --- a/lib/dojo/data/api/Identity.js +++ b/lib/dojo/data/api/Identity.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -10,6 +10,7 @@ dojo._hasResource["dojo.data.api.Identity"] = true; dojo.provide("dojo.data.api.Identity"); dojo.require("dojo.data.api.Read"); + dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, { // summary: // This is an abstract API that data provider implementations conform to. @@ -17,7 +18,7 @@ dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, { // methods unimplemented. getFeatures: function(){ - // summary: + // summary: // See dojo.data.api.Read.getFeatures() return { 'dojo.data.api.Read': true, @@ -45,16 +46,16 @@ dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, { getIdentityAttributes: function(/* item */ item){ // summary: - // Returns an array of attribute names that are used to generate the identity. + // Returns an array of attribute names that are used to generate the identity. // For most stores, this is a single attribute, but for some complex stores // such as RDB backed stores that use compound (multi-attribute) identifiers // it can be more than one. If the identity is not composed of attributes // on the item, it will return null. This function is intended to identify // the attributes that comprise the identity so that so that during a render - // of all attributes, the UI can hide the the identity information if it + // of all attributes, the UI can hide the the identity information if it // chooses. // item: - // The item from the store from which to obtain the array of public attributes that + // The item from the store from which to obtain the array of public attributes that // compose the identifier, if any. // example: // | var itemId = store.getIdentity(kermit); @@ -67,14 +68,14 @@ dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, { fetchItemByIdentity: function(/* object */ keywordArgs){ // summary: - // Given the identity of an item, this method returns the item that has - // that identity through the onItem callback. Conforming implementations - // should return null if there is no item with the given identity. - // Implementations of fetchItemByIdentity() may sometimes return an item - // from a local cache and may sometimes fetch an item from a remote server, + // Given the identity of an item, this method returns the item that has + // that identity through the onItem callback. Conforming implementations + // should return null if there is no item with the given identity. + // Implementations of fetchItemByIdentity() may sometimes return an item + // from a local cache and may sometimes fetch an item from a remote server, // // keywordArgs: - // An anonymous object that defines the item to locate and callbacks to invoke when the + // An anonymous object that defines the item to locate and callbacks to invoke when the // item has been located and load has completed. The format of the object is as follows: // { // identity: string|object, @@ -84,9 +85,9 @@ dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, { // } // The *identity* parameter. // The identity parameter is the identity of the item you wish to locate and load - // This attribute is required. It should be a string or an object that toString() + // This attribute is required. It should be a string or an object that toString() // can be called on. - // + // // The *onItem* parameter. // Function(item) // The onItem parameter is the callback to invoke when the item has been loaded. It takes only one @@ -98,12 +99,12 @@ dojo.declare("dojo.data.api.Identity", dojo.data.api.Read, { // parameter, the error object // // The *scope* parameter. - // If a scope object is provided, all of the callback functions (onItem, + // If a scope object is provided, all of the callback functions (onItem, // onError, etc) will be invoked in the context of the scope object. // In the body of the callback function, the value of the "this" // keyword will be the scope object. If no scope object is provided, // the callback functions will be called in the context of dojo.global. - // For example, onItem.call(scope, item, request) vs. + // For example, onItem.call(scope, item, request) vs. // onItem.call(dojo.global, item, request) if(!this.isItemLoaded(keywordArgs.item)){ throw new Error('Unimplemented API: dojo.data.api.Identity.fetchItemByIdentity'); diff --git a/lib/dojo/data/api/Notification.js b/lib/dojo/data/api/Notification.js index b1abad797..33daa3010 100644 --- a/lib/dojo/data/api/Notification.js +++ b/lib/dojo/data/api/Notification.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -10,6 +10,7 @@ dojo._hasResource["dojo.data.api.Notification"] = true; dojo.provide("dojo.data.api.Notification"); dojo.require("dojo.data.api.Read"); + dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, { // summary: // This is an abstract API that data provider implementations conform to. @@ -18,12 +19,12 @@ dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, { // // description: // This API defines a set of APIs that all datastores that conform to the - // Notifications API must implement. In general, most stores will implement + // Notifications API must implement. In general, most stores will implement // these APIs as no-op functions for users who wish to monitor them to be able - // to connect to then via dojo.connect(). For non-users of dojo.connect, + // to connect to then via dojo.connect(). For non-users of dojo.connect, // they should be able to just replace the function on the store to obtain // notifications. Both read-only and read-write stores may implement - // this feature. In the case of a read-only store, this feature makes sense if + // this feature. In the case of a read-only store, this feature makes sense if // the store itself does internal polling to a back-end server and periodically updates // its cache of items (deletes, adds, and updates). // @@ -36,7 +37,7 @@ dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, { // | dojo.connect(store, "onSet", onSet); getFeatures: function(){ - // summary: + // summary: // See dojo.data.api.Read.getFeatures() return { 'dojo.data.api.Read': true, @@ -44,16 +45,16 @@ dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, { }; }, - onSet: function(/* item */ item, - /* attribute-name-string */ attribute, + onSet: function(/* item */ item, + /* attribute-name-string */ attribute, /* object | array */ oldValue, /* object | array */ newValue){ // summary: - // This function is called any time an item is modified via setValue, setValues, unsetAttribute, etc. + // This function is called any time an item is modified via setValue, setValues, unsetAttribute, etc. // description: - // This function is called any time an item is modified via setValue, setValues, unsetAttribute, etc. - // Its purpose is to provide a hook point for those who wish to monitor actions on items in the store - // in a simple manner. The general expected usage is to dojo.connect() to the store's + // This function is called any time an item is modified via setValue, setValues, unsetAttribute, etc. + // Its purpose is to provide a hook point for those who wish to monitor actions on items in the store + // in a simple manner. The general expected usage is to dojo.connect() to the store's // implementation and be called after the store function is called. // // item: @@ -62,11 +63,11 @@ dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, { // The attribute being changed represented as a string name. // oldValue: // The old value of the attribute. In the case of single value calls, such as setValue, unsetAttribute, etc, - // this value will be generally be an atomic value of some sort (string, int, etc, object). In the case of + // this value will be generally be an atomic value of some sort (string, int, etc, object). In the case of // multi-valued attributes, it will be an array. // newValue: - // The new value of the attribute. In the case of single value calls, such as setValue, this value will be - // generally be an atomic value of some sort (string, int, etc, object). In the case of multi-valued attributes, + // The new value of the attribute. In the case of single value calls, such as setValue, this value will be + // generally be an atomic value of some sort (string, int, etc, object). In the case of multi-valued attributes, // it will be an array. In the case of unsetAttribute, the new value will be 'undefined'. // // returns: @@ -93,12 +94,12 @@ dojo.declare("dojo.data.api.Notification", dojo.data.api.Read, { // { // item: someItem, //The parent item // attribute: "attribute-name-string", //The attribute the new item was assigned to. - // oldValue: something //Whatever was the previous value for the attribute. + // oldValue: something //Whatever was the previous value for the attribute. // //If it is a single-value attribute only, then this value will be a single value. // //If it was a multi-valued attribute, then this will be an array of all the values minues the new one. // newValue: something //The new value of the attribute. In the case of single value calls, such as setValue, this value will be // //generally be an atomic value of some sort (string, int, etc, object). In the case of multi-valued attributes, - // //it will be an array. + // //it will be an array. // } // // returns: diff --git a/lib/dojo/data/api/Read.js b/lib/dojo/data/api/Read.js index 0a84aa5f9..ff8518cd4 100644 --- a/lib/dojo/data/api/Read.js +++ b/lib/dojo/data/api/Read.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -10,26 +10,27 @@ dojo._hasResource["dojo.data.api.Read"] = true; dojo.provide("dojo.data.api.Read"); dojo.require("dojo.data.api.Request"); + dojo.declare("dojo.data.api.Read", null, { // summary: - // This is an abstract API that data provider implementations conform to. + // This is an abstract API that data provider implementations conform to. // This file defines methods signatures and intentionally leaves all the - // methods unimplemented. For more information on the dojo.data APIs, + // methods unimplemented. For more information on the dojo.data APIs, // please visit: http://www.dojotoolkit.org/node/98 - getValue: function( /* item */ item, - /* attribute-name-string */ attribute, + getValue: function( /* item */ item, + /* attribute-name-string */ attribute, /* value? */ defaultValue){ // summary: // Returns a single attribute value. // Returns defaultValue if and only if *item* does not have a value for *attribute*. // Returns null if and only if null was explicitly set as the attribute value. // Returns undefined if and only if the item does not have a value for the - // given attribute (which is the same as saying the item does not have the attribute). + // given attribute (which is the same as saying the item does not have the attribute). // description: // Saying that an "item x does not have a value for an attribute y" - // is identical to saying that an "item x does not have attribute y". - // It is an oxymoron to say "that attribute is present but has no values" + // is identical to saying that an "item x does not have attribute y". + // It is an oxymoron to say "that attribute is present but has no values" // or "the item has that attribute but does not have any attribute values". // If store.hasAttribute(item, attribute) returns false, then // store.getValue(item, attribute) will return undefined. @@ -112,7 +113,7 @@ dojo.declare("dojo.data.api.Read", null, { }, containsValue: function(/* item */ item, - /* attribute-name-string */ attribute, + /* attribute-name-string */ attribute, /* anything */ value){ // summary: // Returns true if the given *value* is one of the values that getValues() @@ -135,8 +136,8 @@ dojo.declare("dojo.data.api.Read", null, { isItem: function(/* anything */ something){ // summary: - // Returns true if *something* is an item and came from the store instance. - // Returns false if *something* is a literal, an item from another store instance, + // Returns true if *something* is an item and came from the store instance. + // Returns false if *something* is a literal, an item from another store instance, // or is any object other than an item. // // something: @@ -173,9 +174,9 @@ dojo.declare("dojo.data.api.Read", null, { // isItemLoaded() returns true before loadItem() is even called, // then loadItem() need not do any work at all and will not even invoke // the callback handlers. So, before invoking this method, check that - // the item has not already been loaded. + // the item has not already been loaded. // keywordArgs: - // An anonymous object that defines the item to load and callbacks to invoke when the + // An anonymous object that defines the item to load and callbacks to invoke when the // load has completed. The format of the object is as follows: // { // item: object, @@ -198,12 +199,12 @@ dojo.declare("dojo.data.api.Read", null, { // parameter, the error object // // The *scope* parameter. - // If a scope object is provided, all of the callback functions (onItem, + // If a scope object is provided, all of the callback functions (onItem, // onError, etc) will be invoked in the context of the scope object. // In the body of the callback function, the value of the "this" // keyword will be the scope object. If no scope object is provided, // the callback functions will be called in the context of dojo.global(). - // For example, onItem.call(scope, item, request) vs. + // For example, onItem.call(scope, item, request) vs. // onItem.call(dojo.global(), item, request) if(!this.isItemLoaded(keywordArgs.item)){ throw new Error('Unimplemented API: dojo.data.api.Read.loadItem'); @@ -214,25 +215,25 @@ dojo.declare("dojo.data.api.Read", null, { // summary: // Given a query and set of defined options, such as a start and count of items to return, // this method executes the query and makes the results available as data items. - // The format and expectations of stores is that they operate in a generally asynchronous + // The format and expectations of stores is that they operate in a generally asynchronous // manner, therefore callbacks are always used to return items located by the fetch parameters. // // description: // A Request object will always be returned and is returned immediately. - // The basic request is nothing more than the keyword args passed to fetch and - // an additional function attached, abort(). The returned request object may then be used - // to cancel a fetch. All data items returns are passed through the callbacks defined in the + // The basic request is nothing more than the keyword args passed to fetch and + // an additional function attached, abort(). The returned request object may then be used + // to cancel a fetch. All data items returns are passed through the callbacks defined in the // fetch parameters and are not present on the 'request' object. // // This does not mean that custom stores can not add methods and properties to the request object - // returned, only that the API does not require it. For more info about the Request API, + // returned, only that the API does not require it. For more info about the Request API, // see dojo.data.api.Request // // keywordArgs: - // The keywordArgs parameter may either be an instance of + // The keywordArgs parameter may either be an instance of // conforming to dojo.data.api.Request or may be a simple anonymous object // that may contain any of the following: - // { + // { // query: query-object or query-string, // queryOptions: object, // onBegin: Function, @@ -245,10 +246,10 @@ dojo.declare("dojo.data.api.Read", null, { // sort: array // } // All implementations should accept keywordArgs objects with any of - // the 9 standard properties: query, onBegin, onItem, onComplete, onError - // scope, sort, start, and count. Some implementations may accept additional - // properties in the keywordArgs object as valid parameters, such as - // {includeOutliers:true}. + // the 9 standard properties: query, onBegin, onItem, onComplete, onError + // scope, sort, start, and count. Some implementations may accept additional + // properties in the keywordArgs object as valid parameters, such as + // {includeOutliers:true}. // // The *query* parameter. // The query may be optional in some data store implementations. @@ -256,28 +257,28 @@ dojo.declare("dojo.data.api.Read", null, { // of the query itself -- each different data store implementation // may have its own notion of what a query should look like. // However, as of dojo 0.9, 1.0, and 1.1, all the provided datastores in dojo.data - // and dojox.data support an object structure query, where the object is a set of + // and dojox.data support an object structure query, where the object is a set of // name/value parameters such as { attrFoo: valueBar, attrFoo1: valueBar1}. Most of the - // dijit widgets, such as ComboBox assume this to be the case when working with a datastore - // when they dynamically update the query. Therefore, for maximum compatibility with dijit + // dijit widgets, such as ComboBox assume this to be the case when working with a datastore + // when they dynamically update the query. Therefore, for maximum compatibility with dijit // widgets the recommended query parameter is a key/value object. That does not mean that the - // the datastore may not take alternative query forms, such as a simple string, a Date, a number, - // or a mix of such. Ultimately, The dojo.data.api.Read API is agnostic about what the query - // format. - // Further note: In general for query objects that accept strings as attribute - // value matches, the store should also support basic filtering capability, such as * + // the datastore may not take alternative query forms, such as a simple string, a Date, a number, + // or a mix of such. Ultimately, The dojo.data.api.Read API is agnostic about what the query + // format. + // Further note: In general for query objects that accept strings as attribute + // value matches, the store should also support basic filtering capability, such as * // (match any character) and ? (match single character). An example query that is a query object - // would be like: { attrFoo: "value*"}. Which generally means match all items where they have + // would be like: { attrFoo: "value*"}. Which generally means match all items where they have // an attribute named attrFoo, with a value that starts with 'value'. // // The *queryOptions* parameter // The queryOptions parameter is an optional parameter used to specify optiosn that may modify // the query in some fashion, such as doing a case insensitive search, or doing a deep search - // where all items in a hierarchical representation of data are scanned instead of just the root + // where all items in a hierarchical representation of data are scanned instead of just the root // items. It currently defines two options that all datastores should attempt to honor if possible: // { // ignoreCase: boolean, //Whether or not the query should match case sensitively or not. Default behaviour is false. - // deep: boolean //Whether or not a fetch should do a deep search of items and all child + // deep: boolean //Whether or not a fetch should do a deep search of items and all child // //items instead of just root-level items in a datastore. Default is false. // } // @@ -287,14 +288,14 @@ dojo.declare("dojo.data.api.Read", null, { // will be called just once, before the first onItem callback is called. // The onBegin callback function will be passed two arguments, the // the total number of items identified and the Request object. If the total number is - // unknown, then size will be -1. Note that size is not necessarily the size of the - // collection of items returned from the query, as the request may have specified to return only a + // unknown, then size will be -1. Note that size is not necessarily the size of the + // collection of items returned from the query, as the request may have specified to return only a // subset of the total set of items through the use of the start and count parameters. // // The *onItem* parameter. // function(item, request); // If an onItem callback function is provided, the callback function - // will be called as each item in the result is received. The callback + // will be called as each item in the result is received. The callback // function will be passed two arguments: the item itself, and the // Request object. // @@ -304,12 +305,12 @@ dojo.declare("dojo.data.api.Read", null, { // If an onComplete callback function is provided, the callback function // will be called just once, after the last onItem callback is called. // Note that if the onItem callback is not present, then onComplete will be passed - // an array containing all items which matched the query and the request object. - // If the onItem callback is present, then onComplete is called as: + // an array containing all items which matched the query and the request object. + // If the onItem callback is present, then onComplete is called as: // onComplete(null, request). // // The *onError* parameter. - // function(errorData, request); + // function(errorData, request); // If an onError callback function is provided, the callback function // will be called if there is any sort of error while attempting to // execute the query. @@ -317,29 +318,29 @@ dojo.declare("dojo.data.api.Read", null, { // an Error object and the Request object. // // The *scope* parameter. - // If a scope object is provided, all of the callback functions (onItem, + // If a scope object is provided, all of the callback functions (onItem, // onComplete, onError, etc) will be invoked in the context of the scope // object. In the body of the callback function, the value of the "this" // keyword will be the scope object. If no scope object is provided, - // the callback functions will be called in the context of dojo.global(). - // For example, onItem.call(scope, item, request) vs. + // the callback functions will be called in the context of dojo.global(). + // For example, onItem.call(scope, item, request) vs. // onItem.call(dojo.global(), item, request) // // The *start* parameter. - // If a start parameter is specified, this is a indication to the datastore to + // If a start parameter is specified, this is a indication to the datastore to // only start returning items once the start number of items have been located and // skipped. When this parameter is paired withh 'count', the store should be able - // to page across queries with millions of hits by only returning subsets of the + // to page across queries with millions of hits by only returning subsets of the // hits for each query // // The *count* parameter. - // If a count parameter is specified, this is a indication to the datastore to - // only return up to that many items. This allows a fetch call that may have - // millions of item matches to be paired down to something reasonable. + // If a count parameter is specified, this is a indication to the datastore to + // only return up to that many items. This allows a fetch call that may have + // millions of item matches to be paired down to something reasonable. // // The *sort* parameter. - // If a sort parameter is specified, this is a indication to the datastore to - // sort the items in some manner before returning the items. The array is an array of + // If a sort parameter is specified, this is a indication to the datastore to + // sort the items in some manner before returning the items. The array is an array of // javascript objects that must conform to the following format to be applied to the // fetching of items: // { @@ -347,18 +348,18 @@ dojo.declare("dojo.data.api.Read", null, { // descending: true|false; // Optional. Default is false. // } // Note that when comparing attributes, if an item contains no value for the attribute - // (undefined), then it the default ascending sort logic should push it to the bottom + // (undefined), then it the default ascending sort logic should push it to the bottom // of the list. In the descending order case, it such items should appear at the top of the list. - // + // // returns: // The fetch() method will return a javascript object conforming to the API // defined in dojo.data.api.Request. In general, it will be the keywordArgs // object returned with the required functions in Request.js attached. // Its general purpose is to provide a convenient way for a caller to abort an - // ongoing fetch. - // + // ongoing fetch. + // // The Request object may also have additional properties when it is returned - // such as request.store property, which is a pointer to the datastore object that + // such as request.store property, which is a pointer to the datastore object that // fetch() is a method of. // // exceptions: @@ -373,7 +374,7 @@ dojo.declare("dojo.data.api.Read", null, { // | var request = store.fetch(onComplete: showEverything); // example: // Fetch only 10 books that match the query 'all books', starting at the fifth book found during the search. - // This demonstrates how paging can be done for specific queries. + // This demonstrates how paging can be done for specific queries. // | var request = store.fetch({query:"all books", start: 4, count: 10, onComplete: showBooks}); // example: // Fetch all items that match the query, calling 'callback' each time an item is located. @@ -412,21 +413,21 @@ dojo.declare("dojo.data.api.Read", null, { // and then when the user presses the "Next Page" button... // | fetchArgs.start += 20; // | store.fetch(fetchArgs); // get the next 20 items - var request = null; + var request = null; throw new Error('Unimplemented API: dojo.data.api.Read.fetch'); return request; // an object conforming to the dojo.data.api.Request API }, getFeatures: function(){ // summary: - // The getFeatures() method returns an simple keyword values object - // that specifies what interface features the datastore implements. - // A simple CsvStore may be read-only, and the only feature it + // The getFeatures() method returns an simple keyword values object + // that specifies what interface features the datastore implements. + // A simple CsvStore may be read-only, and the only feature it // implements will be the 'dojo.data.api.Read' interface, so the // getFeatures() method will return an object like this one: // {'dojo.data.api.Read': true}. // A more sophisticated datastore might implement a variety of - // interface features, like 'dojo.data.api.Read', 'dojo.data.api.Write', + // interface features, like 'dojo.data.api.Read', 'dojo.data.api.Write', // 'dojo.data.api.Identity', and 'dojo.data.api.Attribution'. return { 'dojo.data.api.Read': true @@ -435,14 +436,14 @@ dojo.declare("dojo.data.api.Read", null, { close: function(/*dojo.data.api.Request || keywordArgs || null */ request){ // summary: - // The close() method is intended for instructing the store to 'close' out + // The close() method is intended for instructing the store to 'close' out // any information associated with a particular request. // // description: - // The close() method is intended for instructing the store to 'close' out + // The close() method is intended for instructing the store to 'close' out // any information associated with a particular request. In general, this API - // expects to recieve as a parameter a request object returned from a fetch. - // It will then close out anything associated with that request, such as + // expects to recieve as a parameter a request object returned from a fetch. + // It will then close out anything associated with that request, such as // clearing any internal datastore caches and closing any 'open' connections. // For some store implementations, this call may be a no-op. // @@ -450,7 +451,7 @@ dojo.declare("dojo.data.api.Read", null, { // An instance of a request for the store to use to identify what to close out. // If no request is passed, then the store should clear all internal caches (if any) // and close out all 'open' connections. It does not render the store unusable from - // there on, it merely cleans out any current data and resets the store to initial + // there on, it merely cleans out any current data and resets the store to initial // state. // // example: @@ -463,7 +464,7 @@ dojo.declare("dojo.data.api.Read", null, { getLabel: function(/* item */ item){ // summary: // Method to inspect the item and return a user-readable 'label' for the item - // that provides a general/adequate description of what the item is. + // that provides a general/adequate description of what the item is. // // description: // Method to inspect the item and return a user-readable 'label' for the item @@ -471,17 +472,17 @@ dojo.declare("dojo.data.api.Read", null, { // most labels will be a specific attribute value or collection of the attribute // values that combine to label the item in some manner. For example for an item // that represents a person it may return the label as: "firstname lastlame" where - // the firstname and lastname are attributes on the item. If the store is unable + // the firstname and lastname are attributes on the item. If the store is unable // to determine an adequate human readable label, it should return undefined. Users that wish - // to customize how a store instance labels items should replace the getLabel() function on - // their instance of the store, or extend the store and replace the function in + // to customize how a store instance labels items should replace the getLabel() function on + // their instance of the store, or extend the store and replace the function in // the extension class. // // item: // The item to return the label for. // - // returns: - // A user-readable string representing the item or undefined if no user-readable label can + // returns: + // A user-readable string representing the item or undefined if no user-readable label can // be generated. throw new Error('Unimplemented API: dojo.data.api.Read.getLabel'); return undefined; @@ -489,21 +490,21 @@ dojo.declare("dojo.data.api.Read", null, { getLabelAttributes: function(/* item */ item){ // summary: - // Method to inspect the item and return an array of what attributes of the item were used + // Method to inspect the item and return an array of what attributes of the item were used // to generate its label, if any. // // description: - // Method to inspect the item and return an array of what attributes of the item were used + // Method to inspect the item and return an array of what attributes of the item were used // to generate its label, if any. This function is to assist UI developers in knowing what // attributes can be ignored out of the attributes an item has when displaying it, in cases - // where the UI is using the label as an overall identifer should they wish to hide + // where the UI is using the label as an overall identifer should they wish to hide // redundant information. // // item: // The item to return the list of label attributes for. // - // returns: - // An array of attribute names that were used to generate the label, or null if public attributes + // returns: + // An array of attribute names that were used to generate the label, or null if public attributes // were not used to generate the label. throw new Error('Unimplemented API: dojo.data.api.Read.getLabelAttributes'); return null; diff --git a/lib/dojo/data/api/Request.js b/lib/dojo/data/api/Request.js index d613c7b11..5c94cb5e0 100644 --- a/lib/dojo/data/api/Request.js +++ b/lib/dojo/data/api/Request.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -9,16 +9,17 @@ if(!dojo._hasResource["dojo.data.api.Request"]){ //_hasResource checks added by dojo._hasResource["dojo.data.api.Request"] = true; dojo.provide("dojo.data.api.Request"); + dojo.declare("dojo.data.api.Request", null, { // summary: // This class defines out the semantics of what a 'Request' object looks like // when returned from a fetch() method. In general, a request object is - // nothing more than the original keywordArgs from fetch with an abort function - // attached to it to allow users to abort a particular request if they so choose. + // nothing more than the original keywordArgs from fetch with an abort function + // attached to it to allow users to abort a particular request if they so choose. // No other functions are required on a general Request object return. That does not // inhibit other store implementations from adding extentions to it, of course. // - // This is an abstract API that data provider implementations conform to. + // This is an abstract API that data provider implementations conform to. // This file defines methods signatures and intentionally leaves all the // methods unimplemented. // @@ -26,10 +27,10 @@ dojo.declare("dojo.data.api.Request", null, { abort: function(){ // summary: - // This function is a hook point for stores to provide as a way for + // This function is a hook point for stores to provide as a way for // a fetch to be halted mid-processing. // description: - // This function is a hook point for stores to provide as a way for + // This function is a hook point for stores to provide as a way for // a fetch to be halted mid-processing. For more details on the fetch() api, // please see dojo.data.api.Read.fetch(). throw new Error('Unimplemented API: dojo.data.api.Request.abort'); diff --git a/lib/dojo/data/api/Write.js b/lib/dojo/data/api/Write.js index 3fd0b1af0..08779180b 100644 --- a/lib/dojo/data/api/Write.js +++ b/lib/dojo/data/api/Write.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -10,14 +10,15 @@ dojo._hasResource["dojo.data.api.Write"] = true; dojo.provide("dojo.data.api.Write"); dojo.require("dojo.data.api.Read"); + dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // summary: - // This is an abstract API that data provider implementations conform to. + // This is an abstract API that data provider implementations conform to. // This file defines function signatures and intentionally leaves all the // functionss unimplemented. getFeatures: function(){ - // summary: + // summary: // See dojo.data.api.Read.getFeatures() return { 'dojo.data.api.Read': true, @@ -31,16 +32,16 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // item based on the *keywordArgs* provided. In general, the attribute // names in the keywords become the attributes in the new item and as for // the attribute values in keywordArgs, they become the values of the attributes - // in the new item. In addition, for stores that support hierarchical item + // in the new item. In addition, for stores that support hierarchical item // creation, an optional second parameter is accepted that defines what item is the parent // of the new item and what attribute of that item should the new item be assigned to. // In general, this will assume that the attribute targetted is multi-valued and a new item - // is appended onto the list of values for that attribute. + // is appended onto the list of values for that attribute. // // keywordArgs: // A javascript object defining the initial content of the item as a set of JavaScript 'property name: value' pairs. // parentInfo: - // An optional javascript object defining what item is the parent of this item (in a hierarchical store. Not all stores do hierarchical items), + // An optional javascript object defining what item is the parent of this item (in a hierarchical store. Not all stores do hierarchical items), // and what attribute of that parent to assign the new item to. If this is present, and the attribute specified // is a multi-valued attribute, it will append this item into the array of values for that attribute. The structure // of the object is as follows: @@ -51,7 +52,7 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // // exceptions: // Throws an exception if *keywordArgs* is a string or a number or - // anything other than a simple anonymous object. + // anything other than a simple anonymous object. // Throws an exception if the item in parentInfo is not an item from the store // or if the attribute isn't an attribute name string. // example: @@ -66,11 +67,11 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // summary: // Deletes an item from the store. // - // item: + // item: // The item to delete. // // exceptions: - // Throws an exception if the argument *item* is not an item + // Throws an exception if the argument *item* is not an item // (if store.isItem(item) returns false). // example: // | var success = store.deleteItem(kermit); @@ -78,7 +79,7 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { return false; // boolean }, - setValue: function( /* item */ item, + setValue: function( /* item */ item, /* string */ attribute, /* almost anything */ value){ // summary: @@ -103,7 +104,7 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { }, setValues: function(/* item */ item, - /* string */ attribute, + /* string */ attribute, /* array */ values){ // summary: // Adds each value in the *values* array as a value of the given @@ -130,7 +131,7 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { return false; // boolean }, - unsetAttribute: function( /* item */ item, + unsetAttribute: function( /* item */ item, /* string */ attribute){ // summary: // Deletes all the values of an attribute on an item. @@ -154,9 +155,9 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // summary: // Saves to the server all the changes that have been made locally. // The save operation may take some time and is generally performed - // in an asynchronous fashion. The outcome of the save action is + // in an asynchronous fashion. The outcome of the save action is // is passed into the set of supported callbacks for the save. - // + // // keywordArgs: // { // onComplete: function @@ -172,7 +173,7 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // are generally passed to the onComplete. // // The *onError* parameter. - // function(errorData); + // function(errorData); // // If an onError callback function is provided, the callback function // will be called if there is any sort of error while attempting to @@ -184,12 +185,12 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { // onComplete, onError, etc) will be invoked in the context of the scope // object. In the body of the callback function, the value of the "this" // keyword will be the scope object. If no scope object is provided, - // the callback functions will be called in the context of dojo.global. - // For example, onComplete.call(scope) vs. + // the callback functions will be called in the context of dojo.global. + // For example, onComplete.call(scope) vs. // onComplete.call(dojo.global) // // returns: - // Nothing. Since the saves are generally asynchronous, there is + // Nothing. Since the saves are generally asynchronous, there is // no need to return anything. All results are passed via callbacks. // example: // | store.save({onComplete: onSave}); @@ -211,8 +212,8 @@ dojo.declare("dojo.data.api.Write", dojo.data.api.Read, { isDirty: function(/* item? */ item){ // summary: - // Given an item, isDirty() returns true if the item has been modified - // since the last save(). If isDirty() is called with no *item* argument, + // Given an item, isDirty() returns true if the item has been modified + // since the last save(). If isDirty() is called with no *item* argument, // then this function returns true if any item has been modified since // the last save(). // diff --git a/lib/dojo/data/util/filter.js b/lib/dojo/data/util/filter.js index d23e63ade..909cc49bc 100644 --- a/lib/dojo/data/util/filter.js +++ b/lib/dojo/data/util/filter.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -9,12 +9,14 @@ if(!dojo._hasResource["dojo.data.util.filter"]){ //_hasResource checks added by dojo._hasResource["dojo.data.util.filter"] = true; dojo.provide("dojo.data.util.filter"); +dojo.getObject("data.util.filter", true, dojo); + dojo.data.util.filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){ - // summary: + // summary: // Helper function to convert a simple pattern to a regular expression for matching. // description: // Returns a regular expression object that conforms to the defined conversion rules. - // For example: + // For example: // ca* -> /^ca.*$/ // *ca* -> /^.*ca.*$/ // *c\*a* -> /^.*c\*a.*$/ @@ -26,7 +28,7 @@ dojo.data.util.filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ // * Means match anything, so ca* means match anything starting with ca // ? Means match single character. So, b?b will match to bob and bab, and so on. // \ is an escape character. So for example, \* means do not treat * as a match, but literal character *. - // To use a \ as a character in the string, it must be escaped. So in the pattern it should be + // To use a \ as a character in the string, it must be escaped. So in the pattern it should be // represented by \\ to be treated as an ordinary \ character instead of an escape. // // ignoreCase: diff --git a/lib/dojo/data/util/simpleFetch.js b/lib/dojo/data/util/simpleFetch.js index 0bfb19ec3..b3f859b48 100644 --- a/lib/dojo/data/util/simpleFetch.js +++ b/lib/dojo/data/util/simpleFetch.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -10,30 +10,32 @@ dojo._hasResource["dojo.data.util.simpleFetch"] = true; dojo.provide("dojo.data.util.simpleFetch"); dojo.require("dojo.data.util.sorter"); +dojo.getObject("data.util.simpleFetch", true, dojo); + dojo.data.util.simpleFetch.fetch = function(/* Object? */ request){ // summary: // The simpleFetch mixin is designed to serve as a set of function(s) that can - // be mixed into other datastore implementations to accelerate their development. - // The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems() + // be mixed into other datastore implementations to accelerate their development. + // The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems() // call by returning an array of all the found items that matched the query. The simpleFetch mixin // is not designed to work for datastores that respond to a fetch() call by incrementally // loading items, or sequentially loading partial batches of the result - // set. For datastores that mixin simpleFetch, simpleFetch + // set. For datastores that mixin simpleFetch, simpleFetch // implements a fetch method that automatically handles eight of the fetch() // arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope // The class mixing in simpleFetch should not implement fetch(), - // but should instead implement a _fetchItems() method. The _fetchItems() - // method takes three arguments, the keywordArgs object that was passed + // but should instead implement a _fetchItems() method. The _fetchItems() + // method takes three arguments, the keywordArgs object that was passed // to fetch(), a callback function to be called when the result array is // available, and an error callback to be called if something goes wrong. // The _fetchItems() method should ignore any keywordArgs parameters for - // start, count, onBegin, onItem, onComplete, onError, sort, and scope. + // start, count, onBegin, onItem, onComplete, onError, sort, and scope. // The _fetchItems() method needs to correctly handle any other keywordArgs - // parameters, including the query parameter and any optional parameters - // (such as includeChildren). The _fetchItems() method should create an array of - // result items and pass it to the fetchHandler along with the original request object - // -- or, the _fetchItems() method may, if it wants to, create an new request object - // with other specifics about the request that are specific to the datastore and pass + // parameters, including the query parameter and any optional parameters + // (such as includeChildren). The _fetchItems() method should create an array of + // result items and pass it to the fetchHandler along with the original request object + // -- or, the _fetchItems() method may, if it wants to, create an new request object + // with other specifics about the request that are specific to the datastore and pass // that as the request object to the handler. // // For more information on this specific function, see dojo.data.api.Read.fetch() diff --git a/lib/dojo/data/util/sorter.js b/lib/dojo/data/util/sorter.js index c0261c848..539d3ca02 100644 --- a/lib/dojo/data/util/sorter.js +++ b/lib/dojo/data/util/sorter.js @@ -1,5 +1,5 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ @@ -9,11 +9,13 @@ if(!dojo._hasResource["dojo.data.util.sorter"]){ //_hasResource checks added by dojo._hasResource["dojo.data.util.sorter"] = true; dojo.provide("dojo.data.util.sorter"); -dojo.data.util.sorter.basicComparator = function( /*anything*/ a, +dojo.getObject("data.util.sorter", true, dojo); + +dojo.data.util.sorter.basicComparator = function( /*anything*/ a, /*anything*/ b){ - // summary: + // summary: // Basic comparision function that compares if an item is greater or less than another item - // description: + // description: // returns 1 if a > b, -1 if a < b, 0 if equal. // 'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list. // And compared to each other, null is equivalent to undefined. @@ -30,18 +32,18 @@ dojo.data.util.sorter.basicComparator = function( /*anything*/ a, b = undefined; } if(a == b){ - r = 0; + r = 0; }else if(a > b || a == null){ - r = 1; + r = 1; } return r; //int {-1,0,1} }; dojo.data.util.sorter.createSortFunction = function( /* attributes array */sortSpec, /*dojo.data.core.Read*/ store){ - // summary: + // summary: // Helper function to generate the sorting function based off the list of sort attributes. - // description: + // description: // The sort function creation will look for a property on the store called 'comparatorMap'. If it exists // it will look in the mapping for comparisons function for the attributes. If one is found, it will // use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates. @@ -83,7 +85,7 @@ dojo.data.util.sorter.createSortFunction = function( /* attributes array */sortS } comp = map[attr] || bc; } - sortFunctions.push(createSortFunction(attr, + sortFunctions.push(createSortFunction(attr, dir, comp, store)); } } @@ -95,7 +97,7 @@ dojo.data.util.sorter.createSortFunction = function( /* attributes array */sortS return ret;//int } } - return 0; //int + return 0; //int }; // Function }; |