// <?
// The JgAjaxRequest function is used to created XmlHttpRequest to be sent to your
// server. A requetes contains none to many data to be sent via GET or POST HTTP protocole.
// Currently JgAjaxRequest supports :
// * addData - appends one data to the request
// * addElement - appends the value of an HTML element of current document
// * addForm - appends all values of a form elements
// * send - send the configurated request
// elements are identified by their HTML id

function JgAjaxRequest() {

    // (public) config variables
    this.requestURI = String(window.location); // default is current page
    this.requestMethod = 'POST';       // 'POST' or 'GET'
    this.asynchronousMode = true;      // synchronous will make ajax a blocking function  (prefer not use !)
    this.debugMode = false;            // true or false
    this.statusMode = true;            // true or false
	this.result = '' // Result from last action

    // (private) aggregate data while adding
    this._dataToSend = '';
    this._xml = null;
	this._r = null;
	this._busy = false;

    //  (public) addData(dataName, dataValue);
    // Usage :
    //  jgajax.addData('oneName', 'oneValue');
    this.addData = function(dataName, dataValue) {
        if(this._dataToSend!='') this._dataToSend += '&';
        this._dataToSend += escape(dataName)+'='+escape(dataValue);
        this._debug("Adding data... \nname = "+dataName+"\nvalue = "+dataValue);
    }
    

    //  (public) addElement(element);
    // Usage :
    //  jgajax.addElemnt(elementObject);
    //  jgajax.addElement('elementID');
    this.addElement = function(element) {
        var objElt;
        if( typeof(element) == "string" ) objElt = this._$(element);
        else objElt = element;

        if(objElt && objElt.name) {
            if( objElt.type=='select-multiple' ) {
				var objOptions = objElt.options;
				for( var i=0; i < objOptions.length; i++) {
					if( objOptions[i].selected ) {
						this.addData(objElt.name, objOptions[i].value);
					}
				}
			} else this.addData(objElt.name, objElt.value);
        } else if( objElt.tagName == 'FIELDSET' ) return;
		else this._debug("Error element not found !!!\nobjElt="+element.tagName, true);
    }

    //  (public) addForm(frm);
    // Usage :
    //  jgajax.addForm(formObject);
    //  jgajax.addForm('formID');
	this.addForm = function(frm) {
        var objForm;
        if (typeof(frm) == "string") objForm = this._$(frm);
        else objForm = frm;

        if (objForm && objForm.tagName == 'FORM' ) {
            var formElements = objForm.elements;
            for( var i=0; i < formElements.length; i++) {
                if ((formElements[i].type == 'radio' || formElements[i].type == 'checkbox') && formElements[i].checked == false)
                	continue;
                this.addElement(formElements[i]);
            }
        } else this._debug("Error form not found !!!\nobjForm="+frm, true);
    }

	this.sendForm = function(formId) {
        var objForm;
        if (typeof(formId) == "string") objForm = this._$(formId);
        else objForm = formId;

		if (objForm && objForm.tagName == 'FORM') {
			this.requestURI = objForm.action;
            var formElements = objForm.elements;
            for( var i=0; i < formElements.length; i++) {
                if ((formElements[i].type == 'radio' || formElements[i].type == 'checkbox') && formElements[i].checked == false)
                	continue;
                this.addElement(formElements[i]);
            }
			this.sendRequest();
        } else this._debug("Error form not found !!!\nobjForm="+formId, true);
	}


    // (private) jgajax._$() is shorthand for document.getElementById()
    this._$ = function(ID) {
        return document.getElementById(ID);
    }

    // (private) jgajax._debug(text) active in debugging mode
    this._debug = function(text,error) {
        if(this.debugMode || error) alert(text);
		//if(error) alert('Une erreur est survenue lors de l\'envoi de la requète\nVeuillez nous en excuser');
    }

    // (private) jgajax._status(text) active in show status mode
    this._status = function(statustype) {
        if(this.statusMode) {
            var div = this._$('JgAjaxStatus');
            if(!div) return false;
            switch( statustype ) {
                case 1:
                div.innerHTML = 'Interrogation du serveur...';
                div.style.visibility = 'visible';
                break;

                case 2:
                div.innerHTML = 'En attente d\'une réponse...';
                div.style.visibility = 'visible';
                break;

                case 3:
                div.innerHTML = 'Réception des données...';
                div.style.visibility = 'visible';
                break;

                case 4:
                div.innerHTML = 'Traitement des données...';
                div.style.visibility = 'visible';
                break;

                default:
                div.innerHTML = '';
                div.style.visibility = 'hidden';
                break;
            }
        }
    }
    
	// (private) Get the XMLHttpRequest Object
    this._getRequestObject = function() {
        this._debug("Initializing Request Object..");
        var req;
        try	{
            req=new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try	{
                req=new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e2) {
                req=null;
            }
        }
        if(!req && typeof(XMLHttpRequest) != "undefined") req = new XMLHttpRequest();
        if(!req) this._debug("Request Object Instantiation failed.", true);
        return req;
    }


    //  (public) jgajax.sendRequest()
    // Usage : must be call when request is ready
    this.sendRequest = function() {
        if(typeof(this.requestURI)!='string' || this.requestURI=='') {
            //alert(typeof(this.requestURI));
            alert('Please configure the requestURI before sending data\n current :\n '+this.requestURI);
            return false;
        }

		if(this._busy) {
            this._dataToSend = '';
			alert("Le serveur est en cours d'intérrogation\n\nVeuillez patienter...");
			return false;
		}

        var i,r,postData;
        this._debug("Starting jgajax javscript engine...");

		this.addData('JGAJAX','JGAJAX');


		var value;
		switch(this.requestMethod) {
      		case 'GET' : {
                if( this.requestURI.indexOf("?")==-1 ) {
                    this.requestURI += '?';
                } else {
                    this.requestURI += '&';
                }
                this.requestURI += this._dataToSend;
				postData = null;
                this._dataToSend = '';
		    }
            break;

            case 'POST' : {
                postData = this._dataToSend;
                this._dataToSend = '';
            }
            break;

            default: {
                alert("Illegal request type: " + this.requestMethod+ '\nValide types are "GET" or "POST"');
                this._dataToSend = '';
                return false;
            }
            break;
        }

        r = this._getRequestObject();
        r.open(this.requestMethod, this.requestURI, this.asynchronousMode);
        if (this.requestMethod == 'POST') {
            try {
                r.setRequestHeader("Method", "POST " + this.requestURI + " HTTP/1.1");
                r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            } catch(e) {
                alert("Your browser does not appear to  support asynchronous requests using POST.");
                return false;
            }
        }

        r.onreadystatechange = function() {
            jgajax._status(r.readyState);
            if( r.readyState==4 ) {
				jgajax._busy = false;
                if( r.status==200 ) {
                    jgajax._debug("Received:\n" + r.responseText);
                    var data = r.responseXML;
					jgajax._r = r.responseText;
                    if (data) {
                        jgajax._processResponse(data,true);
                    } else {
                        jgajax._debug("Non XML response !!! I can't process it :\n"+r.responseText, true);
                        jgajax._status(5);
                    }
                } else {
                    jgajax._debug('HTTP Error : '+r.status+'\n'+r.responseText, true);
                    jgajax._status(5);
                }
            }
            return;
        }
        
        this._debug("Sending data\n URI="+this.requestURI+"\n POST data:"+ postData);
        r.send(postData);
        this._debug("Waiting for response...");
        delete r;
		this._busy = true;
        return true;
    }
    
    // (private) Process XML responses returned from the request
    this._processResponse = function(xml) {
        this._xml = xml;
        xml = xml.documentElement;
        if(!xml.childNodes[0]) {
            this._debug('XMLResponse\nXML parsing ERROR !!!\nResponse is empty', true);
            this._status(5);
            return false;
        }
        if(xml.childNodes[0].nodeName=='#text') {
            this._debug('XMLResponse\nXML parsing ERROR !!!\n'+xml.childNodes[0].nodeValue+'\n\n'+this._r, true);
            this._status(5);
            return false;
        }
        this._debug("Processing XML response... \n"+xml );
        for (i=0; i < xml.childNodes.length; i++) {
            if (xml.childNodes[i].nodeName == "alert") {
                if (xml.childNodes[i].firstChild) alert(xml.childNodes[i].firstChild.nodeValue);
            }
            if (xml.childNodes[i].nodeName == "return") {
                if (xml.childNodes[i].firstChild) this.result = xml.childNodes[i].firstChild.nodeValue;
            }
            if (xml.childNodes[i].nodeName == "jscript") {
				if (xml.childNodes[i].firstChild) eval(xml.childNodes[i].firstChild.nodeValue);
      		}

         	if (xml.childNodes[i].nodeName == "update") {
                var action;
                var element;
                var attribute;
                var search;
                var data;
                var type;
                var objElement;

                for (j=0; j<xml.childNodes[i].attributes.length; j++) {
                    if (xml.childNodes[i].attributes[j].name == "action") {
                        action = xml.childNodes[i].attributes[j].value;
                    }
                }

                var node = xml.childNodes[i];
                for (j=0;j<node.childNodes.length;j++) {
                    if (node.childNodes[j].nodeName == "target") {
                        for (k=0; k<node.childNodes[j].attributes.length; k++) {
                            if (node.childNodes[j].attributes[k].name == "attribute") {
                                attribute = node.childNodes[j].attributes[k].value;
                            }
                        }
                        element = node.childNodes[j].firstChild.nodeValue;
                    }
                    if (node.childNodes[j].nodeName == "search") {
                        if (node.childNodes[j].firstChild) search = node.childNodes[j].firstChild.nodeValue;
                        else search = "";
                    }
                    if (node.childNodes[j].nodeName == "data") {
                        if (node.childNodes[j].firstChild) data = node.childNodes[j].firstChild.nodeValue;
                        else data = "";
                    }
                    if (node.childNodes[j].nodeName == "type") {
                        if (node.childNodes[j].firstChild) type = node.childNodes[j].firstChild.nodeValue;
                        else type = "";
                    }
                }

                if (action=="assign") {
					if( this._$(element) ) eval("document.getElementById('"+element+"')."+attribute+"=data;");
					else this._debug('addAssign : Element "'+element+'.'+attribute+'" non trouvé',true);
				}
                if (action=="append") eval("document.getElementById('"+element+"')."+attribute+"+=data;");
                if (action=="prepend") eval("document.getElementById('"+element+"')."+attribute+"=data+document.getElementById('"+element+"')."+attribute);
                if (action=="replace") {
                    eval("var v=document.getElementById('"+element+"')."+attribute);
                    var v2 = v.indexOf(search)==-1?v:"";
                    while (v.indexOf(search) > -1) {
                        x = v.indexOf(search)+search.length+1;
                        v2 += v.substr(0,x).replace(search,data);
                        v = v.substr(x,v.length-x);
                    }
                }
                if (action=="clear") eval("document.getElementById('"+element+"')."+attribute+"='';");
                if (action=="remove")	{
                    objElement = this._$(element);
                    if ( objElement && objElement.parentNode && objElement.parentNode.removeChild) {
                        objElement.parentNode.removeChild(objElement);
                    } else this._debug("Can't remove "+element+"."+attribute+"\nNOT FOUND !!!");
                }
                if (action=="create") {
					if( !this._$(data) ) {
						var objParent = this._$(element);
						if( objParent ) {
							objElement = document.createElement(attribute);
							objElement.setAttribute('id',data);
							if (type && type != '') objElement.setAttribute('type',type);
							objParent.appendChild(objElement);
							if (objParent.tagName == "FORM") { }
						} else this._debug('addCreate : Parent "'+element+'" non trouvé',true);
					}
                }
            }
        }
        this._status(5);
    }
}
var jgajax = new JgAjaxRequest();
//if(!jgajax._$('JgAjaxStatus'))
//    document.write('<div id="JgAjaxStatus"></div>');

