// $Id: ajax_utilities.js,v 1.22 2010-01-05 15:37:30 nelf Exp $
// The file handles making and receiving GET and POST
//  Ajax (Asynchronous Javascript XML) requests.

// Upon making a successful Ajax request it calls callForward()
//  function, and upon receipt of a correct response it calls
//  callBack() function. You can redefine these functions to manipulate 
//  the page as you wish.

var d = document;	
var oHTTP_request = false;
var isRequesting = false;
var isAjaxDebug = false;

var oRedirect = new Object();
oRedirect.action = "";
oRedirect.form_id = "form";
oRedirect.names = null;
oRedirect.method = "GET";

oRedirect.redirect_url = "http://www.psand.net";
oRedirect.redirect_form_id = "";

// You can redeclare this variable in your page if you like.
var sWaiting_message = "Still waiting for previous server response. Please be patient.";

var oThrobber = d.createElement("img");
oThrobber.src="/shared_images/icons/throbber.gif";

function callForward(){
    // A void function unless redeclared
    
    //  This function gets called upon a successful Ajax request 
    //  getting sent to the server.

    // Redeclare this function in your page if you wish to do
    //  any processing upon sending a request, i.e. disabling buttons,
    //  links, visual tickers etc.
    return false;
}

function callBack(){
    // A void function unless redeclared
    
    //  This function gets called upon a successful Ajax response 
    //  being received.

    // Redeclare this function in your page if you wish to
    //  handle the oHTTP_request object in any way or re-enable
    //  buttons, links etc.
    return false;
}

function callFail(exception){
    // A void function unless redeclared

    // This function get called upon a response failure - for example 
    //   a network outage, corrupt return data or user interrupt (usually
    //   Iain restarting the server :) As you can see it currently
    //   silently fails rather than a JS error which could leave the
    //   page inoperable.
    //   Redeclare this function in your page if you wish to alert the 
    //   error and/or undo the processes in callForward(); 
    // exception should contain the error message
    return false;
}

function makePostRequest(sUrl, sParams) {
    // Unless there is a request in process
    //   this function creates and sends a post request
    //   to sUrl with POST parameters sParams 

    if (isRequesting){
	if (sWaiting_message != ""){
	    alert(sWaiting_message);
	}
	return false;
    }

    oHTTP_request = null;	
    oHTTP_request = false;	
    
    // Attempt to create a request object

    if (window.XMLHttpRequest) { // Mozilla, Safari,...
	oHTTP_request = new XMLHttpRequest();
	if (oHTTP_request.overrideMimeType) {
	    oHTTP_request.overrideMimeType('text/xml');
	}
    } else if (window.ActiveXObject) { // IE
	try {
	    oHTTP_request = new ActiveXObject("Msxml2.XMLHTTP");
	} catch (e) {
	    try {
		oHTTP_request = new ActiveXObject("Microsoft.XMLHTTP");
	    } catch (e) {}
	}
    }
    
    if (!oHTTP_request) {
	return false;
    }
    // Set the handler for the response

    oHTTP_request.onreadystatechange = checkResponse;

    // If there is a leading '?', remove it
    if(sParams.substring(0,1) == '?') {
	sParams = sParams.substring(1);
    }

    // Send request    

    oHTTP_request.open('POST', sUrl, true);
    oHTTP_request.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
    oHTTP_request.send(sParams);
    isRequesting = true;
    callForward();
    if (isAjaxDebug){
	alert("Sending to "+sUrl+"\nwith parameters "+sParams);
    }
}

function makeGetRequest(sUrl) {
	
    // Unless there is a request in process
    //   this function creates and sends a get request
    //   to sUrl with POST parameters sParams 

    if (isRequesting){
	if (sWaiting_message != ""){
	    alert(sWaiting_message);
	}
	return;
    }
   
    oHTTP_request = null;
    oHTTP_request = false;
    
    // Attempt to create a request object
    
    if (window.XMLHttpRequest) { // Mozilla, Safari,...
	oHTTP_request = new XMLHttpRequest();
	if (oHTTP_request.overrideMimeType) {
	    oHTTP_request.overrideMimeType('text/xml');
	}
    } else if (window.ActiveXObject) { // IE
	try {
	    oHTTP_request = new ActiveXObject("Msxml2.XMLHTTP");
	} catch (e) {
	    try {
		oHTTP_request = new ActiveXObject("Microsoft.XMLHTTP");
	    } catch (e) {}
	}
    }

    if (!oHTTP_request) {
	return false;
    }
 
    // Add a non repeating anti-cache parameter
   
    dEpoch = new Date();
    dEpoch = dEpoch.getTime();
    sUrl += '&cache='+dEpoch;
    
    // Set the handler for the response

    oHTTP_request.onreadystatechange = checkResponse;

    // Send request

    oHTTP_request.open('GET', sUrl, true);
    oHTTP_request.send(null);
    isRequesting = true;
    callForward();
    if (isAjaxDebug){
	alert("Sending to\n"+sUrl);
    }
}

function evalJSON(sText){
	return eval("("+sText+")");
}

function checkResponse() {

    // Listen to server response until complete
    //   once complete, check it is ok, if so call callback function


    if (oHTTP_request.readyState == 4) {
	try {
	    if (oHTTP_request.status){
		if (oHTTP_request.status == 200 || oHTTP_request.status == 122) {
		    isRequesting = false;
		    
		    if (isAjaxDebug){
			alert("Received response of \n"+oHTTP_request.responseText);
		    }
		    callBack();
		    return true;
		}else{
		    alert("There was a problem with the server response.\nthe server returned a code of "+oHTTP_request.status+"\nPlease contact support with this information.");
		    oHTTP_request = null;
		    oHTTP_request = false;
		    isRequesting = false;
		    return false;
		}
	    }
	}
	catch(ex) {
	
	    oHTTP_request = null;
	    oHTTP_request = false;
	    isRequesting  = false;
	    callFail(ex);		    
	    return false;
	}
    }
}
			

function replaceContent(sIdentity, sText){

    // Replace the content of element with id="sIdentity" with sText
    //   using innerHTML

    var oParent = d.getElementById(sIdentity);

    try {
	oParent.innerHTML = sText;
    }
    catch (e) {
	// IE sometimes fails unless we wrap the string in another element.
	var oWrappingDiv = d.createElement('div');
	oWrappingDiv.innerHTML = sText;
	oParent.appendChild(oWrappingDiv);
    }
    return true;
}

function disableElements(aElements){

    // Disables an array of elements by id

    for (var x=0; x<aElements.length; x++){
	if (d.getElementById(aElements[x])){
	    d.getElementById(aElements[x]).disabled = true;
	}
    }
    
}

function enableElements(aElements){

    // Enables an array of elements by id

    for (var x=0; x<aElements.length; x++){
	if (d.getElementById(aElements[x])){
	    d.getElementById(aElements[x]).disabled = false;
	}
    }
}

function killRequest(){
    
    // This function destroys the HTTP request
    //  and should be called in the unload

    if (oHTTP_request){
	oHTTP_request.abort();
	oHTTP_request = null;
    }
}

function unRequest(){

    // Backward compatability function

    killRequest();
}

function checkNames(aNames, sName){
    
    // Checks to see if a field name is present in an array of field names

    if (aNames == null){return true;}

    for (var x=0; x<aNames.length; x++){
	if (aNames[x] == sName){
	    return true;
	} 
    }
    return false;
}

function harvestForm(sForm_id, aNames){

    // This function harvests the data from a form based on id and 
    //  returns a parameter string ready for a request
    //  of the form ?id=4&dealer=Tice%20and%20sons
  
    // To use it, if you want all the form name/value pairs then call
    //  harvestForm("form", null);
    // If you want certain values use:
    //  harvestForm("form", ["login","password"]);


      var sParams = '';
      var oForm = d.getElementById(sForm_id); 
				   
      for (var x=0; x<oForm.elements.length; x++){
	var oElement = oForm.elements[x];


	if (oElement.type == undefined || oElement.type == "submit" ){
	    continue;	
	}
	if (oElement.type == "text" || oElement.type == "hidden"){
	    if (checkNames(aNames,oElement.name)){
		sParams += '&'+ oElement.name + '=' + encodeURIComponent(oElement.value);
	    }
	    continue;
	}
	if (oElement.type == "textarea"){
	    if (checkNames(aNames,oElement.name)){
		sParams += '&'+ oElement.name + '=' + encodeURIComponent(oElement.value);
	    }
	    continue;
	}
	if (oElement.type == "radio"){
	    if (oElement.checked){
		if (checkNames(aNames,oElement.name)){
		    sParams += '&'+ oElement.name + '=' + encodeURIComponent(oElement.value); 
		} 
		continue;
	    }	
	}
	if (oElement.type == "checkbox"){
	    if (oElement.checked){
		if (checkNames(aNames,oElement.name)){
		    sParams += '&'+ oElement.name + '=' + encodeURIComponent(oElement.value);
		}  
		continue;
	    }	
	}

	sReg = /^select-one$/;
	if (sReg.test(oElement.type)){
	    if (checkNames(aNames,oElement.name)){
		sParams += '&'+ oElement.name + '=' + encodeURIComponent(oElement.value);  
	    }
	    continue;
	}
	
	sReg = /^select-multiple$/;
	if (sReg.test(oElement.type)){
	    for(i = 0; i < oElement.options.length; i++)
		{
		    if (oElement.options[i].selected){
			if (checkNames(aNames,oElement.name)){
			    sParams += '&'+ oElement.name + '=' + encodeURIComponent(oElement.options[i].value); 
			} 	
		    }
		}
	    continue;
	}
	
	// Ignore non-matched elements
    }
    
    // Remove the leading ampersand and prepend a ? instead

    if (sParams.indexOf("&") == 0){
	sParams = sParams.substring(1);
    }

    if (sParams.length>0){
	sParams = "?" + sParams;
    }
    
    return sParams;
}

function ajaxRedirect(){

    //The use of this function requires that within
    //  your page you must reset the values
    //  of the global redirect object that you require.

    //  At the top of this file you will see the default values
    //  which often means you only need to set the action and
    //  redirect url.
    

    // UPDATE SETTINGS

    // oRedirect.action = "edit.html"; // the update action   
    // oRedirect.form_id = "form";     // the id of the form to be submitted
    // oRedirect.names = ["telephone","postcode"]; // optional names of values 
    //                                             // to return otherwise set null
    // oRedirect.names = null;         // This will return all values in the form
    // oRedirect.method = "GET";       // The Ajax request method

    // REDIRECT SETTINGS

    // oRedirect.redirect_url = "http://www.google.com"; // The redirect URL
    // oRedirect.redirect_form_id = "";                  // Form id to submit
    //                                     // if this is blank it will redirect
    //                                     // to the url above

    // You'll need to an event handler something like this:

    // document.getElementById("form").onsubmit = function(){ajaxRedirect();return false;}

    // OR if you are already running a validation() function then instead of returning true at the end:

    //  ajaxRedirect();
    //  return false;

    // That's it... You can always set
    // isAjaxDebug = true;
    // in your page for a verbose alert box output.

    // There is an example of the function being used in:
    // psand/EAW/html/invoices/invoice_items/add.html

    callBack = function(){
	if (oRedirect.redirect_form_id && oRedirect.redirect_form_id!=""){
	    d.getElementById(oRedirect.redirect_form_id).submit();
	}else{
	    window.location.href = oRedirect.redirect_url;
	}
   }

    sParams = harvestForm(oRedirect.form_id, oRedirect.names);
    
    if (oRedirect.method == "GET"){
	makeGetRequest(oRedirect.action+sParams);
    } else if (oRedirect.method == "POST") {
	makePostRequest(oRedirect.action,sParams);
    } else {
	alert("Unknown method: " + oRedirect.method);
    }
}

function showThrobber(sElementId){

    // Appens the standard throbber to element specified by id 
    // Optional second argument is a different Throbber gif

    if (arguments[1]){
	oThrobber.src=arguments[1];	
    }
    d.getElementById(sElementId).appendChild(oThrobber); 
}

function hideThrobber(sElementId){
    removeChildNodes(d.getElementById(sElementId)); 
}
