diff -r 315255cd1aef -r 20be4dd42b12 mypackage_wrt/FeedUpdateBroker.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mypackage_wrt/FeedUpdateBroker.js Fri Apr 30 15:01:03 2010 +0100 @@ -0,0 +1,180 @@ +/////////////////////////////////////////////////////////////////////////////// +// The FeedUpdateBroker class implements a simple RSS fetcher and parser. +// Adapted from WRTKit RssReader example + +// Constructor. +function FeedUpdateBroker() { + this.httpReq = null; + this.feedAddress = null; + this.callback = null; + this.ignoreContent = false; + this.cancelled = false; + this.responseParser = this.handleRssResponse; + this.startFromItem = 0; + this.maxItems = 0; +} + +// Fetches a feed from the specified URL and calls the callback when the feed +// has been fetched and parsed, or if the process results in an error. +FeedUpdateBroker.prototype.doFetchFeed = function(){ + // create new XML HTTP request + this.httpReq = new Ajax(); + + // set callback + var self = this; + this.httpReq.onreadystatechange = function() { self.readyStateChanged(); }; + + // initiate the request + this.httpReq.open("GET", nocache(this.feedAddress), true); + this.httpReq.send(null); +} + +// has been fetched and parsed, or if the process results in an error. +FeedUpdateBroker.prototype.fetchFeed = function(feedURL, callback) { + // remember callback + this.callback = callback; + this.feedAddress = feedURL; + this.doFetchFeed(); +} + +// Callback for ready-state change events in the XML HTTP request. +FeedUpdateBroker.prototype.readyStateChanged = function() { + // complete request? + if (this.httpReq.readyState == 4) { + // attempt to get response status + var responseStatus = null; + try { + responseStatus = this.httpReq.status; + } catch (noStatusException) {} + + // are we being prompted for login? + var text = this.httpReq.responseText; + if ( isLoginPrompt (text) ) { + var self = this; +// setTimeout(self.doFetchFeed(), 100); + login(function(){self.doFetchFeed();}); + return; + } + + // handle the response and call the registered callback object + var response = this.httpReq.responseXML; + if (response == null) { + // if the content type is not set correctly, we get the response as text + var xmlparser = new DOMParser(); + response = xmlparser.parseFromString(this.httpReq.responseText, "text/xml"); + } + this.callback.feedUpdateCompleted(this.handleResponse(responseStatus, response)); + } +} + +// Handles a completed response. +FeedUpdateBroker.prototype.handleResponse = function(responseStatus, xmlDoc){ + if (this.responseParser == null) { + return this.handleRssResponse(responseStatus, xmlDoc); + } + else { + return this.responseParser.call(this, this, responseStatus, xmlDoc); + } +} + + +FeedUpdateBroker.prototype.handleRssResponse = function(broker, responseStatus, xmlDoc){ + if ( this.cancelled ) { + return { status: "cancelled" }; + } + if (responseStatus == 200 && xmlDoc != null) { + // node ref for iterating + var node; + + // get last modified time - default to current time + var lastModified = new Date().getTime(); + var channelElements = xmlDoc.getElementsByTagName("channel"); + if (channelElements.length > 0) { + node = channelElements[0].firstChild; + while (node != null) { + if (node.nodeType == Node.ELEMENT_NODE) { + if (node.nodeName == "pubDate" || + node.nodeName == "lastBuildDate" || + node.nodeName == "dc:date") { + lastModified = getTextOfNode(node); + break; + } + } + node = node.nextSibling; + } + } + + // init feed items array + var items = []; + + // we got the feed XML so now we'll parse it + var itemElements = xmlDoc.getElementsByTagName("item"); + + for (var i = this.startFromItem; i < itemElements.length; i++) { + if ( this.maxItems > 0 && this.maxItems < i ) { + break; + } + // iterate through child nodes of this item and gather + // all the data we need for a feed item + var title = null; + var date = null; + var description = null; + var url = null; + var author = null; + node = itemElements[i].firstChild; + while (node != null) { + if (node.nodeType == Node.ELEMENT_NODE) { + if (node.nodeName == "title") { + // item title + title = getTextOfNode(node); + } else if (node.nodeName == "pubDate" || node.nodeName == "dc:date") { + // item publishing date + date = getTextOfNode(node); + } else if (node.nodeName == "description" && !this.ignoreContent ) { + // item description + description = getTextOfNode(node); + } else if (node.nodeName == "link") { + // link URL + url = getTextOfNode(node); + } else if (node.nodeName == "dc:creator" ) { + author = getTextOfNode(node); + } + } + node = node.nextSibling; + } + + // create the item and add to the items array + items.push({ title: title, date: date, description: description, url: url, author: author }); + } + + // update was completed successfully + return { status: "ok", lastModified: lastModified, items: items }; + } else { + // update failed + return { status: "error" }; + } +} + +// Returns the text of a node. +function getTextOfNode(node) { + var buf = ""; + // iterate through all child elements and collect all text to the buffer + var child = node.firstChild; + while (child != null) { + if (child.nodeType == Node.TEXT_NODE || child.nodeType == Node.CDATA_SECTION_NODE) { + // append text to buffer + if (buf != "") { + buf += " "; + } + buf += child.nodeValue; + } + child = child.nextSibling; + } + + return buf; +} + +FeedUpdateBroker.prototype.cancel = function() { + this.cancelled = true; + this.httpReq.abort(); +}