// Title: ajax
// Version: 1
// Last Modify: 8 Jan 2008, kc

// Update History:
//	11 May, 2009	Added rss link


var type;				//Type of browser we are using
var xmlhttp=false;
var xmlhttp2=false;
var updated;

function xml2text(xmlNode)
{
  try {
    // Gecko-based browsers, Safari, Opera.
    return (new XMLSerializer()).serializeToString(xmlNode);
  }
  catch (e) {
    try {
      // Internet Explorer.
      return xmlNode.xml;
    }
    catch (e)
    {//Strange Browser ??
     alert('Xmlserializer not supported');
    }
  }
  return false;
}

function text2xml(inText,typeStr) {
	if (typeStr == null) {
		typeStr = "application/xml"	
	}
		
	xmlDoc = null;
	if (document.all) {
		try //Internet Explorer
		  {
		  xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		  xmlDoc.async="false";
		  xmlDoc.loadXML(inText);
		  }
		catch(e)
		  {
		  	alert(e.message);
		  }
	} else {
	  try //Firefox, Mozilla, Opera, etc.
	    {
	    parser=new DOMParser();
	    xmlDoc=parser.parseFromString(inText,typeStr);
	    }
	  catch(e) {alert(e.message)}
	}
	return xmlDoc;
}

function initAjaxVars() {
	if (navigator.userAgent.indexOf("Opera")!=-1
	   	 && document.getElementById) type="OP"; 
	if (document.all) type="IE"; 
	if (document.layers) type="NN"; 
	if (!document.all && document.getElementById) type="MO"; 

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/
	if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
	  xmlhttp = new XMLHttpRequest();
	}

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp2 = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp2 = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp2 = false;
  }
 }
@end @*/
	if (!xmlhttp2 && typeof XMLHttpRequest!='undefined') {
	  xmlhttp2 = new XMLHttpRequest();
	}

}

initAjaxVars();

// pass the URL to get data from, pass the posting data, a unique ID in theID
// additionally, pass a reference to a function that will accept an ID and the responseText.
// the unique ID is used to match a response to a request.
function ajaxPost(theURL, theDATA, theID, callFunc) {
	//load up an ajax call to save the data for this doc
	xmlhttp.open("POST", theURL+"&rn="+Math.random(),true);
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4) {
			callFunc(theID, xmlhttp.responseText);
		}
	 }
	xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
	xmlhttp.setRequestHeader("Content-Length", theDATA.length);
	xmlhttp.send(theDATA);
}

// pass the URL to get data from, a unique ID in theID
// additionally, pass a reference to a function that will accept an ID and the responseText.
// the unique ID is used to match a response to a request.
function ajaxGet(theURL, theID, callFunc) {
	xmlhttp.open("GET", theURL+"&rn="+Math.random(),true);
	xmlhttp.onreadystatechange=function() {
		if (xmlhttp.readyState==4) {
			callFunc(theID, xmlhttp.responseText);
		}
	 }
 	xmlhttp.send(null);
 	ignoreSave = false;
}


// the following are our synchronous calls for get and post
function sjaxGet(theURL) {
	if (window.XMLHttpRequest) {
		AJAX=new XMLHttpRequest();
	} else {
		AJAX=new ActiveXObject("Microsoft.XMLHTTP");
	}
	if (AJAX) {
		AJAX.open("GET", theURL+"&rn="+Math.random(), false);
		AJAX.send(null);
		return AJAX.responseText;
	} else {
		return false;
	}
}

function sjaxPost(theURL, theDATA) {
	if (window.XMLHttpRequest) {
		AJAX=new XMLHttpRequest();
	} else {
		AJAX=new ActiveXObject("Microsoft.XMLHTTP");
	}
	if (AJAX) {
		AJAX.open("GET", theURL+"&rn="+Math.random(), false);
		xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
		xmlhttp.setRequestHeader("Content-Length", theDATA.length);
		AJAX.send(theDATA);
		return AJAX.responseText;
	} else {
		return false;
	}
}

// rss feed client
rssHost = "ajxData.4sp?type=rss&url=";

	/*
		displayRSS(URI,hideTitle,includeDescr,rssDivID,theHost,mainObj,subObj,subLink,linkImage)
		URI				the url of the RSS feed we are retriving
		hideTitle		whether or not to show the title of the feed at the top of the news list
		includeDescr	show the descr for each news item lime
		rssDivID		what ID to put the results into
		theHost			url of the function taht is actually making the call to get the RRS data
		mainObj			tag type of the new item (default is ul)
		subObj			tag type of the description item (default is li)
		subLink			is the description a child of news title (default is false)
		linkImage		name of image to show to right of news title item(s)
	*/
function displayRSS(URI,hideTitle,includeDescr,rssDivID,theHost,mainObj,subObj,subLink,linkImage) {
	var mydiv;
	var rssxmlhttp=false;
	if (rssDivID != null) {
		mydiv  = document.getElementById(rssDivID);
	} else {
		mydiv  = document.getElementById("rss");
	}
	if (theHost == null) {
		theHost = rssHost;
	}
	if (mainObj==null) mainObj = "ul";
	if (subObj==null) subObj = "li";
	
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  rssxmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   rssxmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   rssxmlhttp = false;
  }
 }
@end @*/
	if (!rssxmlhttp && typeof XMLHttpRequest!='undefined') {
	  rssxmlhttp = new XMLHttpRequest();
	}
	URI = URI.replaceAll("&","%26");
	URI = URI.replaceAll("?","%3F");
	//alert(theHost+URI);
	rssxmlhttp.open("GET", theHost+URI, true);
	var ptag = document.createElement("p");
	ptag.appendChild(document.createTextNode("Loading RSS feed..."));
	//ptag.innerHTML = "<p>Loading RSS feed...</p>"
	mydiv.appendChild(ptag);
	rssxmlhttp.onreadystatechange=function() {
		if (rssxmlhttp.readyState==2) {
			// mydiv.appendChild(ptag);
		}
		if (rssxmlhttp.readyState==4) {
			var responseString = rssxmlhttp.responseText;
			//alert(responseString);
			xmlDoc = text2xml(responseString,"text/xml");
			
			items = xmlDoc;
			formatRSS();
			//mydiv.removeChild(ptag);
		}
	 }
	 rssxmlhttp.send(null);
	
		function formatRSS() {
			ptag.innerHTML = "";
			var items_count=items.getElementsByTagName('item').length;
			//alert(items.getElementsByTagName('item'));
			if(items_count == 0) {
				ptag.innerHTML = "Empty RSS feed or unsupported feed format."
				return;
			}
			var link=new Array();
			var title=new Array();
            var descr=new Array();
			for(var i=0; i<items_count; i++) {
				if(items.getElementsByTagName('item')[i].getElementsByTagName('link').length==1)
					link[i]=items.getElementsByTagName('item')[i].getElementsByTagName('link')[0];
				if(items.getElementsByTagName('item')[i].getElementsByTagName('title').length==1)
					title[i]=items.getElementsByTagName('item')[i].getElementsByTagName('title')[0];
				if(items.getElementsByTagName('item')[i].getElementsByTagName('description').length==1)
					descr[i]=items.getElementsByTagName('item')[i].getElementsByTagName('description')[0];
			}
			if(title.length==0) return false;
			if(! hideTitle) {
				h2=document.createElement("p");//was h2
				bloga = document.createElement("a");
				try {
					bloga.appendChild(document.createTextNode(xmlDoc.getElementsByTagName('title')[0].firstChild.nodeValue));
				} catch (err) {
					//
				}
				try {
					bloga.setAttribute("href",xmlDoc.getElementsByTagName("link")[0].firstChild.nodeValue);
				} catch (err) {
					//
				}
				h2.appendChild(bloga);
				h2.appendChild(document.createTextNode(" "));
	        	        rssa = document.createElement("a");
				h2.appendChild(rssa);
				rssa.setAttribute("href",URI);
				rssa.setAttribute("class","RSS");
				rssa.appendChild(document.createTextNode("RSS"));
				mydiv.appendChild(h2);
			}
			ul = document.createElement(mainObj);
			mydiv.appendChild(ul);
			for(var i=0; i<items_count; i++) {
				var title_w, link_w;
				title_w=(title.length>0)?title[i].firstChild.nodeValue:"<i>Untitled</i>";
				link_w=(link.length>0)?link[i].firstChild.nodeValue:"";
				descr_w=(descr.length>0)?descr[i].firstChild.nodeValue:"";
				
				imgObj = null;
				if (linkImage != null) {
					// it should be title, then the image
					imgObj = document.createElement("img");
					imgObj.src = linkImage;
				}
				litag = document.createElement(subObj);
                linktag =document.createElement("a");
				linktag.setAttribute("href",link_w);
				linktag.setAttribute("title",descr_w);
				linktag.setAttribute("target","_new");
				
				linktag.appendChild(document.createTextNode(title_w));
				if (imgObj != null) {
					linktag.appendChild(document.createTextNode(" "));
					linktag.appendChild(imgObj);
				}
				litag.appendChild(linktag);
                if (includeDescr) {
                
                    desctag=document.createElement("p");
                    desctag.appendChild(document.createTextNode(descr_w));
                    if (subLink) {
                    	litag.appendChild(desctag);
					}				
				}
                
                ul.appendChild(litag);
                if ((includeDescr) && (!subLink)) {
                	//ul.appendChild(desctag);
                	mydiv.appendChild(desctag);
                	ul = document.createElement(mainObj);
					mydiv.appendChild(ul);
                }
                
			}
		}
}


// this next function helps us keep a queue, create a var on your page with a blank URL using
// var yourVar = new loadData("","yourVar","")

// whenever data is needed, issue yourVar.storeNew(theURL,theID,callFunc,maxWaitSecs);
// then anywhere call yourVar.executeFirstItem()
// the function then will be repeatedly called until done

function loadData(theURL, theID, callFunc, maxWaitSecs) {
	// take thse params and add them to an array
	// after the page is loaded, executeFirstItem is called
	// when the data is received, the next item in the
	// array is processed, etc. and until the queue is empty
	var tickWait = 1000;	// 1 second
	
	this.urlList = new Array();
	this.idList = new Array();
	this.funcList = new Array();
	this.startedProcessing = new Array();
	this.maxWaitSecList = new Array();
	
	if (theURL == "") {
		this.varName = theID; // now I know the window's var name for timeout purposes
	}
	
	this.storeNew = function (theURL, theID, callFunc, maxWaitSecs) {
		var newPos = this.findID(theID);
		if (newPos < 0) newPos = this.urlList.length;
		this.urlList[newPos] = theURL;
		this.idList[newPos] = theID;
		this.funcList[newPos] = callFunc;
		this.startedProcessing[newPos] = null;
		if (maxWaitSecs == null) maxWaitSecs = 10;
		this.maxWaitSecList[newPos] = maxWaitSecs;
		if (this.getLength() == 1) {
			window.setTimeout("callQueue()",tickWait);
		}
	}

	this.getLength = function () {
		return(this.urlList.length);
	}

	this.removeTop = function () {
		// need to delete the first one
		this.urlList.splice(0,1);
		this.idList.splice(0,1);
		this.funcList.splice(0,1);
		this.startedProcessing.splice(0,1);
		this.maxWaitSecList.splice(0,1);
	}
	
	this.findID = function (theID) {
		var foundID = -1;
		for (var c = 1; c <= this.idList.length; c++) {
			if (this.idList[c-1] == theID) {
				foundID = c-1;
			}
		}
		return foundID;
	}
	
	this.removeID = function (theID) {
		foundID = this.findID(theID);
		if (foundID>= 0) {
			this.urlList.splice(foundID,1);
			this.idList.splice(foundID,1);
			this.funcList.splice(foundID,1);
			this.startedProcessing.splice(foundID,1);
			this.maxWaitSecList.splice(foundID,1);
			if (this.getLength() > 0) {
				//window.setTimeout("callQueue()",tickWait);
			}
		}
	}

	this.executeFirstItem = function () {
		// if there is an item, call getSomeData and remove the first item from the list, return true
		// else return false (no items)
		//alert("attempting");
		if (this.getLength() > 0) {
			//getSomeData(theURL, theID, callFunc)
			if (this.urlList[0] != "") {
				if (this.startedProcessing[0] == null) {
					ajaxGet(this.urlList[0],this.idList[0],this.funcList[0]);
					this.startedProcessing[0] = 1;
				} else {
					// the first item is waiting a result...do we give up, if so,
					// remove and make the next call...
					this.startedProcessing[0]++;
					if (this.startedProcessing[0] >= this.maxWaitSecList[0]) {	// 5 * 1 seconds is too long
						try {
							//alert("Removing request for "+this.urlList[0]);
							this.removeTop();	// kill it and move on
						}
						catch (err) {
							// they must have just removed it
						}
					}
				}
			}
			// let the receiver remove the top
			// this.removeTop();
			if (this.getLength() > 0) {
				window.setTimeout("callQueue()",tickWait);
			}
			return true;
		} else {
			// hmm, let's wait a bit and, when storeNew has a lenth of 1, it will start again
			return false;
		}
	}
	
	if (theURL != "") {
		this.storeNew(theURL, theID, callFunc, maxWaitSecs);
	}
}

