Wikipedia/FeedUpdateBroker.js
changeset 20 918767a9c8d3
equal deleted inserted replaced
19:f3521a11d878 20:918767a9c8d3
       
     1 ///////////////////////////////////////////////////////////////////////////////
       
     2 // The FeedUpdateBroker class implements a simple RSS fetcher and parser.
       
     3 // Adapted from WRTKit RssReader example
       
     4 
       
     5 // Constructor.
       
     6 function FeedUpdateBroker() {
       
     7     this.httpReq = null;
       
     8     this.feedAddress = null;
       
     9     this.callback = null;
       
    10 	this.ignoreContent = false;
       
    11 	this.cancelled = false;
       
    12 	this.responseParser = this.handleRssResponse;
       
    13 	this.startFromItem = 0;
       
    14 	this.maxItems = 0;
       
    15 }
       
    16 
       
    17 // Fetches a feed from the specified URL and calls the callback when the feed
       
    18 // has been fetched and parsed, or if the process results in an error.
       
    19 FeedUpdateBroker.prototype.doFetchFeed = function(){    
       
    20     // create new XML HTTP request
       
    21     this.httpReq = new Ajax();
       
    22     
       
    23     // set callback
       
    24     var self = this;
       
    25     this.httpReq.onreadystatechange = function() { self.readyStateChanged(); };
       
    26 
       
    27     // initiate the request
       
    28     this.httpReq.open("GET", nocache(this.feedAddress), true);
       
    29     this.httpReq.send(null);
       
    30 }
       
    31 
       
    32 // has been fetched and parsed, or if the process results in an error.
       
    33 FeedUpdateBroker.prototype.fetchFeed = function(feedURL, callback) {
       
    34     // remember callback
       
    35     this.callback = callback;
       
    36     this.feedAddress = feedURL;
       
    37 	this.doFetchFeed();
       
    38 }
       
    39 
       
    40 // Callback for ready-state change events in the XML HTTP request.
       
    41 FeedUpdateBroker.prototype.readyStateChanged = function() {
       
    42     // complete request?
       
    43     if (this.httpReq.readyState == 4) {
       
    44         // attempt to get response status
       
    45         var responseStatus = null;
       
    46         try {
       
    47             responseStatus = this.httpReq.status;
       
    48         } catch (noStatusException) {}
       
    49         
       
    50 		// are we being prompted for login?
       
    51 		var text = this.httpReq.responseText;
       
    52 		
       
    53         // handle the response and call the registered callback object
       
    54 		var response = this.httpReq.responseXML;
       
    55 		if (response == null) {
       
    56 			// if the content type is not set correctly, we get the response as text
       
    57 			var xmlparser = new DOMParser();
       
    58 		    response = xmlparser.parseFromString(this.httpReq.responseText, "text/xml");
       
    59 		}
       
    60         this.callback.feedUpdateCompleted(this.handleResponse(responseStatus, response));
       
    61     }
       
    62 }
       
    63 
       
    64 // Handles a completed response.
       
    65 FeedUpdateBroker.prototype.handleResponse = function(responseStatus, xmlDoc){
       
    66 	if (this.responseParser == null) {
       
    67 		return this.handleRssResponse(responseStatus, xmlDoc);
       
    68 	}
       
    69 	else {
       
    70 		return this.responseParser.call(this, this, responseStatus, xmlDoc);
       
    71 	}	
       
    72 }
       
    73 
       
    74 
       
    75 FeedUpdateBroker.prototype.handleRssResponse = function(broker, responseStatus, xmlDoc){
       
    76 	if ( this.cancelled ) {
       
    77         return { status: "cancelled" };
       
    78 	}
       
    79     if (responseStatus == 200 && xmlDoc != null) {
       
    80         // node ref for iterating
       
    81         var node;
       
    82         
       
    83         // get last modified time - default to current time
       
    84         var lastModified = new Date().getTime();
       
    85         var channelElements = xmlDoc.getElementsByTagName("channel");
       
    86         if (channelElements.length > 0) {
       
    87             node = channelElements[0].firstChild;
       
    88             while (node != null) {
       
    89                 if (node.nodeType == Node.ELEMENT_NODE) {
       
    90                     if (node.nodeName == "pubDate" ||
       
    91                             node.nodeName == "lastBuildDate" ||
       
    92                             node.nodeName == "dc:date") {
       
    93                         lastModified = getTextOfNode(node);
       
    94                         break;
       
    95                     }
       
    96                 }
       
    97                 node = node.nextSibling;
       
    98             }
       
    99         }
       
   100         
       
   101         // init feed items array
       
   102         var items = [];
       
   103         
       
   104         // we got the feed XML so now we'll parse it
       
   105         var itemElements = xmlDoc.getElementsByTagName("item");
       
   106 		
       
   107         for (var i = this.startFromItem; i < itemElements.length; i++) {
       
   108 			if ( this.maxItems > 0 && this.maxItems < i ) {
       
   109 				break;
       
   110 			}
       
   111             // iterate through child nodes of this item and gather
       
   112             // all the data we need for a feed item
       
   113             var title = null;
       
   114             var date = null;
       
   115             var description = null;
       
   116             var url = null;
       
   117             var author = null;
       
   118             node = itemElements[i].firstChild;
       
   119             while (node != null) {
       
   120                 if (node.nodeType == Node.ELEMENT_NODE) {
       
   121                     if (node.nodeName == "title") {
       
   122                         // item title
       
   123                         title = getTextOfNode(node);
       
   124                     } else if (node.nodeName == "pubDate" || node.nodeName == "dc:date") {
       
   125                         // item publishing date
       
   126                         date = getTextOfNode(node);
       
   127                     } else if (node.nodeName == "description" && !this.ignoreContent ) {
       
   128                         // item description
       
   129                         description = getTextOfNode(node);
       
   130                     } else if (node.nodeName == "link") {
       
   131                         // link URL
       
   132                         url = getTextOfNode(node);
       
   133                     } else if (node.nodeName == "dc:creator" ) {
       
   134 						author = getTextOfNode(node);
       
   135 					}
       
   136                 }
       
   137                 node = node.nextSibling;
       
   138             }
       
   139             
       
   140             // create the item and add to the items array
       
   141             items.push({ title: title, date: date, description: description, url: url, author: author });
       
   142         }
       
   143         
       
   144         // update was completed successfully
       
   145         return { status: "ok", lastModified: lastModified, items: items };
       
   146     } else {
       
   147         // update failed
       
   148         return { status: "error" };
       
   149     }
       
   150 }
       
   151 
       
   152 // Returns the text of a node.
       
   153 function getTextOfNode(node) {
       
   154     var buf = "";
       
   155 	// iterate through all child elements and collect all text to the buffer
       
   156 	var child = node.firstChild;
       
   157 	while (child != null) {
       
   158 		if (child.nodeType == Node.TEXT_NODE || child.nodeType == Node.CDATA_SECTION_NODE) {
       
   159 			// append text to buffer
       
   160 			if (buf != "") {
       
   161 				buf += " ";
       
   162 			}
       
   163 			buf += child.nodeValue;
       
   164 		}
       
   165 		child = child.nextSibling;
       
   166 	}
       
   167 	
       
   168 	return buf;
       
   169 }
       
   170 
       
   171 FeedUpdateBroker.prototype.cancel = function() {
       
   172 	this.cancelled = true;
       
   173 	this.httpReq.abort();
       
   174 }