/**
 * @(#)rssajax.js  1.0.1  2011-07-01
 *
 * Copyright (c) 2010-2011 Werner Randelshofer
 * Hausmatt 10, CH-6405 Immensee, Switzerland
 * All rights reserved.
 *
 * The copyright of this software is owned by Werner Randelshofer. 
 * You may not use, copy or modify this software, except in  
 * accordance with the license agreement you entered into with  
 * Werner Randelshofer. For details see accompanying license terms. 
 *
 *
 * Original code by Paul Sobocinski. 
 * "RSS and AJAX: A Simple News Reader"
 * http://www.xml.com/pub/a/2006/09/13/rss-and-ajax-a-simple-news-reader.html?page=1
 */


/** A Simple News Reader
 *
 * @version 1.0 2010-07-12 Adapted from original code.
 */

//OBJECTS

// Hack for poor IE browser
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt /*, from*/)
  {
    var len = this.length;

    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}

//objects inside the RSS2Item object
function RSS2Enclosure(encElement)
{
	if (encElement == null)
	{
		this.url = null;
		this.length = null;
		this.type = null;
	}
	else
	{
		this.url = encElement.getAttribute("url");
		this.length = encElement.getAttribute("length");
		this.type = encElement.getAttribute("type");
	}
}

function RSS2Guid(guidElement)
{
	if (guidElement == null)
	{
		this.isPermaLink = null;
		this.value = null;
	}
	else
	{
		this.isPermaLink = guidElement.getAttribute("isPermaLink");
		this.value = guidElement.childNodes[0].nodeValue;
	}
}

function RSS2Source(souElement)
{
	if (souElement == null)
	{
		this.url = null;
		this.value = null;
	}
	else
	{
		this.url = souElement.getAttribute("url");
		this.value = souElement.childNodes[0].nodeValue;
	}
}

function extractText(elem) {
	var text = (typeof(elem.nodeValue)=='string')?elem.nodeValue:"";
	for (var j=0; j<elem.childNodes.length; j++) {
		text += extractText(elem.childNodes[j]);
	}
	return text;
}

//object containing the RSS 2.0 item
function RSS2Item(itemxml)
{
	//required
	this.title;
	this.link;
	this.description;

	//optional vars
	this.author;
	this.comments;
	this.pubDate;

	//optional objects
	this.categories = [];
	this.enclosure;
	this.guid;
	this.source;

	var properties = new Array("title", "link", "description", "author", "comments", "pubDate");
	var tmpElement = null;
	for (var i=0; i<properties.length; i++)
	{
		tmpElement = itemxml.getElementsByTagName(properties[i]);
		if (tmpElement != null) tmpElement=tmpElement[0];
		if (tmpElement != null && tmpElement.childNodes.length> 0) {
		  this[properties[i]]=extractText(tmpElement);
		}
	}

	var categoryElements = itemxml.getElementsByTagName("category");
	for (var i=0; i<categoryElements.length; i++)
	{
		this.categories.push(new RSS2Category(categoryElements[i]));
	}

	this.enclosure = new RSS2Enclosure(itemxml.getElementsByTagName("enclosure")[0]);
	this.guid = new RSS2Guid(itemxml.getElementsByTagName("guid")[0]);
	this.source = new RSS2Source(itemxml.getElementsByTagName("source")[0]);
}

//objects inside the RSS2Channel object
function RSS2Category(catElement)
{
	if (catElement == null)
	{
		this.domain = null;
		this.value = null;
	}
	else
	{
		this.domain = catElement.getAttribute("domain");
		this.value = catElement.childNodes[0].nodeValue;
	}
}

//object containing RSS image tag info
function RSS2Image(imgElement)
{
	if (imgElement == null)
	{
	this.url = null;
	this.link = null;
	this.width = null;
	this.height = null;
	this.description = null;
	}
	else
	{
		imgAttribs = new Array("url","title","link","width","height","description");
		for (var i=0; i<imgAttribs.length; i++)
			if (imgElement.getAttribute(imgAttribs[i]) != null)
				eval("this."+imgAttribs[i]+"=imgElement.getAttribute("+imgAttribs[i]+")");
	}
}

//object containing the parsed RSS 2.0 channel
function RSS2Channel(rssxml)
{
	//required
	this.title;
	this.link;
	this.description;

	//array of RSS2Item objects
	this.items = new Array();

	//optional vars
	this.language;
	this.copyright;
	this.managingEditor;
	this.webMaster;
	this.pubDate;
	this.lastBuildDate;
	this.generator;
	this.docs;
	this.ttl;
	this.rating;

	//optional objects
	this.category;
	this.image;

	var chanElement = rssxml.getElementsByTagName("channel")[0];
	var itemElements = rssxml.getElementsByTagName("item");

	for (var i=0; i<itemElements.length; i++)
	{
		Item = new RSS2Item(itemElements[i]);
		this.items.push(Item);
		//chanElement.removeChild(itemElements[i]);
	}

	var properties = new Array("title", "link", "description", "language", "copyright", "managingEditor", "webMaster", "pubDate", "lastBuildDate", "generator", "docs", "ttl", "rating");
	if (chanElement != null) {
		var tmpElement = null;
	  for (var i=0; i<properties.length; i++) {
			tmpElement = chanElement.getElementsByTagName(properties[i]);
			if (tmpElement != null) tmpElement=tmpElement[0];
			if (tmpElement!= null && tmpElement.childNodes.length> 0) {
				eval("this."+properties[i]+"=tmpElement.childNodes[0].nodeValue");
			}
		}
		this.category = new RSS2Category(chanElement.getElementsByTagName("category")[0]);
		this.image = new RSS2Image(chanElement.getElementsByTagName("image")[0]);
	}
}

//PROCESSES
/*uses xmlhttpreq to get the raw rss xml
*
* If the suplied divid is "chan", then the HTML document must have 
* a div with the following contents:
*
*	<div class="rss" id="chan">
*	</div>
*
*
*@param rssurl the URL of the rss stream
*@param divid  the ID of the DIV element into which we insert the data
*@param maxItems  the maximal number of items to display, specify -1 for all items
*@param maxText  the maximal text length, specify -1 for full length
*@param categories  an array with category names, specify null for all categories
*/
function getRSS(rssURL, divId, maxItems, maxText, categories)
{
	
	//call the right constructor for the browser being used
	var xhr = null;
	if (window.ActiveXObject) {
		xhr = new ActiveXObject("Microsoft.XMLHTTP");
	} else if (window.XMLHttpRequest) {
		xhr = new XMLHttpRequest();
	}
	if (xhr==null) {
		showRSSError(rssURL, divId, 'XMLHttpRequest not supported' );
		return;
	}

	//prepare the xmlhttprequest object
	try {
		xhr.open("GET",rssURL,true);
	} catch (err) { 
		showRSSError(rssURL, divId, err.description );
		return;
	}
	xhr.setRequestHeader("Cache-Control", "no-cache");
	xhr.setRequestHeader("Pragma", "no-cache");
	xhr.onreadystatechange = function() {
		if (xhr.readyState == 4) {
			if (xhr.status == 200) {
				if (xhr.responseXML != null) {
					processRSS(rssURL, xhr.responseXML, divId, maxItems, maxText, categories);
				} else { /* request failed */
					showRSSError(rssURL, divId, 'empty or non-XML response' );
				}
			} else {
				showRSSError(rssURL, divId, "XMLHttpRequest failed: "+xhr.status + ", " + xhr.statusText);
			}
		}
	}

	//send the request
	try {
		xhr.send(null);
	} catch (err) {
		showRSSError(rssURL, divId, err.description );
		return;
	}
}

function showRSSError(rssURL, divId, msg) {
	var divElem = document.getElementById(divId); 
	
	// If the div element does not exist yet, we wait until
	// the document has been loaded, and retry.
	if (divElem == null) {
		var fn = function() {
			showRSSError(rssURL, divId, msg);
			if (window.removeEventListener) { 
				window.removeEventListener('load', fn ,false);
			} else { // for poor IE:
				window.detachEvent('onload', fn);
			}
		};
		if (window.addEventListener) {
			window.addEventListener('load', fn, false);
		} else { // for poor IE:
			window.attachEvent('onload', fn);
		}
		return;
	}
	
	var html = '<p class="footer2"><a href="'+rssURL+'" class="rss" title="'+msg+'">RSS</a>';
	divElem.innerHTML=html;
}


//processes the received rss xml
function processRSS(rssURL, rssxml, divId, maxItems, maxText, categories)
{
	RSS = new RSS2Channel(rssxml);
	showRSS(rssURL, RSS, divId, maxItems, maxText, categories);
}

//shows the RSS content in the browser
function showRSS(rssURL, RSS, divId, maxItems, maxText, categories)
{
		var divElem = document.getElementById(divId); 
	
	// If the div element does not exist yet, we wait until
	// the document has been loaded, and retry.
	if (divElem == null) {
		var fn = function() {
			showRSS(rssURL, RSS, divId, maxItems, maxText, categories);
			if (window.removeEventListener) {
				window.removeEventListener('load', fn ,false);
			} else { // for poor IE:
				window.detachEvent('onload', fn);
			}
		};
		if (window.addEventListener) {
			window.addEventListener('load', fn, false);
		} else { // for poor IE:
			window.attachEvent('onload', fn);
		}
		return;
	}

	//
	if (typeof(maxItems) != 'number' || maxItems < 0) { maxItems=99999; }
	if (typeof(maxText) != 'number' || maxText < 0) { maxText=99999; }
	if (typeof(categories) != 'object' || categories.length == 0) { categories=null; }
	
	//default values for html tags used
	var startRSS = "<article>";
	var endRSS = "</article>";
	var startChannel = "<header><p>";
	var endChannel = "</p></header>";
	var startChannelTitle = "<h4>";
	var endChannelTitle = "</h4>";
	var startDate = "<footer><div class='footer4'>";
	var endDate = "</div></footer>";
	var startChannelCopyright = "<div>";
	var imageTag = "<img class='channelImage'";
	var startItem = "<article><div class='article4'>";
	var endItem = "</div></article>";
	var startTitle = "<h4>";
	var endTitle = "</h4>";
	var startLink = "<div class='itemLink'>";
	var startAPart1 = "<a href='"
	var startAPart2 = "'>";
	var endA = "</a>";
	var startDescription = "<div>";
	var endDescription = "</div>";
	var endTag = "</div>";

	var html = startRSS;

	//populate channel data
	
	html = startChannel;
	html += (RSS.link == null) ? "" : startAPart1 + RSS.link + startAPart2;
	html += (RSS.title == null) ? "" : startChannelTitle + RSS.title + endChannelTitle;
	html += (RSS.link == null) ? "" : endA;
	html += (RSS.description == null) ? "" : startDescription + RSSformatText(RSS.description, maxText) + endDescription;
	html += (RSS.copyright == null) ? "" : startChannelCopyright + RSS.copyright + endTag;
	html += (RSS.pubDate == null) ? "" : startDate + RSSformatDate(RSS.pubDate) + endDate;
	html += endChannel;
	
	// erase the channel date - we don't want it here
	html = startRSS;

	//show the image
	/*
	if (RSS.image.src != null)
	{
		document.getElementById(""+divid+"_image_link").href = RSS.image.link;
		document.getElementById(""+divid+"_image_link").innerHTML = imageTag
			+" alt='"+RSS.image.description
			+"' width='"+RSS.image.width
			+"' height='"+RSS.image.height
			+"' src='"+RSS.image.url
			+"' "+"/>";
	}*/

	//populate the items
	var n = (RSS.items.length <= maxItems) ? RSS.items.length :maxItems;
	for (var i=0, count=0; i<RSS.items.length && count<n; i++)
	{
		// Filter items which are not in the desired categories
		if (categories!=null) {
			var j;
			for (j=0; 
				 j< RSS.items[i].categories.length 
				 && categories.indexOf(RSS.items[i].categories[j].value) == -1;
				 j++) {	}
			if (j == RSS.items[i].categories.length) continue;
		}
		
		html += startItem;
		html += (RSS.items[i].title == null) ? "" : startTitle;
		html += (RSS.items[i].link == null) ? "" : startAPart1 + RSS.items[i].link + startAPart2;
		html += (RSS.items[i].title == null) ? "" : RSS.items[i].title;
		html += (RSS.items[i].link == null) ? "" : endA;
		html += (RSS.items[i].title == null) ? "" : endTitle;
		if (maxText > 0) {
			html += (RSS.items[i].description == null) ? "" : startDescription + RSSformatText(RSS.items[i].description, maxText) + endDescription;
		}
		html += (RSS.items[i].pubDate == null) ? "" : startDate + RSSformatDate(RSS.items[i].pubDate) + endDate;
		html += endItem;
		count++;
	}

	//we're done
	html += endRSS;
	
	html += '<p class="footer2"><a href="'+rssURL+'" class="rss">RSS</a>';
	
	
	
	divElem.innerHTML = html;
	//document.getElementById("chan").style.visibility = "visible";
	return true;
}

/** Ensures that the text is not longer than maxText. */
function RSSformatText(text, maxText) {
	if (text.length <= maxText) {
		return text;
	} else {
		var p = Math.max(text.lastIndexOf(' ',maxText),text.lastIndexOf('.',maxText));
		if (p==-1) p = maxText;
		return text.substring(0, p)+" [...]";
	}	
}
/** Formats a date string. */
function RSSformatDate(text) {
	var d = new Date(text);
	var str= d.toLocaleDateString();
	/*
	var str= d.toLocaleString();
	var p; 
	if (-1 != (p = str.indexOf(" GMT"))) { str = str.substring(0,p); }
	if (-1 != (p = str.indexOf(" UTC"))) { str = str.substring(0,p); }
	if (-1 != (p = str.indexOf(" MESZ"))) { str = str.substring(0,p); }
	if (-1 != (p = str.indexOf(" MEZ"))) { str = str.substring(0,p); }*/
	return str;
}




