From 1354d17270961fff662d40f90521223f8fd0d73b Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 14 Aug 2012 18:59:10 +0400 Subject: update dojo to 1.7.3 --- lib/dojo/data/ItemFileReadStore.js | 946 +------------------------------------ 1 file changed, 2 insertions(+), 944 deletions(-) (limited to 'lib/dojo/data/ItemFileReadStore.js') diff --git a/lib/dojo/data/ItemFileReadStore.js b/lib/dojo/data/ItemFileReadStore.js index 9d175ca2c..b57daa2de 100644 --- a/lib/dojo/data/ItemFileReadStore.js +++ b/lib/dojo/data/ItemFileReadStore.js @@ -4,947 +4,5 @@ see: http://dojotoolkit.org/license for details */ - -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 - // data from JSON files that have contents in this format -- - // { items: [ - // { name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]}, - // { 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 - // in the array of items that acts as the unique identifier for that item. - // - constructor: function(/* Object */ keywordParameters){ - // summary: constructor - // keywordParameters: {url: String} - // keywordParameters: {data: jsonObject} - // keywordParameters: {typeMap: object) - // The structure of the typeMap object is as follows: - // { - // type0: function || object, - // type1: function || object, - // ... - // typeN: function || object - // } - // 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: - // { - // type: function, //constructor. - // deserialize: function(value) //The function that parses the value and constructs the object defined by type appropriately. - // } - - this._arrayOfAllItems = []; - this._arrayOfTopLevelItems = []; - this._loadFinished = false; - this._jsonFileUrl = keywordParameters.url; - this._ccUrl = keywordParameters.url; - this.url = keywordParameters.url; - this._jsonData = keywordParameters.data; - this.data = null; - this._datatypeMap = keywordParameters.typeMap || {}; - if(!this._datatypeMap['Date']){ - //If no default mapping for dates, then set this as default. - //We use the dojo.date.stamp here because the ISO format is the 'dojo way' - //of generically representing dates. - this._datatypeMap['Date'] = { - type: Date, - deserialize: function(value){ - return dojo.date.stamp.fromISOString(value); - } - }; - } - this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true}; - this._itemsByIdentity = null; - this._storeRefPropName = "_S"; // Default name for the store reference to attach to every item. - this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item. - this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item. - this._reverseRefMap = "_RRM"; // Default attribute for constructing a reverse reference map for use with reference integrity - this._loadInProgress = false; //Got to track the initial load to prevent duelling loads of the dataset. - this._queuedFetches = []; - if(keywordParameters.urlPreventCache !== undefined){ - this.urlPreventCache = keywordParameters.urlPreventCache?true:false; - } - if(keywordParameters.hierarchical !== undefined){ - this.hierarchical = keywordParameters.hierarchical?true:false; - } - if(keywordParameters.clearOnClose){ - this.clearOnClose = true; - } - if("failOk" in keywordParameters){ - this.failOk = keywordParameters.failOk?true:false; - } - }, - - url: "", // use "" rather than undefined for the benefit of the parser (#3539) - - //Internal var, crossCheckUrl. Used so that setting either url or _jsonFileUrl, can still trigger a reload - //when clearOnClose and close is used. - _ccUrl: "", - - data: null, // define this so that the parser can populate it - - typeMap: null, //Define so parser can populate. - - //Parameter to allow users to specify if a close call should force a reload or not. - //By default, it retains the old behavior of not clearing if close is called. But - //if set true, the store will be reset to default state. Note that by doing this, - //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. - //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, - - //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 - //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: - // The item to test for being contained by the store. - if(!this.isItem(item)){ - throw new Error("dojo.data.ItemFileReadStore: Invalid item argument."); - } - }, - - _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: - // The attribute to test for being contained by the store. - if(typeof attribute !== "string"){ - throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument."); - } - }, - - getValue: function( /* item */ item, - /* attribute-name-string */ attribute, - /* value? */ defaultValue){ - // 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, - /* attribute-name-string */ attribute){ - // summary: - // See dojo.data.api.Read.getValues() - - this._assertIsItem(item); - this._assertIsAttribute(attribute); - // Clone it before returning. refs: #10474 - return (item[attribute] || []).slice(0); // Array - }, - - getAttributes: function(/* item */ item){ - // summary: - // See dojo.data.api.Read.getAttributes() - this._assertIsItem(item); - var attributes = []; - for(var key in item){ - // Save off only the real item attributes, not the special id marks for O(1) isItem. - if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName) && (key !== this._reverseRefMap)){ - attributes.push(key); - } - } - return attributes; // Array - }, - - hasAttribute: function( /* item */ item, - /* attribute-name-string */ attribute){ - // 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, - /* anything */ value){ - // summary: - // See dojo.data.api.Read.containsValue() - var regexp = undefined; - if(typeof value === "string"){ - regexp = dojo.data.util.filter.patternToRegExp(value, false); - } - return this._containsValue(item, attribute, value, regexp); //boolean. - }, - - _containsValue: function( /* item */ item, - /* attribute-name-string */ attribute, - /* anything */ value, - /* RegExp?*/ regexp){ - // 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 - // 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: - // The value to match. - // regexp: - // Optional regular expression generated off value if value was of string type to handle wildcarding. - // If present and attribute values are string, then it can be used for comparison instead of 'value' - return dojo.some(this.getValues(item, attribute), function(possibleValue){ - if(possibleValue !== null && !dojo.isObject(possibleValue) && regexp){ - if(possibleValue.toString().match(regexp)){ - return true; // Boolean - } - }else if(value === possibleValue){ - return true; // Boolean - } - }); - }, - - isItem: function(/* anything */ something){ - // summary: - // See dojo.data.api.Read.isItem() - if(something && something[this._storeRefPropName] === this){ - if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){ - return true; - } - } - return false; // Boolean - }, - - isItemLoaded: function(/* anything */ something){ - // summary: - // See dojo.data.api.Read.isItemLoaded() - return this.isItem(something); //boolean - }, - - loadItem: function(/* object */ keywordArgs){ - // summary: - // See dojo.data.api.Read.loadItem() - this._assertIsItem(keywordArgs.item); - }, - - getFeatures: function(){ - // summary: - // See dojo.data.api.Read.getFeatures() - return this._features; //Object - }, - - getLabel: function(/* item */ item){ - // summary: - // See dojo.data.api.Read.getLabel() - if(this._labelAttr && this.isItem(item)){ - return this.getValue(item,this._labelAttr); //String - } - return undefined; //undefined - }, - - getLabelAttributes: function(/* item */ item){ - // summary: - // See dojo.data.api.Read.getLabelAttributes() - if(this._labelAttr){ - return [this._labelAttr]; //array - } - return null; //null - }, - - _fetchItems: function( /* Object */ keywordArgs, - /* Function */ findCallback, - /* Function */ errorCallback){ - // summary: - // See dojo.data.util.simpleFetch.fetch() - var self = this, - filter = function(requestArgs, arrayOfItems){ - var items = [], - i, key; - if(requestArgs.query){ - var value, - ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false; - - //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the - //same value for each item examined. Much more efficient. - var regexpList = {}; - for(key in requestArgs.query){ - value = requestArgs.query[key]; - if(typeof value === "string"){ - regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase); - }else if(value instanceof RegExp){ - regexpList[key] = value; - } - } - for(i = 0; i < arrayOfItems.length; ++i){ - var match = true; - var candidateItem = arrayOfItems[i]; - if(candidateItem === null){ - match = false; - }else{ - for(key in requestArgs.query){ - value = requestArgs.query[key]; - if(!self._containsValue(candidateItem, key, value, regexpList[key])){ - match = false; - } - } - } - if(match){ - items.push(candidateItem); - } - } - 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 - // 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. - for(i = 0; i < arrayOfItems.length; ++i){ - var item = arrayOfItems[i]; - if(item !== null){ - items.push(item); - } - } - findCallback(items, requestArgs); - } - }; - - if(this._loadFinished){ - filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions)); - }else{ - //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 - //compatibility. People use _jsonFileUrl (even though officially - //private. - if(this._jsonFileUrl !== this._ccUrl){ - 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; - this.url = this._jsonFileUrl; - }else if(this.url !== this._ccUrl){ - this._jsonFileUrl = this.url; - this._ccUrl = this.url; - } - - //See if there was any forced reset of data. - 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 - //invoked in the callback. - if(this._loadInProgress){ - this._queuedFetches.push({args: keywordArgs, filter: filter}); - }else{ - this._loadInProgress = true; - var getArgs = { - url: self._jsonFileUrl, - handleAs: "json-comment-optional", - preventCache: this.urlPreventCache, - failOk: this.failOk - }; - var getHandler = dojo.xhrGet(getArgs); - getHandler.addCallback(function(data){ - try{ - self._getItemsFromLoadedData(data); - self._loadFinished = true; - self._loadInProgress = false; - - filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions)); - self._handleQueuedFetches(); - }catch(e){ - self._loadFinished = true; - self._loadInProgress = false; - errorCallback(e, keywordArgs); - } - }); - getHandler.addErrback(function(error){ - self._loadInProgress = false; - errorCallback(error, keywordArgs); - }); - - //Wire up the cancel to abort of the request - //This call cancel on the deferred if it hasn't been called - //yet and then will chain to the simple abort of the - //simpleFetch keywordArgs - var oldAbort = null; - if(keywordArgs.abort){ - oldAbort = keywordArgs.abort; - } - keywordArgs.abort = function(){ - var df = getHandler; - if(df && df.fired === -1){ - df.cancel(); - df = null; - } - if(oldAbort){ - oldAbort.call(keywordArgs); - } - }; - } - }else if(this._jsonData){ - try{ - this._loadFinished = true; - this._getItemsFromLoadedData(this._jsonData); - this._jsonData = null; - filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions)); - }catch(e){ - errorCallback(e, keywordArgs); - } - }else{ - errorCallback(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs); - } - } - }, - - _handleQueuedFetches: function(){ - // summary: - // Internal function to execute delayed request in the store. - //Execute any deferred fetches now. - if(this._queuedFetches.length > 0){ - for(var i = 0; i < this._queuedFetches.length; i++){ - var fData = this._queuedFetches[i], - delayedQuery = fData.args, - delayedFilter = fData.filter; - if(delayedFilter){ - delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions)); - }else{ - this.fetchItemByIdentity(delayedQuery); - } - } - this._queuedFetches = []; - } - }, - - _getItemsArray: function(/*object?*/queryOptions){ - // 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._arrayOfTopLevelItems; - }, - - close: function(/*dojo.data.api.Request || keywordArgs || null */ request){ - // summary: - // See dojo.data.api.Read.close() - 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 - //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) && - (this.url == "" || this.url == null) - ) && this.data == null){ - console.debug("dojo.data.ItemFileReadStore: WARNING! Data reload " + - " information has not been provided." + - " Please set 'url' or 'data' to the appropriate value before" + - " the next fetch"); - } - this._arrayOfAllItems = []; - this._arrayOfTopLevelItems = []; - this._loadFinished = false; - this._itemsByIdentity = null; - this._loadInProgress = false; - this._queuedFetches = []; - } - }, - - _getItemsFromLoadedData: function(/* Object */ dataObject){ - // summary: - // Function to parse the loaded data into item format and build the internal items array. - // description: - // Function to parse the loaded data into item format and build the internal items array. - // - // dataObject: - // The JS data object containing the raw data to convery into item format. - // - // returns: array - // Array of items in store item format. - - // First, we define a couple little utility functions... - var addingArrays = false, - self = this; - - function valueIsAnItem(/* anything */ aValue){ - // summary: - // Given any sort of value that could be in the raw json data, - // return true if we should interpret the value as being an - // item itself, rather than a literal value or a reference. - // example: - // | false == valueIsAnItem("Kermit"); - // | false == valueIsAnItem(42); - // | false == valueIsAnItem(new Date()); - // | false == valueIsAnItem({_type:'Date', _value:'1802-05-14'}); - // | false == valueIsAnItem({_reference:'Kermit'}); - // | true == valueIsAnItem({name:'Kermit', color:'green'}); - // | true == valueIsAnItem({iggy:'pop'}); - // | true == valueIsAnItem({foo:42}); - var isItem = ( - (aValue !== null) && - (typeof aValue === "object") && - (!dojo.isArray(aValue) || addingArrays) && - (!dojo.isFunction(aValue)) && - (aValue.constructor == Object || dojo.isArray(aValue)) && - (typeof aValue._reference === "undefined") && - (typeof aValue._type === "undefined") && - (typeof aValue._value === "undefined") && - self.hierarchical - ); - return isItem; - } - - function addItemAndSubItemsToArrayOfAllItems(/* Item */ anItem){ - self._arrayOfAllItems.push(anItem); - for(var attribute in anItem){ - var valueForAttribute = anItem[attribute]; - if(valueForAttribute){ - if(dojo.isArray(valueForAttribute)){ - var valueArray = valueForAttribute; - for(var k = 0; k < valueArray.length; ++k){ - var singleValue = valueArray[k]; - if(valueIsAnItem(singleValue)){ - addItemAndSubItemsToArrayOfAllItems(singleValue); - } - } - }else{ - if(valueIsAnItem(valueForAttribute)){ - addItemAndSubItemsToArrayOfAllItems(valueForAttribute); - } - } - } - } - } - - this._labelAttr = dataObject.label; - - // We need to do some transformations to convert the data structure - // that we read from the file into a format that will be convenient - // to work with in memory. - - // Step 1: Walk through the object hierarchy and build a list of all items - var i, - item; - this._arrayOfAllItems = []; - this._arrayOfTopLevelItems = dataObject.items; - - for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){ - item = this._arrayOfTopLevelItems[i]; - if(dojo.isArray(item)){ - addingArrays = true; - } - addItemAndSubItemsToArrayOfAllItems(item); - item[this._rootItemPropName]=true; - } - - // 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 - // reference and item id special properties for the O(1) isItem - var allAttributeNames = {}, - key; - - for(i = 0; i < this._arrayOfAllItems.length; ++i){ - item = this._arrayOfAllItems[i]; - for(key in item){ - if(key !== this._rootItemPropName){ - var value = item[key]; - if(value !== null){ - if(!dojo.isArray(value)){ - item[key] = [value]; - } - }else{ - item[key] = [null]; - } - } - allAttributeNames[key]=key; - } - } - - // Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName - // This should go really fast, it will generally never even run the loop. - while(allAttributeNames[this._storeRefPropName]){ - this._storeRefPropName += "_"; - } - while(allAttributeNames[this._itemNumPropName]){ - this._itemNumPropName += "_"; - } - while(allAttributeNames[this._reverseRefMap]){ - 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 - // hash table of items keyed by the identity of the items. - var arrayOfValues; - - var identifier = dataObject.identifier; - if(identifier){ - this._itemsByIdentity = {}; - this._features['dojo.data.api.Identity'] = identifier; - for(i = 0; i < this._arrayOfAllItems.length; ++i){ - item = this._arrayOfAllItems[i]; - arrayOfValues = item[identifier]; - var identity = arrayOfValues[0]; - if(!Object.hasOwnProperty.call(this._itemsByIdentity, identity)){ - this._itemsByIdentity[identity] = item; - }else{ - if(this._jsonFileUrl){ - throw new Error("dojo.data.ItemFileReadStore: The json data as specified by: [" + this._jsonFileUrl + "] is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]"); - }else if(this._jsonData){ - throw new Error("dojo.data.ItemFileReadStore: The json data provided by the creation arguments is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]"); - } - } - } - }else{ - this._features['dojo.data.api.Identity'] = Number; - } - - // 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]; - item[this._storeRefPropName] = this; - item[this._itemNumPropName] = i; - } - - // Step 6: We walk through all the attribute values of all the items, - // looking for type/value literals and item-references. - // - // 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] } - // (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:'1918-07-18'}] } - // into this: - // { 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){ - item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] } - for(key in item){ - arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}] - for(var j = 0; j < arrayOfValues.length; ++j){ - value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}} - if(value !== null && typeof value == "object"){ - 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){ - 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); - }else if(dojo.isFunction(mappingObj.deserialize)){ - arrayOfValues[j] = mappingObj.deserialize(value._value); - }else{ - throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function"); - } - } - if(value._reference){ - var referenceDescription = value._reference; // example: {name:'Miss Piggy'} - if(!dojo.isObject(referenceDescription)){ - // example: 'Miss Piggy' - // from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]} - arrayOfValues[j] = this._getItemByIdentity(referenceDescription); - }else{ - // example: {name:'Miss Piggy'} - // from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] } - for(var k = 0; k < this._arrayOfAllItems.length; ++k){ - var candidateItem = this._arrayOfAllItems[k], - found = true; - for(var refKey in referenceDescription){ - if(candidateItem[refKey] != referenceDescription[refKey]){ - found = false; - } - } - if(found){ - arrayOfValues[j] = candidateItem; - } - } - } - if(this.referenceIntegrity){ - var refItem = arrayOfValues[j]; - if(this.isItem(refItem)){ - this._addReferenceToMap(refItem, item, key); - } - } - }else if(this.isItem(value)){ - //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){ - this._addReferenceToMap(value, item, key); - } - } - } - } - } - } - }, - - _addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){ - // summary: - // Method to add an reference map entry for an item and attribute. - // description: - // Method to add an reference map entry for an item and attribute. // - // refItem: - // The item that is referenced. - // parentItem: - // The item that holds the new reference to refItem. - // attribute: - // The attribute on parentItem that contains the new reference. - - //Stub function, does nothing. Real processing is in ItemFileWriteStore. - }, - - getIdentity: function(/* item */ item){ - // summary: - // See dojo.data.api.Identity.getIdentity() - var identifier = this._features['dojo.data.api.Identity']; - if(identifier === Number){ - return item[this._itemNumPropName]; // Number - }else{ - var arrayOfValues = item[identifier]; - if(arrayOfValues){ - return arrayOfValues[0]; // Object || String - } - } - return null; // null - }, - - fetchItemByIdentity: function(/* Object */ keywordArgs){ - // summary: - // See dojo.data.api.Identity.fetchItemByIdentity() - - // Hasn't loaded yet, we have to trigger the load. - var item, - scope; - if(!this._loadFinished){ - 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 - //compatibility. People use _jsonFileUrl (even though officially - //private. - if(this._jsonFileUrl !== this._ccUrl){ - 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; - this.url = this._jsonFileUrl; - }else if(this.url !== this._ccUrl){ - this._jsonFileUrl = this.url; - this._ccUrl = this.url; - } - - //See if there was any forced reset of data. - if(this.data != null && this._jsonData == null){ - this._jsonData = this.data; - this.data = null; - } - - if(this._jsonFileUrl){ - - if(this._loadInProgress){ - this._queuedFetches.push({args: keywordArgs}); - }else{ - this._loadInProgress = true; - var getArgs = { - url: self._jsonFileUrl, - handleAs: "json-comment-optional", - preventCache: this.urlPreventCache, - failOk: this.failOk - }; - var getHandler = dojo.xhrGet(getArgs); - getHandler.addCallback(function(data){ - var scope = keywordArgs.scope?keywordArgs.scope:dojo.global; - try{ - self._getItemsFromLoadedData(data); - self._loadFinished = true; - self._loadInProgress = false; - item = self._getItemByIdentity(keywordArgs.identity); - if(keywordArgs.onItem){ - keywordArgs.onItem.call(scope, item); - } - self._handleQueuedFetches(); - }catch(error){ - self._loadInProgress = false; - if(keywordArgs.onError){ - keywordArgs.onError.call(scope, error); - } - } - }); - getHandler.addErrback(function(error){ - self._loadInProgress = false; - if(keywordArgs.onError){ - var scope = keywordArgs.scope?keywordArgs.scope:dojo.global; - keywordArgs.onError.call(scope, error); - } - }); - } - - }else if(this._jsonData){ - // Passed in data, no need to xhr. - self._getItemsFromLoadedData(self._jsonData); - self._jsonData = null; - self._loadFinished = true; - item = self._getItemByIdentity(keywordArgs.identity); - if(keywordArgs.onItem){ - 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); - if(keywordArgs.onItem){ - scope = keywordArgs.scope?keywordArgs.scope:dojo.global; - keywordArgs.onItem.call(scope, item); - } - } - }, - - _getItemByIdentity: function(/* Object */ identity){ - // summary: - // Internal function to look an item up by its identity map. - var item = null; - if(this._itemsByIdentity && - Object.hasOwnProperty.call(this._itemsByIdentity, identity)){ - item = this._itemsByIdentity[identity]; - }else if (Object.hasOwnProperty.call(this._arrayOfAllItems, identity)){ - item = this._arrayOfAllItems[identity]; - } - if(item === undefined){ - item = null; - } - return item; // Object - }, - - getIdentityAttributes: function(/* item */ item){ - // 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 - return null; // null - }else{ - return [identifier]; // Array - } - }, - - _forceLoad: function(){ - // 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. - 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 - //compatibility. People use _jsonFileUrl (even though officially - //private. - if(this._jsonFileUrl !== this._ccUrl){ - 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; - this.url = this._jsonFileUrl; - }else if(this.url !== this._ccUrl){ - this._jsonFileUrl = this.url; - this._ccUrl = this.url; - } - - //See if there was any forced reset of data. - if(this.data != null){ - this._jsonData = this.data; - this.data = null; - } - - if(this._jsonFileUrl){ - var getArgs = { - url: this._jsonFileUrl, - handleAs: "json-comment-optional", - preventCache: this.urlPreventCache, - failOk: this.failOk, - sync: true - }; - var getHandler = dojo.xhrGet(getArgs); - getHandler.addCallback(function(data){ - try{ - //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. - //TODO: Revisit the loading scheme of this store to improve multi-initial - //request handling. - if(self._loadInProgress !== true && !self._loadFinished){ - self._getItemsFromLoadedData(data); - self._loadFinished = true; - }else if(self._loadInProgress){ - //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."); - } - }catch(e){ - console.log(e); - throw e; - } - }); - getHandler.addErrback(function(error){ - throw error; - }); - }else if(this._jsonData){ - self._getItemsFromLoadedData(self._jsonData); - self._jsonData = null; - self._loadFinished = true; - } - } -}); -//Mix in the simple fetch implementation to this class. -dojo.extend(dojo.data.ItemFileReadStore,dojo.data.util.simpleFetch); - -} +//>>built +define("dojo/data/ItemFileReadStore",["../_base/kernel","../_base/lang","../_base/declare","../_base/array","../_base/xhr","../Evented","../_base/window","./util/filter","./util/simpleFetch","../date/stamp"],function(_1,_2,_3,_4,_5,_6,_7,_8,_9,_a){var _b=_3("dojo.data.ItemFileReadStore",[_6],{constructor:function(_c){this._arrayOfAllItems=[];this._arrayOfTopLevelItems=[];this._loadFinished=false;this._jsonFileUrl=_c.url;this._ccUrl=_c.url;this.url=_c.url;this._jsonData=_c.data;this.data=null;this._datatypeMap=_c.typeMap||{};if(!this._datatypeMap["Date"]){this._datatypeMap["Date"]={type:Date,deserialize:function(_d){return _a.fromISOString(_d);}};}this._features={"dojo.data.api.Read":true,"dojo.data.api.Identity":true};this._itemsByIdentity=null;this._storeRefPropName="_S";this._itemNumPropName="_0";this._rootItemPropName="_RI";this._reverseRefMap="_RRM";this._loadInProgress=false;this._queuedFetches=[];if(_c.urlPreventCache!==undefined){this.urlPreventCache=_c.urlPreventCache?true:false;}if(_c.hierarchical!==undefined){this.hierarchical=_c.hierarchical?true:false;}if(_c.clearOnClose){this.clearOnClose=true;}if("failOk" in _c){this.failOk=_c.failOk?true:false;}},url:"",_ccUrl:"",data:null,typeMap:null,clearOnClose:false,urlPreventCache:false,failOk:false,hierarchical:true,_assertIsItem:function(_e){if(!this.isItem(_e)){throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");}},_assertIsAttribute:function(_f){if(typeof _f!=="string"){throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");}},getValue:function(_10,_11,_12){var _13=this.getValues(_10,_11);return (_13.length>0)?_13[0]:_12;},getValues:function(_14,_15){this._assertIsItem(_14);this._assertIsAttribute(_15);return (_14[_15]||[]).slice(0);},getAttributes:function(_16){this._assertIsItem(_16);var _17=[];for(var key in _16){if((key!==this._storeRefPropName)&&(key!==this._itemNumPropName)&&(key!==this._rootItemPropName)&&(key!==this._reverseRefMap)){_17.push(key);}}return _17;},hasAttribute:function(_18,_19){this._assertIsItem(_18);this._assertIsAttribute(_19);return (_19 in _18);},containsValue:function(_1a,_1b,_1c){var _1d=undefined;if(typeof _1c==="string"){_1d=_8.patternToRegExp(_1c,false);}return this._containsValue(_1a,_1b,_1c,_1d);},_containsValue:function(_1e,_1f,_20,_21){return _4.some(this.getValues(_1e,_1f),function(_22){if(_22!==null&&!_2.isObject(_22)&&_21){if(_22.toString().match(_21)){return true;}}else{if(_20===_22){return true;}}});},isItem:function(_23){if(_23&&_23[this._storeRefPropName]===this){if(this._arrayOfAllItems[_23[this._itemNumPropName]]===_23){return true;}}return false;},isItemLoaded:function(_24){return this.isItem(_24);},loadItem:function(_25){this._assertIsItem(_25.item);},getFeatures:function(){return this._features;},getLabel:function(_26){if(this._labelAttr&&this.isItem(_26)){return this.getValue(_26,this._labelAttr);}return undefined;},getLabelAttributes:function(_27){if(this._labelAttr){return [this._labelAttr];}return null;},_fetchItems:function(_28,_29,_2a){var _2b=this,_2c=function(_2d,_2e){var _2f=[],i,key;if(_2d.query){var _30,_31=_2d.queryOptions?_2d.queryOptions.ignoreCase:false;var _32={};for(key in _2d.query){_30=_2d.query[key];if(typeof _30==="string"){_32[key]=_8.patternToRegExp(_30,_31);}else{if(_30 instanceof RegExp){_32[key]=_30;}}}for(i=0;i<_2e.length;++i){var _33=true;var _34=_2e[i];if(_34===null){_33=false;}else{for(key in _2d.query){_30=_2d.query[key];if(!_2b._containsValue(_34,key,_30,_32[key])){_33=false;}}}if(_33){_2f.push(_34);}}_29(_2f,_2d);}else{for(i=0;i<_2e.length;++i){var _35=_2e[i];if(_35!==null){_2f.push(_35);}}_29(_2f,_2d);}};if(this._loadFinished){_2c(_28,this._getItemsArray(_28.queryOptions));}else{if(this._jsonFileUrl!==this._ccUrl){_1.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;this.url=this._jsonFileUrl;}else{if(this.url!==this._ccUrl){this._jsonFileUrl=this.url;this._ccUrl=this.url;}}if(this.data!=null){this._jsonData=this.data;this.data=null;}if(this._jsonFileUrl){if(this._loadInProgress){this._queuedFetches.push({args:_28,filter:_2c});}else{this._loadInProgress=true;var _36={url:_2b._jsonFileUrl,handleAs:"json-comment-optional",preventCache:this.urlPreventCache,failOk:this.failOk};var _37=_5.get(_36);_37.addCallback(function(_38){try{_2b._getItemsFromLoadedData(_38);_2b._loadFinished=true;_2b._loadInProgress=false;_2c(_28,_2b._getItemsArray(_28.queryOptions));_2b._handleQueuedFetches();}catch(e){_2b._loadFinished=true;_2b._loadInProgress=false;_2a(e,_28);}});_37.addErrback(function(_39){_2b._loadInProgress=false;_2a(_39,_28);});var _3a=null;if(_28.abort){_3a=_28.abort;}_28.abort=function(){var df=_37;if(df&&df.fired===-1){df.cancel();df=null;}if(_3a){_3a.call(_28);}};}}else{if(this._jsonData){try{this._loadFinished=true;this._getItemsFromLoadedData(this._jsonData);this._jsonData=null;_2c(_28,this._getItemsArray(_28.queryOptions));}catch(e){_2a(e,_28);}}else{_2a(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."),_28);}}}},_handleQueuedFetches:function(){if(this._queuedFetches.length>0){for(var i=0;i