summaryrefslogtreecommitdiff
path: root/lib/dojo/data
diff options
context:
space:
mode:
authorAndrew Dolgov <[email protected]>2011-11-08 20:40:44 +0400
committerAndrew Dolgov <[email protected]>2011-11-08 20:40:44 +0400
commit81bea17aefb26859f825b9293c7c99192874806e (patch)
treefb244408ca271affa2899adb634788802c9a89d8 /lib/dojo/data
parent870a70e109ac9e80a88047044530de53d0404ec7 (diff)
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dojo/data')
-rw-r--r--lib/dojo/data/ItemFileReadStore.js195
-rw-r--r--lib/dojo/data/ItemFileWriteStore.js85
-rw-r--r--lib/dojo/data/ObjectStore.js487
-rw-r--r--lib/dojo/data/api/Identity.js31
-rw-r--r--lib/dojo/data/api/Notification.js33
-rw-r--r--lib/dojo/data/api/Read.js161
-rw-r--r--lib/dojo/data/api/Request.js13
-rw-r--r--lib/dojo/data/api/Write.js41
-rw-r--r--lib/dojo/data/util/filter.js10
-rw-r--r--lib/dojo/data/util/simpleFetch.js26
-rw-r--r--lib/dojo/data/util/sorter.js22
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
};