// CONTAINER FOR ALL AJAX FUNCTIONALITY (HTTPRequest object and callback)
function js_ajax_Object(action, url, params, callback, retType) {
	// Initialising HTTPRequest object
	var req=js_ajax_Init();
	req.onreadystatechange=js_ajax_Request;
	// Creating parameter string to send with request
	var send_params=js_ajax_Params();
	
	
	// Initialises HTTPRequest object
	function js_ajax_Init() {
		try {
			// For non-microsoft browsers
			return new XMLHttpRequest();
		}
		catch(try_microsoft) {
			try {
				// A version of microsoft HttpRequest
				return new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch(try_othermicrosoft) {
				// Another version of microsoft HttpRequest
				return new ActiveXObject("Msxml2.XMLHTTP");
			}
		}
	}
	
	// Processes state changes and initialises callback
	function js_ajax_Request() {
		// readyState of 4 signifies request is complete
		if(req.readyState==4) {
			// status of 200 signifies sucessful HTTP call
			if(req.status==200) {
				if(callback) {
					// If a callback has been specified, determining return type format
					if(retType=="xml") {
						// Returning xml document
						callback(req.responseXML);
						req=null;
					}
					else {
						// Returning text string
						callback(req.responseText);
						req=null;
					}
				}
			}
			else {
				// Error handling
				js_ajax_Error();
			}
		}
	}
	
	// Generates query parameter string from params object
	function js_ajax_Params() {
		// Initialising locat params variable
		var p="";
		
		// Looping through params object
		for(var i in params) {
			// Creating value escaping special chars and plus sign
			var value=escape(String(params[i]));
			var value=value.replace(/\+/g, "%2B");
			
			// Generating query string for each item in object (as 'key=value&')
			p+=String(i)+"="+value+"&";
		}
		
		// Returning complete parameter string
		return p;
	}
	
	// Makes a HTTP GET request to the URL asynchronously
	this.js_ajax_Get=function() {
		// Generating URL for GET method (as url?params)
		var send_url=encodeURI(url+"?"+send_params);
		
		// Opening and sending request
		req.open("GET", send_url, true);
		req.send(null);
	}
	
	// Makes a HTTP POST request to the URL asynchronously
	this.js_ajax_Post=function() {
		// Opening request and setting headers
		req.open("POST", url, true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;");
		req.setRequestHeader("Content-length", send_params.length);
		req.setRequestHeader("Connection", "close");
		
		// Sending request with parameters
 		req.send(send_params);
	}
	
	// Executes on error in ajax request
	function js_ajax_Error() {
		// This function must be handled in the calling page
		if(window.js_callback_Error) {
			js_callback_Error(req.status);
		}
		
		// Mails error log
		//js_ajax_MailError(req.status, req.statusText, action, url, send_params);
		req=null;
	}
}

// SENDS OUT AN ERROR LOG BY EMAIL
function js_ajax_MailError(status, statusText, action, error_url, send_params) {
	// Creating object for holding parameters
	var params=new Object();
	
	// URL sending out error mail
	var url="/request/xml/error/xml_error_MAIL.cfm";
	
	// Generating parameters
	params["domain"]=document.location.host;
	params["page"]=document.location.pathname;
	params["params"]=send_params;
	params["action"]=action+" ["+error_url+"]";
	params["status"]=status;
	params["message"]=statusText;
	
	// Sending ajax mail request 
	var ajax=new js_ajax_Object("Sending error log", url, params);
	ajax.js_ajax_Post();
}

// REMOVES HTML ELEMENTS TO PEVENT IE MEMORY LEAKS
function js_dom_Garbage(obj_element, delete_root) {
	// Setting default for deleting root element (default: false)
	var delete_root=delete_root ? true : false;
	
	// Grabbing garbage bin object
	var obj_gBin=document.getElementById("gBin");
	
	// Creating div if not exists
	if(!obj_gBin) {
		// Creating hidden div object
		var obj_gBin=document.createElement("div");
		obj_gBin.id="gBin";
		obj_gBin.style.display="none";
		// Appending to body
		document.body.appendChild(obj_gBin);
	}
	
	// If child nodes exist
	if(obj_element.childNodes) {
		// Cycling through child nodes
		for(var i=obj_element.childNodes.length-1; i>=0; i--) {
			// Grabbing child node
			var obj_child=obj_element.childNodes[i];
			// Deleting child nodes and cleaning up
			js_dom_Garbage(obj_child, true);
			obj_child=null;
		}
	}
	
	// If deleting root entity (the one passed into the function originally)
	if(delete_root) {
		// Grabbing attributes
		var attrib=obj_element.attributes, i, l, n;
		
		if(attrib) {
			for(var i=0; i<attrib.length; i++) {
				n=attrib[i].name;
				
				if(typeof obj_element[n]==="function") {
					obj_element[n]=null;
				}
			}
		}
		
		// Moving the element to the garbage bin
		obj_gBin.appendChild(obj_element);
		obj_gBin.innerHTML="";
	}
	
	// Cleaning up
	obj_gBin=null;
	obj_element=null;
}
