📄 xmlstore.js
字号:
// 'item' must be an instance of a dojox.data.XmlItem from the store instance. // 'attribute' can be an XML attribute name of the element or one of // special names described below. // If 'attribute' specifies "tagName", nothing is removed and false is // returned. // If 'attribute' specifies "childNodes" or "text()", all child nodes // are removed. // For generic attributes, if '_attributeMap' is specified, // an actual attribute name is looked up with the tag name of // the element and 'attribute' (concatenated with '.'). // Then, if 'attribute' starts with "@", the XML attribute is removed. // Otherwise, child elements of the tag name specified with // 'attribute' are removed. // item: // An XML element that holds the attribute // attribute: // A tag name of child elements, an XML attribute name or one of // special names // returns: // False for "tagName", otherwise true if(attribute === "tagName"){ return false; //boolean } this._backupItem(item); var element = item.element; if(attribute === "childNodes" || attribute === "text()"){ while(element.firstChild){ element.removeChild(element.firstChild); } }else{ attribute = this._getAttribute(element.nodeName, attribute); if(attribute.charAt(0) === '@'){ var name = attribute.substring(1); element.removeAttribute(name); }else{ for(var i = element.childNodes.length - 1; i >= 0; i--){ var node = element.childNodes[i]; if( node.nodeType === 1 /*ELEMENT_NODE*/ && node.nodeName === attribute){ element.removeChild(node); } } } } return true; //boolean }, save: function(/* object */ keywordArgs){ // summary: // Save new and/or modified items (XML elements) // description: // 'url' is used to save XML documents for new, modified and/or // deleted XML elements. // keywordArgs: // An object for callbacks if(!keywordArgs){ keywordArgs = {}; } for(var i = 0; i < this._modifiedItems.length; i++){ this._saveItem(this._modifiedItems[i], keywordArgs, "PUT"); } for(var i = 0; i < this._newItems.length; i++){ var item = this._newItems[i]; if(item.element.parentNode){ // reparented this._newItems.splice(i, 1); i--; continue; } this._saveItem(this._newItems[i], keywordArgs, "POST"); } for(var i = 0; i < this._deletedItems.length; i++){ this._saveItem(this._deletedItems[i], keywordArgs, "DELETE"); } }, revert: function(){ // summary: // Invalidate changes (new and/or modified elements) // returns: // True console.log("XmlStore.revert() _newItems=" + this._newItems.length); console.log("XmlStore.revert() _deletedItems=" + this._deletedItems.length); console.log("XmlStore.revert() _modifiedItems=" + this._modifiedItems.length); this._newItems = []; this._restoreItems(this._deletedItems); this._deletedItems = []; this._restoreItems(this._modifiedItems); this._modifiedItems = []; return true; //boolean }, isDirty: function(/* item? */ item){ // summary: // Check whether an item is new, modified or deleted // description: // If 'item' is specified, true is returned if the item is new, // modified or deleted. // Otherwise, true is returned if there are any new, modified // or deleted items. // item: // An item (XML element) to check // returns: // True if an item or items are new, modified or deleted, otherwise // false if (item) { var element = this._getRootElement(item.element); return (this._getItemIndex(this._newItems, element) >= 0 || this._getItemIndex(this._deletedItems, element) >= 0 || this._getItemIndex(this._modifiedItems, element) >= 0); //boolean } else { return (this._newItems.length > 0 || this._deletedItems.length > 0 || this._modifiedItems.length > 0); //boolean } }, _saveItem: function(item, keywordArgs, method){ if(method === "PUT"){ url = this._getPutUrl(item); }else if(method === "DELETE"){ url = this._getDeleteUrl(item); }else{ // POST url = this._getPostUrl(item); } if(!url){ if(keywordArgs.onError){ keywordArgs.onError.call(scope, new Error("No URL for saving content: " + postContent)); } return; } var saveArgs = { url: url, method: (method || "POST"), contentType: "text/xml", handleAs: "xml" }; var saveHander; if(method === "PUT"){ saveArgs.putData = this._getPutContent(item); saveHandler = dojo.rawXhrPut(saveArgs); }else if(method === "DELETE"){ saveHandler = dojo.xhrDelete(saveArgs); }else{ // POST saveArgs.postData = this._getPostContent(item); saveHandler = dojo.rawXhrPost(saveArgs); } var scope = (keywordArgs.scope || dojo.global); var self = this; saveHandler.addCallback(function(data){ self._forgetItem(item); if(keywordArgs.onComplete){ keywordArgs.onComplete.call(scope); } }); saveHandler.addErrback(function(error){ if(keywordArgs.onError){ keywordArgs.onError.call(scope, error); } }); }, _getPostUrl: function(item){ // summary: // Generate a URL for post // description: // This default implementation just returns 'url'. // Sub-classes may override this method for the custom URL. // item: // An item to save // returns: // A post URL return this.url; //string }, _getPutUrl: function(item){ // summary: // Generate a URL for put // description: // This default implementation just returns 'url'. // Sub-classes may override this method for the custom URL. // item: // An item to save // returns: // A put URL return this.url; //string }, _getDeleteUrl: function(item){ // summary: // Generate a URL for delete // description: // This default implementation returns 'url' with 'keyAttribute' // as a query string. // Sub-classes may override this method for the custom URL based on // changes (new, deleted, or modified). // item: // An item to delete // returns: // A delete URL var url = this.url; if (item && this.keyAttribute !== "") { var value = this.getValue(item, this.keyAttribute); if (value) { var key = this.keyAttribute.charAt(0) ==='@' ? this.keyAttribute.substring(1): this.keyAttribute; url += url.indexOf('?') < 0 ? '?' : '&'; url += key + '=' + value; } } return url; //string }, _getPostContent: function(item){ // summary: // Generate a content to post // description: // This default implementation generates an XML document for one // (the first only) new or modified element. // Sub-classes may override this method for the custom post content // generation. // item: // An item to save // returns: // A post content var element = item.element; var declaration = "<?xml version=\"1.0\"?>"; // FIXME: encoding? return declaration + dojox.data.dom.innerXML(element); //XML string }, _getPutContent: function(item){ // summary: // Generate a content to put // description: // This default implementation generates an XML document for one // (the first only) new or modified element. // Sub-classes may override this method for the custom put content // generation. // item: // An item to save // returns: // A post content var element = item.element; var declaration = "<?xml version=\"1.0\"?>"; // FIXME: encoding? return declaration + dojox.data.dom.innerXML(element); //XML string },/* internal API */ _getAttribute: function(tagName, attribute){ if(this._attributeMap){ var key = tagName + "." + attribute; var value = this._attributeMap[key]; if(value){ attribute = value; }else{ // look for global attribute value = this._attributeMap[attribute]; if(value){ attribute = value; } } } return attribute; //object }, _getItem: function(element){ return new dojox.data.XmlItem(element, this); //object }, _getItemIndex: function(items, element){ for(var i = 0; i < items.length; i++){ if(items[i].element === element){ return i; //int } } return -1; //int }, _backupItem: function(item){ var element = this._getRootElement(item.element); if( this._getItemIndex(this._newItems, element) >= 0 || this._getItemIndex(this._modifiedItems, element) >= 0){ return; // new or already modified } if(element != item.element){ item = this._getItem(element); } item._backup = element.cloneNode(true); this._modifiedItems.push(item); }, _restoreItems: function(items){ dojo.forEach(items,function(item){ if(item._backup){ item.element = item._backup; item._backup = null; } },this); }, _forgetItem: function(item){ var element = item.element; var index = this._getItemIndex(this._newItems, element); if(index >= 0){ this._newItems.splice(index, 1); } index = this._getItemIndex(this._deletedItems, element); if(index >= 0){ this._deletedItems.splice(index, 1); } index = this._getItemIndex(this._modifiedItems, element); if(index >= 0){ this._modifiedItems.splice(index, 1); } }, _getDocument: function(element){ if(element){ return element.ownerDocument; //DOMDocument }else if(!this._document){ return dojox.data.dom.createDocument(); // DOMDocument } }, _getRootElement: function(element){ while(element.parentNode){ element = element.parentNode; } return element; //DOMElement }});//FIXME: Is a full class here really needed for containment of the item or would//an anon object work fine?dojo.declare("dojox.data.XmlItem", null, { constructor: function(element, store) { // summary: // Initialize with an XML element // element: // An XML element // store: // The containing store, if any. this.element = element; this.store = store; }, // summary: // A data item of 'XmlStore' // description: // This class represents an item of 'XmlStore' holding an XML element. // 'element' // element: // An XML element toString: function() { // summary: // Return a value of the first text child of the element // returns: // a value of the first text child of the element var str = ""; if (this.element) { for (var i = 0; i < this.element.childNodes.length; i++) { var node = this.element.childNodes[i]; if (node.nodeType === 3) { str = node.nodeValue; break; } } } return str; //String }});dojo.extend(dojox.data.XmlStore,dojo.data.util.simpleFetch);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -