diff options
Diffstat (limited to 'includes/js/dojox/data/AtomReadStore.js')
-rw-r--r-- | includes/js/dojox/data/AtomReadStore.js | 543 |
1 files changed, 543 insertions, 0 deletions
diff --git a/includes/js/dojox/data/AtomReadStore.js b/includes/js/dojox/data/AtomReadStore.js new file mode 100644 index 0000000..2bc6920 --- /dev/null +++ b/includes/js/dojox/data/AtomReadStore.js @@ -0,0 +1,543 @@ +if(!dojo._hasResource["dojox.data.AtomReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojox.data.AtomReadStore"] = true; +dojo.provide("dojox.data.AtomReadStore"); + +dojo.require("dojo.data.util.simpleFetch"); +dojo.require("dojo.data.util.filter"); +dojo.require("dojo.date.stamp"); + +dojo.experimental("dojox.data.AtomReadStore"); + +dojo.declare("dojox.data.AtomReadStore", null, { + // summary: + // A read only data store for Atom XML based services or documents + // description: + // A data store for Atom XML based services or documents. This store is still under development + // and doesn't support wildcard filtering yet. Attribute filtering is limited to category or id. + + constructor: function(/* object */ args) { + // summary: + // Constructor for the AtomRead store. + // args: + // An anonymous object to initialize properties. It expects the following values: + // url: The url to a service or an XML document that represents the store + // unescapeHTML: A boolean to specify whether or not to unescape HTML text + // sendQuery: A boolean indicate to add a query string to the service URL + + if(args){ + this.url = args.url; + this.rewriteUrl = args.rewriteUrl; + this.label = args.label || this.label; + this.sendQuery = (args.sendQuery || args.sendquery || this.sendQuery); + this.unescapeHTML = args.unescapeHTML; + } + if(!this.url){ + throw new Error("AtomReadStore: a URL must be specified when creating the data store"); + } + }, + + //Values that may be set by the parser. + //Ergo, have to be instantiated to something + //So the parser knows how to set them. + url: "", + + label: "title", + + sendQuery: false, + + unescapeHTML: false, + + /* dojo.data.api.Read */ + + getValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* value? */ defaultValue){ + // summary: + // Return an attribute value + // description: + // 'item' must be an instance of an object created by the AtomReadStore instance. + // Accepted attributes are id, subtitle, title, summary, content, author, updated, + // published, category, link and alternate + // item: + // An item returned by a call to the 'fetch' method. + // attribute: + // A attribute of the Atom Entry + // defaultValue: + // A default value + // returns: + // An attribute value found, otherwise 'defaultValue' + this._assertIsItem(item); + this._assertIsAttribute(attribute); + this._initItem(item); + attribute = attribute.toLowerCase(); + //If the attribute has previously been retrieved, then return it + if(!item._attribs[attribute] && !item._parsed){ + this._parseItem(item); + item._parsed = true; + } + var retVal = item._attribs[attribute]; + + if(!retVal && attribute=="summary") { + var content = this.getValue(item, "content"); + var regexp = new RegExp("/(<([^>]+)>)/g", "i"); + var text = content.text.replace(regexp,""); + retVal = { + text: text.substring(0, Math.min(400, text.length)), + type: "text" + }; + item._attribs[attribute] = retVal; + } + + if(retVal && this.unescapeHTML){ + if ((attribute == "content" || attribute == "summary" || attribute == "subtitle") && !item["_"+attribute+"Escaped"]) { + retVal.text = this._unescapeHTML(retVal.text); + item["_"+attribute+"Escaped"] = true; + } + } + return retVal ? dojo.isArray(retVal) ? retVal[0]: retVal : undefined; + }, + + getValues: function(/* item */ item, /* attribute || attribute-name-string */ attribute){ + // summary: + // Return an attribute value + // description: + // 'item' must be an instance of an object created by the AtomReadStore instance. + // Accepted attributes are id, subtitle, title, summary, content, author, updated, + // published, category, link and alternate + // item: + // An item returned by a call to the 'fetch' method. + // attribute: + // A attribute of the Atom Entry + // defaultValue: + // A default value + // returns: + // An array of values for the attribute value found, otherwise 'defaultValue' + this._assertIsItem(item); + this._assertIsAttribute(attribute); + this._initItem(item); + attribute = attribute.toLowerCase(); + //If the attribute has previously been retrieved, then return it + if(!item._attribs[attribute]){ + this._parseItem(item); + } + var retVal = item._attribs[attribute]; + return retVal ? ((retVal.length !== undefined && typeof(retVal) !== "string") ? retVal : [retVal]) : undefined; + }, + + getAttributes: function(/* item */ item) { + // summary: + // Return an array of attribute names + // description: + // 'item' must be have been created by the AtomReadStore instance. + // tag names of child elements and XML attribute names of attributes + // specified to the element are returned along with special attribute + // names applicable to the element including "tagName", "childNodes" + // if the element has child elements, "text()" if the element has + // child text nodes, and attribute names in '_attributeMap' that match + // the tag name of the element. + // item: + // An XML element + // returns: + // An array of attributes found + this._assertIsItem(item); + if(!item._attribs){ + this._initItem(item); + this._parseItem(item); + } + var attrNames = []; + for(var x in item._attribs){ + attrNames.push(x); + } + return attrNames; //array + }, + + hasAttribute: function(/* item */ item, /* attribute || attribute-name-string */ attribute){ + // summary: + // Check whether an element has the attribute + // item: + // 'item' must be created by the AtomReadStore instance. + // attribute: + // An attribute of an Atom Entry item. + // returns: + // True if the element has the attribute, otherwise false + return (this.getValue(item, attribute) !== undefined); //boolean + }, + + containsValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* anything */ value){ + // summary: + // Check whether the attribute values contain the value + // item: + // 'item' must be an instance of a dojox.data.XmlItem from the store instance. + // attribute: + // A tag name of a child element, An XML attribute name or one of + // special names + // returns: + // True if the attribute values contain the value, otherwise false + var values = this.getValues(item, attribute); + for(var i = 0; i < values.length; i++){ + if((typeof value === "string")){ + if(values[i].toString && values[i].toString() === value){ + return true; + } + }else if (values[i] === value){ + return true; //boolean + } + } + return false;//boolean + }, + + isItem: function(/* anything */ something){ + // summary: + // Check whether the object is an item (XML element) + // item: + // An object to check + // returns: + // True if the object is an XML element, otherwise false + if(something && something.element && something.store && something.store === this){ + return true; //boolean + } + return false; //boolran + }, + + isItemLoaded: function(/* anything */ something){ + // summary: + // Check whether the object is an item (XML element) and loaded + // item: + // An object to check + // returns: + // True if the object is an XML element, otherwise false + return this.isItem(something); //boolean + }, + + loadItem: function(/* object */ keywordArgs){ + // summary: + // Load an item (XML element) + // keywordArgs: + // object containing the args for loadItem. See dojo.data.api.Read.loadItem() + }, + + getFeatures: function() { + // summary: + // Return supported data APIs + // returns: + // "dojo.data.api.Read" and "dojo.data.api.Write" + var features = { + "dojo.data.api.Read": true + }; + return features; //array + }, + + getLabel: function(/* item */ item){ + // summary: + // See dojo.data.api.Read.getLabel() + if((this.label !== "") && this.isItem(item)){ + var label = this.getValue(item,this.label); + if(label && label.text){ + return label.text; + }else if (label){ + return label.toString(); + }else{ + return undefined; + } + } + return undefined; //undefined + }, + + getLabelAttributes: function(/* item */ item){ + // summary: + // See dojo.data.api.Read.getLabelAttributes() + if(this.label !== ""){ + return [this.label]; //array + } + return null; //null + }, + + getFeedValue: function(attribute, defaultValue){ + // summary: + // Non-API method for retrieving values regarding the Atom feed, + // rather than the Atom entries. + var values = this.getFeedValues(attribute, defaultValue); + if(dojo.isArray(values)){ + return values[0]; + } + return values; + }, + + getFeedValues: function(attribute, defaultValue){ + // summary: + // Non-API method for retrieving values regarding the Atom feed, + // rather than the Atom entries. + if(!this.doc){ + return defaultValue; + } + if(!this._feedMetaData){ + this._feedMetaData = { + element: this.doc.getElementsByTagName("feed")[0], + store: this, + _attribs: {} + }; + this._parseItem(this._feedMetaData); + } + return this._feedMetaData._attribs[attribute] || defaultValue; + }, + + _initItem: function(item){ + // summary: + // Initializes an item before it can be parsed. + if(!item._attribs){ + item._attribs = {}; + } + }, + + _fetchItems: function(request, fetchHandler, errorHandler) { + // summary: + // Retrieves the items from the Atom XML document. + var url = this._getFetchUrl(request); + if(!url){ + errorHandler(new Error("No URL specified.")); + return; + } + var localRequest = (!this.sendQuery ? request : null); // use request for _getItems() + + var _this = this; + var docHandler = function(data){ + _this.doc = data; + var items = _this._getItems(data, localRequest); + var query = request.query; + if(query) { + if(query.id) { + items = dojo.filter(items, function(item){ + return (_this.getValue(item, "id") == query.id); + }); + } else if(query.category){ + items = dojo.filter(items, function(entry) { + var cats = _this.getValues(entry, "category"); + if(!cats){ + return false; + } + return dojo.some(cats, "return item.term=='"+query.category+"'"); + }); + } + } + + if (items && items.length > 0) { + fetchHandler(items, request); + } + else { + fetchHandler([], request); + } + }; + + if (this.doc) { + docHandler(this.doc); + }else{ + var getArgs = { + url: url, + handleAs: "xml"//, + // preventCache: true + }; + var getHandler = dojo.xhrGet(getArgs); + getHandler.addCallback(docHandler); + + getHandler.addErrback(function(data){ + errorHandler(data, request); + }); + } + }, + + _getFetchUrl: function(request){ + if(!this.sendQuery){ + return this.url; + } + var query = request.query; + if(!query){ + return this.url; + } + if(dojo.isString(query)){ + return this.url + query; + } + var queryString = ""; + for(var name in query){ + var value = query[name]; + if(value){ + if(queryString){ + queryString += "&"; + } + queryString += (name + "=" + value); + } + } + if(!queryString){ + return this.url; + } + //Check to see if the URL already has query params or not. + var fullUrl = this.url; + if(fullUrl.indexOf("?") < 0){ + fullUrl += "?"; + }else{ + fullUrl += "&"; + } + return fullUrl + queryString; + }, + + _getItems: function(document, request) { + // summary: + // Parses the document in a first pass + if(this._items){ + return this._items; + } + var items = []; + var nodes = []; + + if(document.childNodes.length < 1){ + this._items = items; + console.log("dojox.data.AtomReadStore: Received an invalid Atom document. Check the content type header"); + return items; + } + + var feedNodes = dojo.filter(document.childNodes, "return item.tagName && item.tagName.toLowerCase() == 'feed'"); + + var query = request.query; + + if(!feedNodes || feedNodes.length != 1){ + console.log("dojox.data.AtomReadStore: Received an invalid Atom document, number of feed tags = " + (feedNodes? feedNodes.length : 0)); + return items; + } + + nodes = dojo.filter(feedNodes[0].childNodes, "return item.tagName && item.tagName.toLowerCase() == 'entry'"); + + if(request.onBegin){ + request.onBegin(nodes.length); + } + + for(var i = 0; i < nodes.length; i++){ + var node = nodes[i]; + if(node.nodeType != 1 /*ELEMENT_NODE*/){ + continue; + } + items.push(this._getItem(node)); + } + this._items = items; + return items; + }, + + close: function(/*dojo.data.api.Request || keywordArgs || null */ request){ + // summary: + // See dojo.data.api.Read.close() + }, + +/* internal API */ + + _getItem: function(element){ + return { + element: element, + store: this + }; + }, + + _parseItem: function(item) { + var attribs = item._attribs; + var _this = this; + var text, type; + + function getNodeText(node){ + var txt = node.textContent || node.innerHTML || node.innerXML; + if(!txt && node.childNodes[0]){ + var child = node.childNodes[0]; + if (child && (child.nodeType == 3 || child.nodeType == 4)) { + txt = node.childNodes[0].nodeValue; + } + } + return txt; + } + function parseTextAndType(node) { + return {text: getNodeText(node),type: node.getAttribute("type")}; + } + dojo.forEach(item.element.childNodes, function(node){ + var tagName = node.tagName ? node.tagName.toLowerCase() : ""; + switch(tagName){ + case "title": + attribs[tagName] = { + text: getNodeText(node), + type: node.getAttribute("type") + }; break; + case "subtitle": + case "summary": + case "content": + attribs[tagName] = parseTextAndType(node); + break; + case "author": + var nameNode ,uriNode; + dojo.forEach(node.childNodes, function(child){ + if(!child.tagName){ + return; + } + switch(child.tagName.toLowerCase()){ + case "name":nameNode = child;break; + case "uri": uriNode = child; break; + } + }); + var author = {}; + if(nameNode && nameNode.length == 1){ + author.name = getNodeText(nameNode[0]); + } + if(uriNode && uriNode.length == 1){ + author.uri = getNodeText(uriNode[0]); + } + attribs[tagName] = author; + break; + case "id": attribs[tagName] = getNodeText(node); break; + case "updated": attribs[tagName] = dojo.date.stamp.fromISOString(getNodeText(node) );break; + case "published": attribs[tagName] = dojo.date.stamp.fromISOString(getNodeText(node));break; + case "category": + if(!attribs[tagName]){ + attribs[tagName] = []; + } + attribs[tagName].push({scheme:node.getAttribute("scheme"), term: node.getAttribute("term")}); + break; + case "link": + if(!attribs[tagName]){ + attribs[tagName] = []; + } + var link = { + rel: node.getAttribute("rel"), + href: node.getAttribute("href"), + type: node.getAttribute("type")}; + attribs[tagName].push(link); + + if(link.rel == "alternate") { + attribs["alternate"] = link; + } + break; + default: + break; + } + }); + }, + + _unescapeHTML : function(text) { + //Replace HTML character codes with their unencoded equivalents, e.g. ’ with ' + text = text.replace(/’/m , "'").replace(/″/m , "\"").replace(/</m,">").replace(/>/m,"<").replace(/&/m,"&"); + return text; + }, + + _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("dojox.data.AtomReadStore: 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("dojox.data.AtomReadStore: Invalid attribute argument."); + } + } +}); +dojo.extend(dojox.data.AtomReadStore,dojo.data.util.simpleFetch); + +} |