📄 itemfilewritestore.js
字号:
}else{ this._addReferenceToMap(possibleItem, item, attribute); } } }, this); for(var rId in map){ var removedItem; if(this._itemsByIdentity){ removedItem = this._itemsByIdentity[rId]; }else{ removedItem = this._arrayOfAllItems[rId]; } this._removeReferenceFromMap(removedItem, item, attribute); } }else{ //Everything is new (no old values) so we have to just //insert all the references, if any. for(var i = 0; i < newValueArray.length; i++){ var value = newValueArray[i]; if(this.isItem(value)){ this._addReferenceToMap(value, item, attribute); } } } } item[attribute] = newValueArray; success = true; } // Now we make the dojo.data.api.Notification call if(callOnSet){ this.onSet(item, attribute, oldValueOrValues, newValueOrValues); } return success; // boolean }, _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. var parentId = this.getIdentity(parentItem); var references = refItem[this._reverseRefMap]; if(!references){ references = refItem[this._reverseRefMap] = {}; } var itemRef = references[parentId]; if(!itemRef){ itemRef = references[parentId] = {}; } itemRef[attribute] = true; }, _removeReferenceFromMap: function(/* item */ refItem, /* item */ parentItem, /*strin*/ attribute){ // summary: // 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 // the item, its reference object and entry are removed. // // refItem: // The item that is referenced. // parentItem: // The item holding a reference to refItem. // attribute: // The attribute on parentItem that contains the reference. var identity = this.getIdentity(parentItem); var references = refItem[this._reverseRefMap]; var itemId; if(references){ for(itemId in references){ if(itemId == identity){ delete references[itemId][attribute]; if(this._isEmpty(references[itemId])){ delete references[itemId]; } } } if(this._isEmpty(references)){ delete refItem[this._reverseRefMap]; } } }, _dumpReferenceMap: function(){ // summary: // Function to dump the reverse reference map of all items in the store for debug purposes. // description: // Function to dump the reverse reference map of all items in the store for debug purposes. var i; for(i = 0; i < this._arrayOfAllItems.length; i++){ var item = this._arrayOfAllItems[i]; if(item && item[this._reverseRefMap]){ console.log("Item: [" + this.getIdentity(item) + "] is referenced by: " + dojo.toJson(item[this._reverseRefMap])); } } }, _getValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute){ var valueOrValues = undefined; if(this.hasAttribute(item, attribute)){ var valueArray = this.getValues(item, attribute); if(valueArray.length == 1){ valueOrValues = valueArray[0]; }else{ valueOrValues = valueArray; } } return valueOrValues; }, _flatten: function(/* anything */ value){ if(this.isItem(value)){ var item = value; // 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"}); // we want to return // {_reference:2} var identity = this.getIdentity(item); var referenceObject = {_reference: identity}; return referenceObject; }else{ if(typeof value === "object"){ for(var type in this._datatypeMap){ var typeMap = this._datatypeMap[type]; if (dojo.isObject(typeMap) && !dojo.isFunction(typeMap)){ if(value instanceof typeMap.type){ if(!typeMap.serialize){ throw new Error("ItemFileWriteStore: No serializer defined for type mapping: [" + type + "]"); } return {_type: type, _value: typeMap.serialize(value)}; } } else if(value instanceof typeMap){ //SImple mapping, therefore, return as a toString serialization. return {_type: type, _value: value.toString()}; } } } return value; } }, _getNewFileContentString: function(){ // 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 var serializableStructure = {}; var identifierAttribute = this._getIdentifierAttribute(); if(identifierAttribute !== Number){ serializableStructure.identifier = identifierAttribute; } if(this._labelAttr){ serializableStructure.label = this._labelAttr; } serializableStructure.items = []; for(var i = 0; i < this._arrayOfAllItems.length; ++i){ var item = this._arrayOfAllItems[i]; if(item !== null){ var serializableItem = {}; for(var key in item){ if(key !== this._storeRefPropName && key !== this._itemNumPropName){ var attribute = key; var valueArray = this.getValues(item, attribute); if(valueArray.length == 1){ serializableItem[attribute] = this._flatten(valueArray[0]); }else{ var serializableArray = []; for(var j = 0; j < valueArray.length; ++j){ serializableArray.push(this._flatten(valueArray[j])); serializableItem[attribute] = serializableArray; } } } } serializableStructure.items.push(serializableItem); } } var prettyPrint = true; return dojo.toJson(serializableStructure, prettyPrint); }, _isEmpty: function(something){ // summary: // Function to determine if an array or object has no properties or values. // something: // The array or object to examine. var empty = true; if(dojo.isObject(something)){ var i; for(i in something){ empty = false; break; } }else if(dojo.isArray(something)){ if(something.length > 0){ empty = false; } } return empty; //boolean }, save: function(/* object */ keywordArgs){ // summary: See dojo.data.api.Write.save() this._assert(!this._saveInProgress); // this._saveInProgress is set to true, briefly, from when save is first called to when it completes this._saveInProgress = true; var self = this; var saveCompleteCallback = function(){ self._pending = { _newItems:{}, _modifiedItems:{}, _deletedItems:{} }; self._saveInProgress = false; // must come after this._pending is cleared, but before any callbacks if(keywordArgs && keywordArgs.onComplete){ var scope = keywordArgs.scope || dojo.global; keywordArgs.onComplete.call(scope); } }; var saveFailedCallback = function(){ self._saveInProgress = false; if(keywordArgs && keywordArgs.onError){ var scope = keywordArgs.scope || dojo.global; keywordArgs.onError.call(scope); } }; if(this._saveEverything){ var newFileContentString = this._getNewFileContentString(); this._saveEverything(saveCompleteCallback, saveFailedCallback, newFileContentString); } if(this._saveCustom){ this._saveCustom(saveCompleteCallback, saveFailedCallback); } if(!this._saveEverything && !this._saveCustom){ // Looks like there is no user-defined save-handler function. // That's fine, it just means the datastore is acting as a "mock-write" // store -- changes get saved in memory but don't get saved to disk. saveCompleteCallback(); } }, revert: function(){ // summary: See dojo.data.api.Write.revert() this._assert(!this._saveInProgress); var identity; for(identity in this._pending._newItems){ var newItem = this._pending._newItems[identity]; newItem[this._storeRefPropName] = null; // null out the new item, but don't change the array index so // so we can keep using _arrayOfAllItems.length. this._arrayOfAllItems[newItem[this._itemNumPropName]] = null; if(newItem[this._rootItemPropName]){ this._removeArrayElement(this._arrayOfTopLevelItems, newItem); } if(this._itemsByIdentity){ delete this._itemsByIdentity[identity]; } } for(identity in this._pending._modifiedItems){ // find the original item and the modified item that replaced it var originalItem = this._pending._modifiedItems[identity]; var modifiedItem = null; if(this._itemsByIdentity){ modifiedItem = this._itemsByIdentity[identity]; }else{ modifiedItem = this._arrayOfAllItems[identity]; } // make the original item into a full-fledged item again originalItem[this._storeRefPropName] = this; modifiedItem[this._storeRefPropName] = null; // replace the modified item with the original one var arrayIndex = modifiedItem[this._itemNumPropName]; this._arrayOfAllItems[arrayIndex] = originalItem; if(modifiedItem[this._rootItemPropName]){ var i; for (i = 0; i < this._arrayOfTopLevelItems.length; i++) { var possibleMatch = this._arrayOfTopLevelItems[i]; if (this.getIdentity(possibleMatch) == identity){ this._arrayOfTopLevelItems[i] = originalItem; break; } } } if(this._itemsByIdentity){ this._itemsByIdentity[identity] = originalItem; } } var deletedItem; for(identity in this._pending._deletedItems){ deletedItem = this._pending._deletedItems[identity]; deletedItem[this._storeRefPropName] = this; var index = deletedItem[this._itemNumPropName]; //Restore the reverse refererence map, if any. if(deletedItem["backup_" + this._reverseRefMap]){ deletedItem[this._reverseRefMap] = deletedItem["backup_" + this._reverseRefMap]; delete deletedItem["backup_" + this._reverseRefMap]; } this._arrayOfAllItems[index] = deletedItem; if (this._itemsByIdentity) { this._itemsByIdentity[identity] = deletedItem; } if(deletedItem[this._rootItemPropName]){ this._arrayOfTopLevelItems.push(deletedItem); } } //We have to pass through it again and restore the reference maps after all the //undeletes have occurred. for(identity in this._pending._deletedItems){ deletedItem = this._pending._deletedItems[identity]; if(deletedItem["backupRefs_" + this._reverseRefMap]){ dojo.forEach(deletedItem["backupRefs_" + this._reverseRefMap], function(reference){ var refItem; if(this._itemsByIdentity){ refItem = this._itemsByIdentity[reference.id]; }else{ refItem = this._arrayOfAllItems[reference.id]; } this._addReferenceToMap(refItem, deletedItem, reference.attr); }, this); delete deletedItem["backupRefs_" + this._reverseRefMap]; } } this._pending = { _newItems:{}, _modifiedItems:{}, _deletedItems:{} }; return true; // boolean }, isDirty: function(/* item? */ item){ // summary: See dojo.data.api.Write.isDirty() if(item){ // return true if the item is dirty var identity = this.getIdentity(item); return new Boolean(this._pending._newItems[identity] || this._pending._modifiedItems[identity] || this._pending._deletedItems[identity]); // 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) || !this._isEmpty(this._pending._modifiedItems) || !this._isEmpty(this._pending._deletedItems)){ return true; } return false; // boolean } },/* dojo.data.api.Notification */ 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 // 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. }, 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. }});}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -