/*******************************************************************************
 * Clean Ajax
 * -----------------------------------------------------------------------------
 * Copyright (C) 2007-2008 Ondrej Fischer
 *
 *   Clean implementation of portable ajax interface. Prototypical inheritance
 * does all the trick.
 */


/**
 * Clean Ajax constructor can register handlers directly as parameters.
 */
function CleanAjax(handlers)
{
        var request = this.request = this.init();

        var stateHandlers = new Array();

        request.onreadystatechange = function onreadystatechange()
        {
                if(stateHandlers[request.readyState]) stateHandlers[request.readyState].call(request);
        };

        /**
         * Registering of handlers in an already existing instance.
         */
        this.setStateHandler = function setStateHandler(state, handler)
        {
                stateHandlers[state] = handler;
                return this;
        }

        this.request = function(method, uri, data, headers)
        {
                request.open(method, uri, this.async);
                if(headers) for(var i in headers) request.setRequestHeader(i, headers[i]);
                request.send(data);
                return this;
        }

        if(handlers) for(var handler in handlers) this['set' + handler](handlers[handler]);

}

CleanAjax.prototype.async = true;

/**
 * Here we handle creating right prototype, providing AJAX API.
 */
CleanAjax.prototype.init = function initUnsupported()
{
        throw new AjaxUnsupportedException();
}

if(window.ActiveXObject)
CleanAjax.prototype.init = function initActiveX()
{
        return new ActiveXObject("Microsoft.XMLHTTP");
}

if(window.XMLHttpRequest)
CleanAjax.prototype.init = function initXMLHttpRequest()
{
        return new XMLHttpRequest();
}

/**
 * Let's define methods to have easier usage of AJAX primitives.
 */

CleanAjax.prototype.joinParams = function joinParams(params)
{
        var parts = [];
        for(var i in params) parts.push(i + '=' + params[i]);
        return parts.join('&amp;');
}

/**
* Mehtod get() is a simple GET request.
*/
CleanAjax.prototype.get = function get(uri, headers)
{
        return this.request('GET', uri, null, headers);
}

CleanAjax.prototype.getParams = function getParams(uri, params, headers)
{
        return this.request('GET', uri + '?' + this.joinParams(params), null, headers);
}

/**
* Mehtod post() is a generic POST request able to send data of any type.
*/
CleanAjax.prototype.post = function post(uri, data, contentType, headers)
{
        if(!headers) headers = new Object();
        headers['Content-Type'] = contentType;
        return this.request('POST', uri, data, headers);
}

/**
 * Mehtod postXML() is a POST request for sending XML document.
 */
CleanAjax.prototype.postXML = function postXml(url, data, headers)
{
        return this.post(url, data, 'text/xml', headers);
}

CleanAjax.prototype.postRawData = function postRawData(url, data, headers)
{
        return this.post(url, data, 'application/x-www-form-urlencoded', headers);
}

CleanAjax.prototype.postParams = function postParams(url, params, headers)
{
        return this.postRawData(url, this.joinParams(params), headers);
}



CleanAjax.prototype.setLoadingHandler = function setLoadingHandler(handler)
{
        return this.setStateHandler(1, handler);
}

CleanAjax.prototype.setHeaderLoadedHandler = function setLoadedHandler(handler)
{
        return this.setStateHandler(2, handler);
}

CleanAjax.prototype.setDataChunkHandler = function setLoadedHandler(handler)
{
        return this.setStateHandler(3, handler);
}

CleanAjax.prototype.setDataLoadedHandler = function setReadyHandler(handler)
{
        return this.setStateHandler(4, handler);
}

