/**************************************************************************************************
LiveWeb

Assists in making live requests to a web page using XMLHTTP.  Use this to 
dynamically update content on your web page without reloading the browser.

Make sure you include the "debug.js" script in your page.

See the associated LiveWeb.htm for an example of how it works.
*/
document.write('<script type="text/javascript" src="https://scizors.c7.ixwebhosting.com/scripts/js/debug.js"></script>');


/**************************************************************************************************
* CONSTRUCTORS
*/

/*
LiveWeb Request
Assists with the server-side requests made by the LiveWeb class.
Parameters:
	XmlHttp	- the XmlHttp object of the request
	url		- the url of the request
	method	- the method of the request (GET or POST)
*/
function LiveWebRequest(XmlHttp, url, method) {
	this.xmlHttp = this.NewRequestObject();
	this.url = url;
	this.method = method;
}


//Determines what browser is being used and returns the appropriate XML HTTP object.
LiveWebRequest.prototype.NewRequestObject = function() {
	var xmlHttp = null;
	
	//If Opera...
	if (navigator.userAgent.indexOf("Opera") >= 0) {
		//Debug("Opera isn't supported by LiveWeb.");
	}
	//Else if IE...
	else if (navigator.userAgent.indexOf("MSIE") >= 0) { 
		try { 
			xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch(e) {
			try {
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch(e) { 
				alert("Error. Scripting for ActiveX might be disabled");
			}	
		}
	}
	//Else if Mozilla (Netscape or Firefox)...
	else if (navigator.userAgent.indexOf("Mozilla")>=0) {
		xmlHttp = new XMLHttpRequest();
	}
	
	return xmlHttp;
}


/*
LiveWeb Class definition
Parameters:
	func - a reference to a function that will be called when Get and Post requests return.
*/
function LiveWeb(func) {
	//Private variables.
	this.UserFunc = func;
	this.UserPost = "";
	this.VerboseErrors = false;
	
	//Declare our public methods and properties.
	this.Cache = false;						//Set to true to enable the browsers cache for GET requests.
	this.ReturnXML = false;					//Set to true to return an XML object instead of text.
	
	//Create our debug object.
	this.debug = new Debug();
}

/**************************************************************************************************
* PUBLIC METHODS
*/

//Performs a GET request to the server.
LiveWeb.prototype.Get = function(url) {
	this.SendRequest(url, "GET");
}
	
//Performs a POST request to the server.
LiveWeb.prototype.Post = function(url) {
	this.SendRequest(url, "POST");
}

//Sets a form field variable for use in a Post request.
LiveWeb.prototype.SetPost = function(name, value) {
	//Add the parameter to the POST request string.
	if (this.UserPost == "")
		this.UserPost = name + "=" + escape(value);
	else
		this.UserPost += "&" + name + "=" + escape(value);
}

//Sets the user-defined function that will be called when the request returns.
LiveWeb.prototype.SetFunc = function(func) {
	this.UserFunc = func;
}

/**************************************************************************************************
* PRIVATE METHODS
*/

/*
Called to initiate a request.
Parameters:
	url		- the url for the request
	method	- the type of request (GET or POST)
*/
LiveWeb.prototype.SendRequest = function(url, method) {
	var isPost = (method == "POST");
	var _this = this;					//used so "onreadystatechange" gets called within the context of this instance
	
	//If this is a GET request...
	if (!isPost) {
		this.UserPost = null;
		
		//See if caching is turned on or not.
		if (!this.Cache)
			url = url + "&livewebhash=" + getRandom();
	}
	
	//Create our LiveWebRequest object and create a new XMLHTTP object for the request.
	var req = new LiveWebRequest(url, method)
	
	//Start by opening our XMLHTTP object.
	req.xmlHttp.open(method, url , true);
	
	//Add the form content-type if we are doing a POST.
	if (isPost)
		req.xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	
	//Set the method that will be called when the request returns.  The use of "_this" is a workaround
	//that ensures the method stays within the context of this instance of the class.  The "_this"
	//variable is a reference to the current instance.
	req.xmlHttp.onreadystatechange = function() {
		//Make use of the LiveWebRequest object to pass info about this request to the StateChanged method.
		_this.StateChanged(req); 
	};
	
	//Send the request and clear our user POST parameters.
	req.xmlHttp.send(this.UserPost);
	this.UserPost = null;
	
	this.debug.Add(method + ": " + url + "<br />");
}


/*
Called when a request returns.  This calls the user-defined function in return.
Parameters:
	req - an instance of the LiveWebRequest class
*/
LiveWeb.prototype.StateChanged = function(req) { 
	if (req.xmlHttp.readyState == 4) { 
		
		//Catch a problem with Firefox when there is a heavy load.
		try {
			this.debug.Add('StateChanged: ' + req.xmlHttp.readyState + "<br />");
			req.xmlHttp.status;
		}
		catch(e) {
			return;
		}
		
		//If we have a successful request, run the user's function.
		if (req.xmlHttp.status == 200)
			this.UserFunc(true, (req.xmlHttp.ReturnXML ? req.xmlHttp.responseXML : req.xmlHttp.responseText));
		else {
			//Throw an error.
			var errors = "An error occurred retrieving the page contents.\nMethod: " + req.method + "\nURL: " + req.url + "\nStatus: " + req.xmlHttp.status + "\nDesc: " + req.xmlHttp.statusText;
			
			//If we are in verbose error mode, show the details of the error whether or not debugging is turned on.
			if (this.VerboseErrors)
				this.debug.Add(errors.replace(/\n/g, "<br />") + "<br />Details: " + req.xmlHttp.responseText + "<br /><br />");
			
			//Run the user's function, showing an error.
			this.UserFunc(false, errors);
		}
	}
}


//Returns a random number between 0 and 5000.  Used to make the url unique when getting around cached GET requests.
function getRandom() {
	return Math.floor(Math.random() * 99999);
}
