| /* |
| Copyright (c) 2004-2006, The Dojo Foundation |
| All Rights Reserved. |
| |
| Licensed under the Academic Free License version 2.1 or above OR the |
| modified BSD license. For more information on Dojo licensing, see: |
| |
| http://dojotoolkit.org/community/licensing.shtml |
| */ |
| |
| dojo.provide("dojo.data.OpmlStore"); |
| dojo.require("dojo.data.core.Read"); |
| dojo.require("dojo.data.core.Result"); |
| dojo.require("dojo.lang.assert"); |
| dojo.require("dojo.json"); |
| |
| dojo.require("dojo.experimental"); |
| dojo.experimental("dojo.data.OpmlStore"); |
| // FIXME: The OpmlStore works in Firefox but does not yet work in IE. |
| |
| dojo.declare("dojo.data.OpmlStore", dojo.data.core.Read, { |
| /* summary: |
| * The OpmlStore implements the dojo.data.core.Read API. |
| */ |
| |
| /* examples: |
| * var opmlStore = new dojo.data.OpmlStore({url:"geography.opml"}); |
| * var opmlStore = new dojo.data.OpmlStore({url:"http://example.com/geography.opml"}); |
| */ |
| initializer: function(/* object */ keywordParameters) { |
| // keywordParameters: {url: String} |
| this._arrayOfTopLevelItems = []; |
| this._metadataNodes = null; |
| this._loadFinished = false; |
| this._opmlFileUrl = keywordParameters["url"]; |
| }, |
| |
| _assertIsItem: function(/* item */ item) { |
| if (!this.isItem(item)) { |
| throw new Error("dojo.data.OpmlStore: a function was passed an item argument that was not an item"); |
| } |
| }, |
| |
| _removeChildNodesThatAreNotElementNodes: function(/* node */ node, /* boolean */ recursive) { |
| var childNodes = node.childNodes; |
| if (childNodes.length == 0) { |
| return; |
| } |
| var nodesToRemove = []; |
| var i, childNode; |
| for (i = 0; i < childNodes.length; ++i) { |
| childNode = childNodes[i]; |
| if (childNode.nodeType != Node.ELEMENT_NODE) { |
| nodesToRemove.push(childNode); |
| } |
| }; |
| // dojo.debug('trim: ' + childNodes.length + ' total, ' + nodesToRemove.length + ' junk'); |
| for (i = 0; i < nodesToRemove.length; ++i) { |
| childNode = nodesToRemove[i]; |
| node.removeChild(childNode); |
| } |
| // dojo.debug('trim: ' + childNodes.length + ' remaining'); |
| if (recursive) { |
| for (i = 0; i < childNodes.length; ++i) { |
| childNode = childNodes[i]; |
| this._removeChildNodesThatAreNotElementNodes(childNode, recursive); |
| } |
| } |
| }, |
| |
| _processRawXmlTree: function(/* xmlDoc */ rawXmlTree) { |
| var headNodes = rawXmlTree.getElementsByTagName('head'); |
| var headNode = headNodes[0]; |
| this._removeChildNodesThatAreNotElementNodes(headNode); |
| this._metadataNodes = headNode.childNodes; |
| var bodyNodes = rawXmlTree.getElementsByTagName('body'); |
| var bodyNode = bodyNodes[0]; |
| this._removeChildNodesThatAreNotElementNodes(bodyNode, true); |
| |
| var bodyChildNodes = bodyNodes[0].childNodes; |
| for (var i = 0; i < bodyChildNodes.length; ++i) { |
| var node = bodyChildNodes[i]; |
| if (node.tagName == 'outline') { |
| this._arrayOfTopLevelItems.push(node); |
| } |
| } |
| }, |
| |
| get: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* value? */ defaultValue) { |
| // summary: See dojo.data.core.Read.get() |
| this._assertIsItem(item); |
| if (attribute == 'children') { |
| return (item.firstChild || defaultValue); |
| } else { |
| var value = item.getAttribute(attribute); |
| value = (value != undefined) ? value : defaultValue; |
| return value; |
| } |
| }, |
| |
| getValues: function(/* item */ item, /* attribute || attribute-name-string */ attribute) { |
| // summary: See dojo.data.core.Read.getValues() |
| this._assertIsItem(item); |
| if (attribute == 'children') { |
| var array = []; |
| for (var i = 0; i < item.childNodes.length; ++i) { |
| array.push(item.childNodes[i]); |
| } |
| return array; // Array |
| // return item.childNodes; // FIXME: this isn't really an Array |
| } else { |
| return [item.getAttribute(attribute)]; // Array |
| } |
| }, |
| |
| getAttributes: function(/* item */ item) { |
| // summary: See dojo.data.core.Read.getAttributes() |
| this._assertIsItem(item); |
| var attributes = []; |
| var xmlNode = item; |
| var xmlAttributes = xmlNode.attributes; |
| for (var i = 0; i < xmlAttributes.length; ++i) { |
| var xmlAttribute = xmlAttributes.item(i); |
| attributes.push(xmlAttribute.nodeName); |
| } |
| if (xmlNode.childNodes.length > 0) { |
| attributes.push('children'); |
| } |
| return attributes; // array |
| }, |
| |
| hasAttribute: function(/* item */ item, /* attribute || attribute-name-string */ attribute) { |
| // summary: See dojo.data.core.Read.hasAttribute() |
| return (this.getValues(item, attribute).length > 0); |
| }, |
| |
| containsValue: function(/* item */ item, /* attribute || attribute-name-string */ attribute, /* anything */ value) { |
| // summary: See dojo.data.core.Read.containsValue() |
| var values = this.getValues(item, attribute); |
| for (var i = 0; i < values.length; ++i) { |
| var possibleValue = values[i]; |
| if (value == possibleValue) { |
| return true; |
| } |
| } |
| return false; // boolean |
| }, |
| |
| isItem: function(/* anything */ something) { |
| return (something && |
| something.nodeType == Node.ELEMENT_NODE && |
| something.tagName == 'outline'); // boolean |
| }, |
| |
| isItemAvailable: function(/* anything */ something) { |
| return this.isItem(something); |
| }, |
| |
| find: function(/* object? || dojo.data.core.Result */ keywordArgs) { |
| // summary: See dojo.data.core.Read.find() |
| var result = null; |
| if (keywordArgs instanceof dojo.data.core.Result) { |
| result = keywordArgs; |
| result.store = this; |
| } else { |
| result = new dojo.data.core.Result(keywordArgs, this); |
| } |
| var self = this; |
| var bindHandler = function(type, data, evt) { |
| var scope = result.scope || dj_global; |
| if (type == "load") { |
| self._processRawXmlTree(data); |
| if (result.saveResult) { |
| result.items = self._arrayOfTopLevelItems; |
| } |
| if (result.onbegin) { |
| result.onbegin.call(scope, result); |
| } |
| for (var i=0; i < self._arrayOfTopLevelItems.length; i++) { |
| var item = self._arrayOfTopLevelItems[i]; |
| if (result.onnext && !result._aborted) { |
| result.onnext.call(scope, item, result); |
| } |
| } |
| if (result.oncompleted && !result._aborted) { |
| result.oncompleted.call(scope, result); |
| } |
| } else if(type == "error" || type == 'timeout') { |
| // todo: how to handle timeout? |
| var errorObject = data; |
| // dojo.debug("error in dojo.data.OpmlStore.find(): " + dojo.json.serialize(errorObject)); |
| if (result.onerror) { |
| result.onerror.call(scope, data); |
| } |
| } |
| }; |
| |
| if (!this._loadFinished) { |
| if (this._opmlFileUrl) { |
| var bindRequest = dojo.io.bind({ |
| url: this._opmlFileUrl, // "playlist.opml", |
| handle: bindHandler, |
| mimetype: "text/xml", |
| sync: (result.sync || false) }); |
| result._abortFunc = bindRequest.abort; |
| } |
| } |
| return result; // dojo.data.csv.Result |
| }, |
| |
| getIdentity: function(/* item */ item) { |
| // summary: See dojo.data.core.Read.getIdentity() |
| dojo.unimplemented('dojo.data.OpmlStore.getIdentity()'); |
| return null; |
| }, |
| |
| findByIdentity: function(/* string */ identity) { |
| // summary: See dojo.data.core.Read.findByIdentity() |
| dojo.unimplemented('dojo.data.OpmlStore.findByIdentity()'); |
| return null; |
| } |
| }); |
| |
| |