/* 

version 1.1
This code is an object oriented version of the the xmlhttprequest.js file.

change log
version 1.0 - initial release
version 1.0.1 - 5/21/2007 - fixed bug in parseForm method
version 1.1 - 11/9/2009 - added ability to parse json
*/

function ajaxObj() {
	var xmlreturntype = false;
	var debug = false;
	var processingPage = "";
	var functionAfter = "";
	
	this.setDebug = setDebug;
	this.getXML = getXML;
	this.done = done;
	this.start = start;
	this.checkXMLError = checkXMLError;
	this.makeQuery = makeQuery;
	this.parseFormData = parseFormData;
	this.xmlDoNothing = xmlDoNothing;
	this.setProcessing = setProcessing
	this.setFunctionAfter = setFunctionAfter;
	this.setReturnType = setReturnType;
	this.getData = getData;
	this.returnHTML = returnHTML;
	this.returnXML = returnXML;
	this.parseJson = parseJson;
	this.returnJson = returnJson;
	this.execute = execute;
	
	function returnHTML() {
		this.setReturnType(true);	
	}
	function returnXML() {
		this.setRetrunType(false);
	}
	function returnJson() {
		this.returnHTML();	
	}
	function setReturnType(v) {
		this.xmlreturntype = v;
	}
	function execute(qs,type) {
		if(typeof(type)) {
			
		}
		
		this.getXML(qs)
	}
	function setProcessing(page) {
		this.processingPage = page;	
	}
	function setFunctionAfter(f) {
		this.functionAfter = f;	
	}
	function setDebug(status) {
		this.debug = status;
	}
	function getXML(queryString){
		//alert(typeof(this.functionAfter));
		if(typeof(this.functionAfter) == "undefined" || this.functionAfter == "") {
			alert("Please specify a function to run after");	
			return false;
		}
		if(typeof(this.processingPage) == "undefined" || this.processingPage == "") {
			alert("Please specify a processing page");
			return false;	
		}
		functionAfter = this.functionAfter;
		processingPage = this.processingPage
		xmlreturntype = this.xmlreturntype;
		debug = this.debug;
		
		//change the cursor to an hourglass.
		var xmlHttpReq;
		//If the user is using Mozilla or Safari, then we simply need to use XMLHttpRequest as a native function
		if(window.XMLHttpRequest){
			xmlHttpReq = new XMLHttpRequest();
			
		}
		//however, Internet Explorer requires this element be created using ActiveX
		else if(window.ActiveXObject) {
			xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
		}
		//and if the user is unable to create the XMLHttpRequest object, then show an alert stating why and exit the function 
		else	{
			alert("Your browser does not support the technology used in this webpage.  Please use the latest versions of Internet Explorer, Safari, Mozilla, or FireFox");
			return false;
		}
		//set the mimetype based on the type requested
		if(xmlHttpReq.overrideMimeType){
			switch(this.xmlreturntype) {	
				case true:
					xmlHttpReq.overrideMimeType('text/plain');
					//alert("setting return type to plain");
					break;
				default:
					xmlHttpReq.overrideMimeType('text/xml');
					break;
			}
		}
		//open the object, selecting to send the data via an HTTP post method and directing it to go to the php page that
		//will process the request
		xmlHttpReq.open('POST',processingPage,true);
		xmlHttpReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		xmlHttpReq.onreadystatechange = function() {
			//as soon as the readyState is 4, then the function is complete and we want to execute the code inside
			if(xmlHttpReq.readyState == 4) {
				//if the status is 2, then the process completed successfully, so call the function
				if(debug) { alert(xmlHttpReq.responseText);  }
				
				if(xmlHttpReq.status == 200) {
					
					if(!xmlreturntype) {
						eval(functionAfter + "(xmlHttpReq.responseXML.documentElement);");
					}
					else {
						eval(functionAfter + "(xmlHttpReq.responseText);");
					}
				}
				//otherwise, display an error message.
				else {
					alert("An error occurred processing this request.  Please try again.\n\nIf the error continues, please contact the webmaster\n\n" + xmlHttpReq.status + " - " + xmlHttpReq.statusText);
				}
			}
		}
		//send the string
		if(xmlHttpReq.send(queryString)) {
			return true;
		}
		else {
			return false;
		}
	
	}
	
	function done() {
		document.body.style.cursor = "default";	
	}
	function start() {
		document.body.style.cursor = "wait";
	}
	
	function checkXMLError(theXML) {
		var errors = new Array();
		var count = 0;
		xml_errors = theXML.getElementsByTagName("error");
		//check if any errros were returned
		if(xml_errors.length>0) {
			//loop through those errors
			for(i=0;i<xml_errors.length;i++) {
				//and if there is any data to display
				if(xml_errors[i].firstChild) {
					//assign it to the errors array.
					errors[i] = xml_errors[i].firstChild.nodeValue;
					count++;
				}
			}
		}
		return errors;
	}
	
	//loop through a form to get the values of all the elements
	function makeQuery(theForm) {
		//initialize the querystring
		var queryString = "";
		
		var radios = new Array();
		var selects = new Array();
		//loop through all the elements
		for(i=0;i<theForm.elements.length;i++) {
			//get the current element
			elem = theForm.elements[i];
	
			switch(elem.type) {
				//if the element is a textbox, textarea or hidden field,
				//then just append the element name and value to the query string
				case "text":
				case "textarea":
				case "hidden":
				case "password":
					queryString += encodeURIComponent(elem.name) + "=" + encodeURIComponent(elem.value) + "&";
					break;
				//if it's a checkbox
				case "checkbox":
					//first assign the element name to the query string
					queryString += encodeURIComponent(elem.name) + "=";
					//and then check if it's checked.  If it is, then assign the value
					//of the checkbox to the querystring. If it's not, then the 
					//querystring will have a null value for this element.
					if(elem.checked) queryString += encodeURIComponent(elem.value); 
					queryString += "&";
					break;
				//radio element
				case "radio":
					/* radio buttons are a little tricky.  even though the user can check only
					   one, the script will still see all the radio buttons.  So, somehow
					   the script needs to keep track whether a radio button in the group 
					   was checked.  This is done using the radios array.  If the radio button
					   is checked, then radios[elem.name] is set to true to indicate that is was
					   checked.  Otherwise, if that radio button has not been added to the radios
					   array yet, the radio button is added to the array and the value is set to
					   false.  After the form element loop is complete, the radios array will determine
					   if any of the radio groups did not have a checked element and add at least
					   the radio button's name to the query string.  By doing this, the processing PHP 
					   script will know that the radio button was at least a part of the form.*/
					if(elem.checked) {
						
						queryString += encodeURIComponent(elem.name) + "=" + encodeURIComponent(elem.value) + "&";
						radios[elem.name] = true;
					}
					else if(!radios[elem.name]) { radios[elem.name] = false; }
					break;
				//a drop down menu that allows only one option to be selected
				case "select-one":
					queryString += encodeURIComponent(elem.name) + "=";
					//loop through the options to determine which one is selected
					for(x=0;x<elem.options.length;x++) {
						//if the current option is selected, then assign the value of that
						//option to the query string
						if(elem.options[x].selected) { queryString += elem.options[x].value; }
					}
					queryString += "&";
					break;
				//need to figure out how to do this one
				case "select-multiple":
					break;
				//need to figure out how to do this one
				case "file":
					break;
				
			}
		}
		
		//now that the form element loop is done, check all the radio elements to see if any of
		//them are not part of the querystring.  If radios[elemname] is false, then
		//it's not a part of the querystring
		var elemname;
		for(elemname in radios) {
			if(!radios[elemname]) { queryString += encodeURIComponent(elemname) + "=" + "&"; }
		}
		
		//alert(queryString);
		return queryString;
	}
	//this function will take the passed xml chunk, and 
	//created an associated array
	function getData(xmlData) {
		var data = new Array();
		for(x=0;x<xmlData.childNodes.length;x++) {
			if(xmlData.childNodes[x].nodeType != 1) continue;
			else {
				//get the tagname of the current child
				tagName = xmlData.childNodes[x].tagName;
				
				//if(this.debug) { alert("tagName = " + tagName); }
				//and assign it to the data array
				if(xmlData.childNodes[x].firstChild) {
					
					value = xmlData.childNodes[x].firstChild.nodeValue;
					//if(this.debug) { alert("firstChild.nodeValue=" + value); }
				}
				else {
					value = "";
					//if(this.debug) { alert("blank value"); }
				}
				data[tagName] = value
				
			}
		}
		//if(this.debug) {alert(data); }
		return data;
	}
	//this function will take the passed xml chunk, and match up
	//the corresponding form element to populate the form.
	function parseFormData(xmlData,f) {
		var value;
		
		for(x=0;x<xmlData.childNodes.length;x++) {
			if(xmlData.childNodes[x].nodeType != 1) continue;
			else {
				//get the tagname of the current child
				tagName = xmlData.childNodes[x].tagName;
				//alert("tagName = " + tagName);
				//and assign it to the data array
				if(xmlData.childNodes[x].firstChild) {
					value = xmlData.childNodes[x].firstChild.nodeValue;
				}
				else {
					value = "";
				}
				
				//check if there is a form element for this tag
				
				if(f.elements[tagName]) {
					elem = f.elements[tagName];
					//alert(elem.type + " - " + value);
					//alert(elem.type);
					//it's a radio button but only if there are no options (because
					//select objects have length also)
					if(elem.length && !elem.options) {
						if(elem[0].type == "radio") {
							//alert("You have found a radio button - " + elem.length);
							for(y=0;y<elem.length;y++) {
								
								if(elem[y].value == value) { elem[y].checked = true; }
							}
						}
							
					}
					else {
						
						switch(elem.type) {
							
							case "textarea":
							case "text":
							case "hidden":
								elem.value = value;
								break;
							case "select-one":
								
								for(y=0;y<elem.options.length;y++) {
									if(elem.options[y].value == value) { elem.options[y].selected = true; }	
								}
								break;
							case "checkbox":
								if(elem.value == value) { elem.checked = true; }
								break;
							
						}
					}
				}
			}
			
		}
	}
	
	//this function is meant to be called when no action is needed with the 
	//returned xml
	function xmlDoNothing(theXML) {
		
	}
	
	function parseJson(jsonText) {
		return eval('(' + jsonText + ')');
	}

}