Function.prototype.bind = function( object )
{
    var __method = this, args = [];
    return function() {
        return __method.apply(object, args.concat(arguments));
    }
}

var Ajax = function( f_szTarget, f_arrOptions )
{
    this.setTarget(f_szTarget);

    if ( !this.getTransport() ){}

    this.setOptions(f_arrOptions);

    this.request();
};

Ajax.prototype = {
    'xmlhttp'        : null,
    'target'        : '',
    'asynchronous'    : true,
    'method'        : 'POST',
    'params'        : '',
    'onComplete'    : function(){},
    'busy'            : 0,
    
    'getTransport': function()
    {
        try {
            this.xmlhttp = new XMLHttpRequest();
        } catch (e1) {
            try {
                this.xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e2) {
                try {
                    this.xmlhttp = new XMLHttpRequest("Microsoft.XMLHTTP");
                } catch (e3) {
                    this.xmlhttp = false;
                }
            }
        }

        return !!this.xmlhttp;
    },

    'setTarget': function( f_szTarget )
    {
        if ( !f_szTarget )
        {
            f_szTarget = document.location;
        }
        else if ( '?' == f_szTarget.substr(0,1) )
        {
            f_szTarget = document.location + "" + f_szTarget;
        }

        this.target = "" + f_szTarget;
        return true;
    },

    'setOptions': function( f_arrOptions )
    {
        if ( f_arrOptions['method'] )
        {
            this.method = f_arrOptions['method'];
        }

        if ( f_arrOptions['params'] )
        {
            this.params = f_arrOptions['params'];
        }


        if ( f_arrOptions['onComplete'] && "function" == typeof f_arrOptions['onComplete'] )
        {
            this.onComplete = function(){ f_arrOptions['onComplete']( this.xmlhttp ) };
        }


        if ( f_arrOptions['async'] )
        {
            this.asynchronous = f_arrOptions['async'];
        }

        return true;
    },

    'request': function()
    {

        rnd            = Math.random();
        Ajax.busy    = rnd;
        this.busy    = rnd;


        this.xmlhttp.open(
            this.method.toUpperCase(),
            this.target,
            this.asynchronous
        );
        if ( 'POST' == this.method.toUpperCase() )
        {
            this.xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        }
        this.xmlhttp.onreadystatechange = this.whileRequestHandler.bind(this);
        this.xmlhttp.send(this.params);
    },

    'whileRequestHandler': function()
    {

        if ( 1 == this.xmlhttp.readyState )
        {
            Ajax.arrHandlers['onStart'](this.xmlhttp); 
        }
        else if ( 4 == this.xmlhttp.readyState )
        {
            this.onComplete();

            if ( this.busy == Ajax.busy ) Ajax.busy = 0;

            Ajax.arrHandlers['onComplete'](this.xmlhttp); 
        }
    }

};


Ajax.busy            = 0;
Ajax.arrHandlers     = { 'onStart' : function(){}, 'onComplete' : function(){} };
Ajax.setHandlers     = function( f_arrHandlers )
{
    if ( "object" != typeof f_arrHandlers ) return false;

    if ( f_arrHandlers['onStart'] && "function" == typeof f_arrHandlers['onStart'] )
    {
        Ajax.arrHandlers.onStart = f_arrHandlers['onStart'];
    }

    if ( f_arrHandlers['onComplete'] && "function" == typeof f_arrHandlers['onComplete'] )
    {
        Ajax.arrHandlers.onComplete = f_arrHandlers['onComplete'];
    }

    return true;
}; 