
/* *******************************************
     Javascript to implement the AsyncCommObj
     interface using XmlHttpRequest/IFrames
     Originally written by RNR 2007-07-31, 
     updated by JC to provide IFRAME fallback,
     imported from Coverbug
   ******************************************* */

// Constants   
var c_requestContentType = 'application/x-www-form-urlencoded; charset=iso-8859-1'; 

// Constructor
function AsynCommObj(respHandler)
{
    this.response_handler = respHandler;
    this.requestUrl = null;
    this.requestSent = false;

    var http_request = null;
    
    var forceUseOfIFrame = false;
    
    // Create the XmlHttpRequest object
    if (!forceUseOfIFrame && window.XMLHttpRequest)
    {
        // Mozilla, Safari,...
        http_request = new XMLHttpRequest();
    }
    else if (!forceUseOfIFrame && window.ActiveXObject)
    {
        // IE5.5/6
        try
        {
            http_request = new ActiveXObject('Msxml2.XMLHTTP');
        }
        catch (e)
        {
            try
            {
                http_request = new ActiveXObject('Microsoft.XMLHTTP');
            } 
            catch(e) {}
        }
    }
    
    if (http_request == null)
    {
        this.Construct = AsynCommObj_IFrameImpl;
    }
    else
    {
        this.Construct = AsynCommObj_XmlHttpReqImpl;
        this.http_request = http_request;
    }

    this.Construct();
}

function AsynCommObj_XmlHttpReqImpl()
{
    // Create methods
    this.SendGetReq = function (url)
        {
            if (!this.requestSent)
            {
                this.requestUrl = url;
                this.http_request.open('GET', url, true);
                this.requestSent = true;
                this.http_request.send(null);
            }
        };

    this.SendPostReq = function (url, data)
        {
            if (!this.requestSent)
            {
                this.http_request.open('POST', url, true);
                this.http_request.setRequestHeader('Content-Type', c_requestContentType);
                if (data == null) data = '';
                this.http_request.setRequestHeader('Content-length', data.length);
                this.requestSent = true;
                this.http_request.send(data);
            }
        };

    this.AbortReq = function ()
        {
            // abort the request
            if (this.requestSent)
            {
                // JC, 27 Sept
                // setting .onreadystatechange = null in IE6 causes a "type mismatch" error
                // instead set this to an empty function
                this.http_request.onreadystatechange = function(){};
                this.http_request.abort();
            }
        };

    // Assign event handler to request object
    this.http_request.onreadystatechange = CreateDelegate(
            function ()
                {
                    // If the readyState is 'loaded'
                    if (this.http_request.readyState == 4)
                    {
                        // If the response came back 'OK'
                        if (this.http_request.status == 200)
                        {
                            var errorTags = this.http_request.responseXML.getElementsByTagName('error');
                            if(errorTags.length > 0){
                                var errorNode = errorTags.item(0);
                                var errorTextAttribute = errorNode.attributes[0];
                                var errorText = "An unexpected error has occured.";
                                if(errorTextAttribute != null){
                                    errorText = errorTextAttribute.nodeValue;
                                }
                                this.response_handler.handleError(errorText);
                            }else{
                                this.response_handler.processResponse(this.http_request.responseXML.getElementsByTagName('root').item(0));
                            }
                        }
                        // Otherwise there was a problem - report to the user
                        else
                        {
                            var errorText = 'An unexpected error has occured. HTTP status: ' + this.http_request.status + 
                                            ' "' + this.http_request.statusText + '"';
                            this.response_handler.handleError(errorText);
                            /*
                            alert(
                                    'XmlHttpRequest to ' + this.requestUrl + 
                                    ' failed (HTTP status: ' + this.http_request.status + 
                                    ' "' + this.http_request.statusText + '")'
                                );
                            */
                        
                        }
                    }
                },
            this
        );
}


/* **** IFRAME (+ FORM) AsynCommObj : START **** */

// ***** constants *****

// to prevent the creation of multiple forms (getFormElement) we use this var to record the 
// first form generated so that we can re-use it

var c_spawnedForm = null;
var c_spawnedIFrame = null;
var c_spawnedFormName = "AsynCommObj_Form";
var c_spawnedIFrameName = "AsynCommObj_IFrame";

var c_currentCallBackObject = null;

function AsynCommObj_IFrameImpl(inMethod, inTarget, inAction)
{
	// the method by which data is to be sent
    this.SendGetReq = function(url){
        // get the elements needed
        var iframe = this.GetIFrame();
        
        c_currentCallBackObject = this.response_handler;
        
        // this prevents the browser's history being updated
        // isIFrame param is needed to inform the handling page so that
        // it will return as HTML with the xml embedded therein
        iframe.contentWindow.location.replace(url + "&isIFrame=true");
    };
    this.SendPostReq = function(url, data){
    
        url = url + "&isIFrame=true";
    
        // get the elements needed
        var formElement = this.GetForm();
        var iframe = this.GetIFrame();
        // prepare the form for sending the request
        this.SetFormForRequest(formElement, url, iframe.name, "post");
        
        // empty the form of any existing inputs
        while(formElement.childNodes.length > 0){
            formElement.removeChild(formElement.childNodes[0]);
        }
        
        // add inputs for the posting of data
        var keyValueStrings = data.split('&');

        for(var i = 0; i < keyValueStrings.length; i++){
            var keyValueString = keyValueStrings[i];
            var parts = keyValueString.split('=');
            var key = parts[0];
            var value = keyValueString.replace(key + "=", "");

            var input = document.createElement("INPUT");
            input.type = "text";
            input.name = key;
            input.value = value;
            /*
            var input = document.createElement("TEXTAREA");
            input.name = key;
            input.innerHTML = value;
            */
            formElement.appendChild(input);
        }
        
	    // send the request by submitting the form
 	    formElement.submit();
    };
    this.AbortReq = function() { };
    
    this.GetForm = AsynCommObj_IFrameImpl_GetForm;
    this.GetIFrame = AsynCommObj_IFrameImpl_GetIFrame;
    this.SetFormForRequest = AsynCommObj_IFrameImpl_SetFormForRequest;
}

// *** Form and IFrame Element Methods ***

// gets a reference to the form element we want to use
function AsynCommObj_IFrameImpl_GetForm(){
	if(c_spawnedForm == null){
		// otherwise we need to create one
		c_spawnedForm = document.createElement("FORM");
		c_spawnedForm.name = c_spawnedFormName;
		c_spawnedForm.id = c_spawnedFormName;
        c_spawnedForm.style.display = "none";
		// add the form to the page
//		var submitInput = document.createElement("INPUT");
//		submitInput.type = "submit";
//		c_spawnedForm.appendChild(submitInput);
		
		document.body.appendChild(c_spawnedForm);
	}
	return c_spawnedForm;
}

// gets a reference to the iframe element we want the form to target
function AsynCommObj_IFrameImpl_GetIFrame(){
	if(c_spawnedIFrame == null){
		// otherwise we need to create one
		c_spawnedIFrame = document.createElement("IFRAME");
		c_spawnedIFrame.name = c_spawnedIFrameName;
		c_spawnedIFrame.id = c_spawnedIFrameName;
        c_spawnedIFrame.style.display = "none";
		// add the frame to the page
		document.body.appendChild(c_spawnedIFrame);
	}
	return c_spawnedIFrame;
}

// set the values on the form according as needed by the request
function AsynCommObj_IFrameImpl_SetFormForRequest(formElement, action, target, method){
	// set the method and the action
	formElement.action = action;
	formElement.target = target;
	formElement.method = method;
}

/* **** IFRAME (+ FORM) AsynCommObj : END **** */

function CreateDelegate(method, obj)
{
    return function() { method.apply(obj, arguments); };
}
