mypackage_wrt/FeedUpdateBroker.js
changeset 42 20be4dd42b12
--- /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();
+}