/*
SIDE_XMLHTTP
Library to easily use xmlHttpRequest

__version__ = "2.1"

## example ##
    
    function doSomething(someText) { alert(someText);}
    
    var req=new SIDE_XMLHTTP('/path/to/fileOrScript');
    req.process(doSomething);

## end example ##


Changelog

2.2 (29/03/2008)
  deleted some IE xmlhttp fallback, after lecture of 
    http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
2.1
  api simplified (callback is now passed directly to process method)
  user can now choose to receive text or xml
2.0
  code rewritten to permit multiple concurrent requests and have an OO api
1.0
  first release

*/


/**
 * Create an instance of SIDE_XMLHTTP.
 * 
 * new SIDE_XMLHTTP(serverAddr[,serverParams[,randomize]])
 * 
 * @serverAddr
 *     path to a file to read (or a cgi a script). Must reside on the same domain
 * @serverParams is a string with 
 *     string with evenctual arguments to pass to serverAddr, in the well known form
 *     param1=value1&param2=value2
 * @randomize
 *     if omitted or different from false value, it will make the request to add
 *        a xmlhttprand=<currentime> parameter to serverAddr, to avoid caching
 */
function SIDE_XMLHTTP(serverAddr,serverParams,randomize) {
    this.serverAddress=serverAddr;
    this.serverParams=serverParams==undefined ? '' : serverParams;
    if (randomize!=false) this.serverParams+='?xmlhttprand='+(new Date().getTime());
    this.xmlHttp=null; /*it will be initialized soon, it's here for evidence*/
    
    this._answerAsText=true;
    this._callback=null;
    this._method="GET";
    
    /* creates an XMLHttpRequest instance*/
    this._createXmlHttpRequestObject=function() {
        // will store the reference to the XMLHttpRequest object
        var tmp_xmlHttp;
        // this should work for all browsers except IE6 and older
        try {
            // try to create XMLHttpRequest object
            tmp_xmlHttp = new XMLHttpRequest();
        }
        catch(e) {
            // assume IE6 or older
            var XmlHttpVersions = new Array("Msxml2.XMLHTTP.6.0",
                                            "Msxml2.XMLHTTP.4.0",
                                            "Msxml2.XMLHTTP.3.0");
            // try every prog id until one works
            for (var i=0, j=XmlHttpVersions.length; i<j && !tmp_xmlHttp; i++) {
                try { 
                    // try to create XMLHttpRequest object
                    tmp_xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
                } 
                catch (e) {}
            }
        }
        // return the created object or display an error message
        if (!tmp_xmlHttp)
            alert("Error creating the XMLHttpRequest object.");
        else 
            return tmp_xmlHttp;
    }
    
    this.xmlHttp=this._createXmlHttpRequestObject();
}

/**
 * Start the asynchronous request 
 * 
 * @callback function accepting as first parameter the text/xml retrieved
 * @answerAsText boolean value. If different from <false>, callback is given text as parameter (xml otherwise)
 */ 
SIDE_XMLHTTP.prototype.process=function(callback,answerAsText) {
    this._callback=callback;
    this._answerAsText=answerAsText==false ? false : true;
    
    // only continue if xmlHttp isn't void
    if (this.xmlHttp) {
        // try to connect to the server
        try {
            // initiate server access
            var obj=this;
            this.xmlHttp.open(this._method, this.serverAddress + "" + this.serverParams, true);
            //this.xmlHttp.onreadystatechange = function(){_ext_handleRequestStateChange(obj)};
            this.xmlHttp.onreadystatechange = function(){obj._handleRequestStateChange()};
            this.xmlHttp.send(null);
        }
        // display the error in case of failure
        catch (e) {
            alert("Can't connect to server:\n" + e.toString());
        }
    }
}

/**
 * Set the method to use when contacting server
 */
SIDE_XMLHTTP.prototype.setMethod=function(method){
    method=method.toUpperCase();
    if (!method in ["GET","POST"]) {
        throw new UnsupportedMethodException("Only GET and POST are supported");
    }
    else {
        this._method=method;
    }
}

/**
 * Private function called when the state of the HTTP request changes
 */ 
SIDE_XMLHTTP.prototype._handleRequestStateChange=function() {
    // when readyState is 4, we are ready to read the server response
    if (this.xmlHttp.readyState == 4) {
        // continue only if HTTP status is "OK"
        if (this.xmlHttp.status == 200) {
            try {
                // do something with the response from the server
                this._callback(this._answerAsText?this.xmlHttp.responseText:this.xmlHttp.responseXML);
            }
            catch(e) {
                // display error message
                alert("Error reading the response: " + e.toString());
            }
        }
        else {
            // display status message
            alert("There was a problem retrieving the data:\n" + 
                this.xmlHttp.statusText);
        }
    }
}

// *****************************  //

//Exception object create when asking for a method different from GET / POST
function UnsupportedMethodException(message){
    this.message=message;
    this.name="UnsupportedMethodException";
}

UnsupportedMethodException.prototype.toString=function(){
    return this.name+": \""+this.message+"\"";
}