/**
* @projectDescription	A function-based AJAX library which also comes with useful XML functions such as #getNodeValue and #setNodeValue
*
* @author	Burak Yiğit KAYA	byk@amplio-vita.net
* @version	1.2
*
* @param	{String}	[AJAXParams["noAjax"]]	The error message which user will see if his/her browser does not support AJAX.
* @param	{String}	[AJAXParams["loadImgPath"]]	The "loading" gif's path, which might be used in various places.
* @param	{String}	[AJAXParams["loadingText"]]	The "loading" message which will be placed into a dynamically filled container while the content is being loaded.
* @param	{String}	[AJAXParams["pageLeaveWarning"]]	The warning message which will be displayed to user if (s)he tries to leave the page while an AJAX request is loading.
*/

var AJAXParams=new Object();
AJAXParams["noAjax"]="You need an AJAX supported browser to use this page."; //if you want to disable this warning, just set this to false;
AJAXParams["loadImgPath"]="images/loading_img.gif";
AJAXParams["loadingText"]="<br><center><img src=\"" + AJAXParams["loadImgPath"] + "\">Loading, please wait...</center>"; //if you want to disable this text, just set this to false;
//var dynamicContentRequest;
AJAXParams["pageLeaveWarning"]="There are one or more requests in progress. If you exit, there might be data loss."; //if you want to disable this warning, just set this to false;

var activeRequestCount=0;

function getRequestObject()
/**
* Tries to get the XMLHttpRequest object, returns false if the browser does not support AJAX.
* @return	{XMLHttpObject | false}
*/
{
	var requestObject = false;
	if(window.XMLHttpRequest && !(window.ActiveXObject))
	{
		try
		{
			requestObject = new XMLHttpRequest();
		}
		catch(e)
		{
			requestObject = false;
		}
	}
	else if(window.ActiveXObject)
	{
		try
		{
			requestObject = new ActiveXObject("Msxml2.XMLHTTP");
		}
		catch(e)
		{
			try
			{
				requestObject = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch(e)
			{
				requestObject = false;
			}
		}
	}
	return requestObject;
}

function abortNDestroyRequestObject(requestObject)
/**
* Destroys the given XMLHttpRequest object safely.
* Aborts the request if it is active.
* @method
* @param	{XMLHttpRequestObject}	requestObject
*/
{
	if (requestObject)
	{
		if ((requestObject.readyState!=4) && (requestObject.readyState!=0))
			requestObject.abort();
		delete requestObject;
	}
}

function confirmBeforeUnload()
/**
* This function is assigned to the page's onbeforeunload event for pageLeaveWarning feature.
* Should not be called directly.
* @return {String | null}
*/
{
	if (AJAXParams["pageLeaveWarning"] && activeRequestCount>0)
		return AJAXParams["pageLeaveWarning"];
}

/**
* getNodeValue, setNodeValue and collectionToArray functions are service functions for parsing the elementNode objects, which are mainly used in XML parsing.
*/
function getNodeValue(mainItem, nodeName, defaultVal)
/**
* Tries to extract the node value whose name is given with nodeName and is contained by mainItem node. Returns the defaultVal if any error occurs.
* @return	{String}
* @param	{Object}	mainItem	The main node item which holds the sub nodes and their values.
* @param	{String}	nodeName	Name of the sub node whose value will be extracted from the mainItem.
* @param	{String}	[defaultVal]	The default value which will be returned if the sub node whose name is given in nodeName is not found.
*/
{
	defaultVal=(defaultVal) ? defaultVal : "";
	var val;
	try
	{
		val=mainItem.getElementsByTagName(nodeName)[0].firstChild.nodeValue;
		val=(val!=undefined) ? val : defaultVal;
	}
	catch(e)
	{
		val=defaultVal;
	}
	finally
	{
		return val;
	}
}

function setNodeValue(mainItem, nodeName, val)
/**
* Tries to set the node value whose name is given with nodeName and is contained by mainItem node. Returns false if any error occurs.
* @method
* @return	{String}	The value set by the function is returned. If an error occures, the function returns false.
* @param	{Object}	mainItem	The main node item which holds the sub nodes and their values.
* @param	{String}	nodeName Name of the sub node whose value will be set.
* @param	{String}	val	The new value of the sub node whose name is given in nodeName.
*/
{
	try
	{
		mainItem.getElementsByTagName(nodeName)[0].firstChild.nodeValue=val;
		return val;
	}
	catch(e)
	{
		return false;
	}
}

function collectionToArray(collection)
/**
* Converts an element/node collection, which acts as an array usually, to an actual array and returns it, which allows developers to use array-spesific functions.
* @return	{Array}
* @param	{HTMLCollectionObject}	collection	The collection which will be converted to array.
*/
{
	result = new Array();
	for (i = 0; i < collection.length; i++)
		result.push(collection[i]);
	return result;
}

function makeAJAXGetRequest(adress, changeFunction)
/**
* Creates a new XMLHttpRequest object which connects to the adress, which includes the URI encoded and merged GET parameters.
* Assignes changeFunction to the newly created XMLHttpRequest object's onreadystatechange event.
* Frees the XMLHttpRequest object automatically after completing the call.
* @deprecated	Generally used internally from other high-level functions. Not very suitable for end-developers.
* @return {XMLHttpRequestObject}
* @param	{String}	adress	The adress of the page which will be connected. Should include the URI encoded GET parameters.
* @param	{Function(XMLHttpRequestObject)}	[changeFunction]	The function which will be assigned to the newly created XMLHttpRequest object's onreadystatechange event.
*/
{
	var resultRequest = getRequestObject(); //try to create an XMLHttpRequest object
	if (resultRequest) //if the XMLHttpRequest object is valid
	{
		resultRequest.open("GET", adress, true); //set the adress and HTTP method to GET
		resultRequest.onreadystatechange = function()
		{
			if (changeFunction) //if there is an assigned changeFunction, assign it to the onreadystatechange event specially, that it recieves the XMLHttpRequest object as its parameter		
				changeFunction(resultRequest);
			if (resultRequest.readyState==4)
			{
				activeRequestCount--;
				delete resultRequest;
			}
		};
		resultRequest.send(null); //start the request
		activeRequestCount++;
	}
	else if(AJAXParams["noAjax"]) //if cannot create a valid XMLHttpRequest object, inform user.
		alert(AJAXParams["noAjax"]);
	return resultRequest; //return the created XMLHttpRequest object for any further use
}

function makeAJAXPostRequest(adress, parameters, changeFunction)
/**
* Creates a new XMLHttpRequest object which connects to the adress, which includes the URI encoded and merged POST parameters.
* Assignes changeFunction to the newly created XMLHttpRequest object's onreadystatechange event.
* Frees the XMLHttpRequest object automatically after completing the call.
* @deprecated	Generally used internally from other high-level functions. Not very suitable for end-developers.
* @return {XMLHttpRequestObject}
* @param	{String}	adress	The adress of the page which will be connected. Should  NOT include any parameters.
* @param	{String}	parameters	The URI encoded and merged POST parameters for the HTTP request.
* @param	{Function(XMLHttpRequestObject)}	[changeFunction]	The function which will be assigned to the newly created XMLHttpRequest object's onreadystatechange event.
*/
{
	var resultRequest = getRequestObject(); //try to create a XMLHttpRequest object
	if (resultRequest) //if XMLHttpRequest object is valid
	{
		resultRequest.open("POST", adress, true); //set the adress and HTTP method to GET
		resultRequest.onreadystatechange = function()
		{
			if (changeFunction) //if there is an assigned changeFunction, assign it to the onreadystatechange event specially, that it recieves the XMLHttpRequest object as its parameter
				changeFunction(resultRequest);
			if (resultRequest.readyState==4)
			{
				activeRequestCount--;
				delete resultRequest;
			}
		};
		resultRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    resultRequest.setRequestHeader("Content-length", parameters.length);
    resultRequest.setRequestHeader("Connection", "close");
		//set some headers for POST method
		resultRequest.send(parameters); //send the request with parameters attached
		activeRequestCount++;
	}
	else if(AJAXParams["noAjax"]) //if cannot create a valid XMLHttpRequest object, inform user.
		alert(AJAXParams["noAjax"]); //start the request
	return resultRequest; //return the created XMLHttpRequest object for any further use
}

function comfortableAJAXRequest(method, adress, parameters, completedFunction, loadingFunction)
/**
* Takes "GET" or "POST" as method parameter and then according to this, creates a SELF-MANAGED
* XMLHttpRequest object using makeAJAXGetRequest or makeAJAXPostRequest according to the method parameter.
* Developers are strongly adviced to use THIS function instead of the above POST and GET specific functions.
* @return	{XMLHttpRequestObject}
* @param	{String}	method	Should be either POST or GET according to the type of the HTTP request.
* @param	{String}	adress	The adress of the page which will be connected. Should  NOT include any parameters.
* @param	{String|Object}	parameters	The parameters which are either URI encoded and merged or given in the following object format
*	{paramName1: "paramValue1",
*	 paramName2: "paramValue2",
*	 ...
*	}
* @param	{Function(XMLHttpRequestObject)}	[completedFunction]	The function which will be called when the HTTP call is completed. (readyState==4)
* @param	{Function(XMLHttpRequestObject)}	[loadingFunction]	The function which will be called EVERYTIME when an onreadystatechange event is occured with a readyState different than 4. Might be called several times before the call is completed.
*/
{
	var triggerFunction=function (requestObject) //define the custom changeFunction as triggerFunction
	{
		if (requestObject.readyState == 4 && completedFunction) //if the request is finished and there is a  completedFunction assigned
			completedFunction(requestObject); //call the completedFunction sending the requestObject as its parameter
		else if (loadingFunction) //if request is in progress and there is an assigned loadingFunction
			loadingFunction(requestObject); //call the loadingFunction passing the requestObject as its parameter
	}; //finished defining the custom changeFunction
	//checking parameters
	if (typeof parameters=='object')
	{
		var paramsTemp=parameters;
		parameters='';
		for (paramName in paramsTemp)
			parameters+='&' + paramName + '=' + encodeURIComponent(paramsTemp[paramName]);
			delete paramsTemp;
			parameters=parameters.substr(1);
	}
	
	if (method.toUpperCase()=="GET") //if requested method is GET, then call the makeAJAXGetRequest function
		return makeAJAXGetRequest(adress + ((parameters)?'?' + parameters:''), triggerFunction);
	else if (method.toUpperCase()=="POST") //else if requested method is POST, then call the makeAJAXPostRequest function
		return makeAJAXPostRequest(adress, parameters, triggerFunction);
	else //if requested method is invalid, return false
		return false;
}

function loadDynamicContent(theURL, element, completedFunction, loadingFunction)
/**
* Loads a dynamic content to the given container element.
* @result	{XMLHttpRequestObject}
* @param	{String}	theURL	The URL of the content which will be loaded dynamically into the given container.
* @param	{Strimg|Object}	element	The container element itself or its id, which the dynamic content will be loaded into.
* @param	{Function(Object, String)}	[completedFunction]	The function which will be called when the loading of the content is finished. It is called with the target container element and the URL as parameters.
* @param	{Function(Object, String)}	[loadingFunction]	The function which will be called EVERYTIME when an onreadystatechange event is occured with a readyState different than 4 while loading the dynamic content. It is called with the target container element and the URL as parameters.
*
* If the AJAXParams["loadingText"] is defined, target container element's innerHTML is filled with global variable AJAXParams["loadingText"] while the content is loading.
*/
{
	//abortNDestroyRequestObject(dynamicContentRequest);
	if (typeof(element)=='string') //if id of the object is given instead of the object itself
		element=document.getElementById(element); //assign the element the object corresponding to the given id
	var triggerFunc = function(requestObject) //define the custom changeFunction
	{
		if (requestObject.readyState == 4) //if the request is finished
		{
			element.innerHTML=requestObject.responseText; //fill the element's innerHTML with the returning data
			if (completedFunction) //if a callback function assigned to *callbackFunc*
				completedFunction(element, theURL); //call it with the element object and the given URL as its parameters
		}
		else
		{
			if (loadingFunction) //if a custom loadingFunction is assigned
				loadingFunction(element, theURL); //call it with the element object and the given URL as its parameters
			else if (AJAXParams["loadingText"])
				element.innerHTML=AJAXParams["loadingText"]; //set the given element's innerHTML the loading text to inform the user
		}
	};
	return (makeAJAXGetRequest(theURL, triggerFunc)); //make the GET request and return the used XMLHttpRequest object
}

window.onbeforeunload=confirmBeforeUnload;