/*

**    ------------------------------------------------------------------------
**    Current Version 1.0.2
**    ------------------------------------------------------------------------

**    File: myAJAX.js
**    Created by: James Becker (http://www.ajaxlounge.com/)
**    Created on: 10-11-2005
**    Last modified: 12-11-2005
**
**	  For change log and updates see http://www.ajaxlounge.com/myAJAX
**
**	  Bug reports to: bugs.myajax@ajaxlounge.com

**    License Information:
**    -------------------------------------------------------------------------
**    Copyright (C) 2005 James Becker
**
**    This program is free software; you can redistribute it and/or modify it
**    under the terms of the GNU General Public License as published by the
**    Free Software Foundation; either version 2 of the License, or (at your
**    option) any later version.
**    
**    This program is distributed in the hope that it will be useful, but
**    WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
**    General Public License for more details.
**    
**    You should have received a copy of the GNU General Public License along
**    with this program; if not, write to the Free Software Foundation, Inc.,
**    59 Temple Place, Suite 330, Boston, MA 02111-1307 USA or http://www.gnu.org/

**    What is myAJAX:
**    -------------------------------------------------------------------------
**
**    MyAJAX has been produced to help in creating a stable object system from
**    which to launch your own AJAX programs. Examples are across the internet
**    are available for you to write your own handlers and HTTP request objects.
**    myAJAX is for people not wanting to write their own and wanting a rapid
**    deployment system straight from the web. [enjoy - James :)]

*/

function myAJAX(sInstance) {

	/*
	** NO VARS NEED TO BE HARD CODED
	** see http://www.ajaxlounge.com/myajax/ for instructions
	*/

	this.conn; // local holder for connection.
	this.sendMethod = "GET"; // By default all requests will be GET, to change use setMethod function.
	this.vars = Array(); // Variable holder, used to build GET querystring or POST vars.
	this.controlScript = ""; // The control script for which to send commands
	this.active = false; // ** internal var ** Is everthing ok?
	this.instance = ""; // ** internal var ** set on creation to point to self.

	this.responseText = ""; // Holder for response text from AJAX
	this.responseDOM = ""; // Holder for DOM object from AJAX
	this.TXTparser = ""; // pointer to function that parses the response from myAJAX.
	this.DOMparser = ""; // pointer to function that parses the DOM object from myAJAX.
	
	this.HTTPfailcode = ""; // Set on HTTP failure.
	
	/* ----------------------------------------------
	// FUNCTION myAJAX
	// Constructor Function fired at start.
	-----------------------------------------------*/

	this.myAJAX = function () {
		if(sInstance == undefined) {
			document.write("<b>MyAJAX</b> <i>Instance name required.</i><br>");
			this.active = false;
			return false;
		} else {
			this.instance = sInstance;
			this.active = true;
		}
	}
	

	/* ----------------------------------------------
	// FUNCTION getResponse
	// Retreive responded text from connection.
	-----------------------------------------------*/

	this.getResponse = function () {
		if(this.responseText == "") {
			return false;
		} else {
			return this.responseText;
		}
	}
	
	/* ----------------------------------------------
	// FUNCTION getDOMobject
	// Retreive responded DOM object from connection.
	-----------------------------------------------*/

	this.getDOMobject = function () {
		if(typeof(this.responseDOM) == "object") {
			return(this.responseDOM);
		} else {
			return(false);
		}
	}

	/* ----------------------------------------------
	// FUNCTION setMethod ( string Method [POST|GET] )
	// Use to change the connection method.
	-----------------------------------------------*/
	
	this.setMethod = function () {
		if(arguments.length == 0 || arguments.length > 1) {
			return false;
		} else {
			tMethod = arguments[0].toUpperCase();
			
			if(tMethod != "POST" && tMethod != "GET") {
				return false;
			} else {
				this.sendMethod = tMethod;
				return true;
			}
		}
	}
	
	/* ----------------------------------------------
	// FUNCTION clearVars
	// clear the entire array stack.
	// ** WILL KILL ALL stored vars **
	-----------------------------------------------*/

	this.clearVars = function () {
		if(this.vars.length > 0) {
			this.vars = Array();
			return(true);
		} else {
			return(false);
		}	
	}

	
	/* ----------------------------------------------
	// FUNCTION assign ( mixed ( Array | string Key, string Value ) )
	// Assign variables to myAJAX.
	// Assign vars to myAJAX in the form of [key=>value]
	-----------------------------------------------*/
	
	this.assign = function () {
		if(arguments.length == 0) {
			return false;
		} else {
			for(var i = 0; i < arguments.length; i++) {
				if(typeof(arguments[i]) == "object" && arguments[i].length > 0) {
					for(var aryWalk = 0; aryWalk < arguments[i].length; aryWalk++) {
						var tVar = arguments[i][aryWalk];
						if(tVar.indexOf("=>")) {
							var tHolder = tVar.split("=>");
							if(tHolder.length > 2) {
								document.write("<b>MyAJAX</b>: <i>Assign Error: key,value match too big</i> <b>[Error Key: " + aryWalk + "]</b>");
								return false;
							} else {
								this.vars.push({ key: tHolder[0], value: tHolder[1] });
							}
						} else {
						}
					}
				}
				else if(typeof(arguments[i]) == "string") {
					var tVar = arguments[i];
					
					if(tVar.indexOf("=>")) {
						var tHolder = tVar.split("=>");
						if(tHolder.length > 2) {
							document.write("<b>MyAJAX</b>: <i>Assign Error: key,value match too big</i> <b>[Error Key: " + aryWalk + "]</b>");
							return false;
						} else {
							this.vars.push({ key: tHolder[0], value: tHolder[1] });
						}
					} else {
						document.write("<b>MyAJAX</b>: <i>Assign Error: key,value match error</i> <b>[Error Key: " + aryWalk + "]</b>");
						return false;
					}
				}
			}
		}
	}


	/* ----------------------------------------------
	// FUNCTION setTXTParser ( FUNCTION )
	// Sets the internal pointer to [FUNCTION] for
	// parsing the text response.
	-----------------------------------------------*/

	this.setTXTParser = function () {
		if(arguments.length != 1) {
			document.write("<b>MyAJAX</b>: <i>Required: Function</i>");
			return false;
		} else {
			if(typeof(arguments[0]) == "function") {
				this.TXTparser = arguments[0];
				return true;
			} else {
				document.write("<b>MyAJAX</b>: <i>Parameter [1] not of type FUNCTION</i>");
				return false;
			}
		}
	}

	/* ----------------------------------------------
	// FUNCTION setDOMParser ( FUNCTION )
	// Sets the internal pointer to [FUNCTION] for
	// parsing the DOM response object.
	-----------------------------------------------*/

	this.setDOMParser = function () {
		if(arguments.length != 1) {
			document.write("<b>MyAJAX</b>: <i>Required: Function</i>");
			return false;
		} else {
			if(typeof(arguments[0]) == "function") {
				this.DOMparser = arguments[0];
				return true;
			} else {
				document.write("<b>MyAJAX</b>: <i>Parameter [1] not of type FUNCTION</i>");
				return false;
			}
		}
	}

	/* ----------------------------------------------
	// FUNCTION HTTPsuccess
	// ** Internal function - DO NOT CALL Externally **
	// Used for on completion of AJAX call.
	-----------------------------------------------*/

	this.HTTPsuccess = function () {
	
		this.responseText = this.conn.responseText;
		this.responseDOM = this.conn.responseXML;
		
		if(typeof(this.TXTparser) == "function") {
			this.TXTparser();
		}
		
		if(typeof(this.DOMparser) == "function") {
			this.DOMparser();
		}

	}
	
	/* ----------------------------------------------
	// FUNCTION HTTPfailure
	// ** Internal function - DO NOT CALL Externally **
	// Sets the failure of myAJAX to the HTTP return code.
	// Use myAJAX.onFail() to check for failure
	-----------------------------------------------*/

	this.HTTPfailure = function () {
		this.HTTPfailcode = this.conn.status;
	}

	/* ----------------------------------------------
	// FUNCTION onFail
	// returns ( int failcode | FALSE )
	-----------------------------------------------*/

	this.onFail = function () {
		if(this.HTTPfailcode != 0) {
			return(this.HTTPfailcode);
		} else {
			return(false);
		}
	}
	
	
	/* ----------------------------------------------
	// FUNCTION showVars
	// Dump all vars to console
	-----------------------------------------------*/

	this.showVars = function () {
		var qs = "?";
		
		if(this.vars.length > 0) {
			for( var i = 0; i < this.vars.length; i++) {
				document.write("<b>[" + i + "]</b> <i>Key:</i> " + this.vars[i].key + " <i>Value:</i> " + this.vars[i].value + "<br>");
				qs += this.vars[i].key + "=" + this.vars[i].value + "&";
			}
			document.write(((this.controlScript) ? this.controlScript : "<b>Querystring:</b> ") + qs.substr(0,qs.length-1));
		} else {
			document.write("<b>MyAJAX</b>: <i>No variables assigned</i>");
		}
	}	
	
	/* ----------------------------------------------
	// FUNCTION setControl ( string URL ) )
	// Assign the control script to myAJAX
	-----------------------------------------------*/
	
	this.setControl = function (sScript) {
		this.controlScript = sScript;
	}

	/* ----------------------------------------------
	// FUNCTION buildQuery
	// ** Internal function - DO NOT CALL Externally **
	// returns built query for myAJAX to send.
	-----------------------------------------------*/
	
	this.buildQuery = function () {
		var qs = "";
		
		if(this.vars.length > 0) {
			for( var i = 0; i < this.vars.length; i++) {
				qs += this.vars[i].key + "=" + this.vars[i].value + "&";
			}
			
			return(qs.substr(0,qs.length-1));
		}
	}

	/* ----------------------------------------------
	// FUNCTION connect
	// use to connection up and run myAJAX on particular
	// page. Will send all vars assigned. Will terminate
	// returning fail on bad connection.
	// Returns: bool ( TRUE | FALSE )
	-----------------------------------------------*/
	
	this.connect = function () {

		if(this.active) {
			//check for running connections.
			if(this.conn != null && this.conn.readyState != 0 && this.conn.readyState != 4) {
				this.conn.abort();
			}
			
			// due to readystate not updating, create new object each time.
			try {
				this.conn = new XMLHttpRequest();
			} catch (error) {
				try {
					this.conn = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (error) {
					document.write("<b>MyAJAX</b>: <i>XML Http object could not be created.</i>");			
					this.conn = null;
					return false;
				}
			}
			
			//Build state handler function due to being in object.			
			e = "this.stateHandler = function () {";
			e += " oObj = " + this.instance + ";";
			e += " if(oObj.conn.readyState == 4) {";
			e += "	if(oObj.conn.status == 200) {";
			e += "		oObj.HTTPsuccess();";
			e += "	} else {";
			e += "		oObj.HTTPfailure();";
			e += "	}";
			e += " }";
			e += " }";
			
			eval(e);
			
			if(this.sendMethod == "POST") {
				// POST Request
				this.conn.open(this.sendMethod,this.controlScript,false);
				this.conn.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded', true);
				this.conn.onreadystatechange = this.stateHandler;
				this.conn.send(this.buildQuery());
			} else {
				// GET Request
				this.conn.open(this.sendMethod, this.controlScript + "?" + this.buildQuery(), true);
				this.conn.onreadystatechange = this.stateHandler;
				this.conn.send(null);
			}
		} else {
			document.write("<b>MyAJAX</b>: <i>Instance <b>" + this.instance + "</b> is disabled. check configuration</i>");
			return(false);
		}
	}

	//init myAJAX
	//** internal call **
	this.myAJAX();
}
