// class constructor
var AJAX = function()
{
    // handle cache
    this._handle = undefined;

    // default values for some properties
    this._props =
    {
        method: 'GET',
        uri: null,
        asyncronous: true,
        responsetype: 'text',
        response: false,
        callback: null
    };
}

// version
AJAX.VERSION = '0.03';

// exported methods
AJAX.EXPORT = [ 'call' ];

// class methods
AJAX.prototype = {

// make a call
call: function( aProps, rParams )
{
    // set object properties
    for( var cKey in this._props )
    {
        if( aProps[cKey] != undefined )
        {
            this['_' + cKey] = aProps[cKey];
        }
        else
        {
            this['_' + cKey] = this._props[cKey];
        }
    }

    // manage parameters
    var rQuerystring = null;

    if( rParams != undefined )
    {
//alert( 'params: -- ' + rParams );
        // string
        if( typeof( rParams ) == 'string' )
        {
            rQuerystring = rParams;
        }
        // object literal
/*
        else if( typeof( rParams ) == 'object' )
        {
            var aTemp = new Array();

            for( var cKey in rParams )
            {
                aTemp.push( escape( cKey ) + '=' + escape( rParams[cKey] ) );
            }

            // query string
            rQueryString = aTemp.join( '&' );
alert( 'params object: ' + rQueryString );
        }
*/
        // array or array literal
        else
        {
            var aTemp = new Array();
//alert( 'params: ' + rParams.length );
            while( rParams.length )
            {
                aTemp.push( escape( rParams.shift() ) + '=' + escape( rParams.shift() ) );
            }

            // query string
            rQuerystring = aTemp.join( '&' );
        }

        // test HTTP method
        if( this._method.toUpperCase() == 'GET' )
        {
            // append querystring to uri and pass null value to send
            this._uri += '?' + rQuerystring;
            rQuerystring = null;
        }
    }

    // get XMLHttpRequest object
    var oHandle = this._getHandle();

    // reference to AJAX class
    var oParent = this;

    // manage the response
    oHandle.onreadystatechange = function()
    {
        if( oHandle.readyState == 4 )
        {
            if( oHandle.status == 200 )
            {
                cResponse = ( oParent._responsetype == 'text' )
                          ? oHandle.responseText
                          : oHandle.responseXML;

                // Execute callback function
                var oCallback = oParent._callback;

                // Test that callback is a valid CODE reference
                if( oCallback )
                {
                    oCallback( cResponse );
                }
            }
            else
            {
                alert( 'Server returns a bad response! (' + oHandle.status + ')' );
            }
        }
        else
        {
//            alert( 'not ready! (' + oHandle.readyState + ')' );
        }
    }

    // make the call
    oHandle.open( this._method.toUpperCase(), this._uri, this._asyncronous );

    // set the right request header for the POST method
    if( this._method.toUpperCase() == 'POST' )
    {
        oHandle.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
    }

    oHandle.send( rQuerystring );
},

// load the XMLHttpRequest object
_getHandle: function()
{
    // FF, M, NN, O
    if( window.XMLHttpRequest )
    {
        this._handle = new XMLHttpRequest();
    }
    // Exploder
    else if( window.ActiveXObject )
    {
        var aWinzozz = new Array(
            'Msxml2.XMLHTTP.5.0',
            'Msxml2.XMLHTTP.4.0',
            'Msxml2.XMLHTTP.3.0',
            'Msxml2.XMLHTTP',
            'Microsoft.XMLHTTP'
        );

        for( var i = 0; i < aWinzozz.length; i++ )
        {
            try
            {
                this._handle = new ActiveXObject( aWinzozz[i] );

                break;
            }
            catch(e)
            {}
        }
    }

    // Check object validity
    if( typeof( this._handle ) == 'undefined' )
    {
        alert( 'Unable to locate XMLHttpRequest object!' );
    }

    return this._handle;
}

};

/*

=head1 NAME

AJAX - A simple crossbrowser javascript interface to the AJAX technology

=head1 SYNOPSIS

  // Create a new AJAX object
  var oAJAX = new AJAX();

  // Make a call
  oAJAX.call(
      {
          uri: 'http://host.domain.tld/cgi-bin/ajax_script',
          callback: manageResponse
      },
      { param1: 'value1', param2: 'value2' }
  );

  // Manage the response
  function manageResponse( cResponse )
  {
      var oDiv = document.getElementById('myDiv');
      oDiv.innerHtml = cResponse;
  }

=head1 DESCRIPTION

This fabulous class implements an OO approach to the AJAX technology, providing methods for make
asynchronous calls to a CGI from a web page via JavaScript and the XMLHttpRequest object.

=head1 METHODS

=head2 B<new()>

Object constructor, returns a brand new AJAX object.

No parameters are requested here, so you can make multiple different calls on the same object by
passing different parameters to che call() method.

=head2 B<call()>

This public method performs the call via XMLHttpRequest to the specified server's script and
returns the response.

=head3 Parameters

=over 3

=item B<oProps>

Structure with properties used in the call passed as an object literal.

Properties are:

=over 15

=item C<uri>

URI of the script to call; B<mandatory!>

Ex.: http://host.domain.tld/cgi-bin/ajax_script

=item C<method>

HTTP method to use in the call.

GET, POST, HEAD... (default is GET)

=item C<asyncronous>

indicates if the function execution will continue while waiting the server response or not.

true or false (default is true)

=item C<responsetype>

indicates which method use for retrieve the response.

text or xml (default is text)

=item C<callback>

reference to the function to use for process the response.

=back

=item B<rParams>

List of parameters to pass to the call; optional.

You can pass an URL-escaped string, an object literal, an array or an array literal.

=back

=head3 Returned value

=over 4

=item B<cResponse>

Response stuff depending on responsetype setting.

Can be plain text or XML.

=back

=head2 B<_getHandle()>

This private method is called by the call() method and returns the XMLHttpRequest object.

=head1 EXPORTS

When used with C<JSAN> will export C<call>.

=head1 EXAMPLES

  // Call without parameters:
  oAJAX.call(
      {
          uri: 'http://host.domain.tld/cgi-bin/ajax_script',
          callback: function( cText ) { alert( cText ); }
      }
  );

  // Call with parameters as object literal and XML response:
  oAJAX.call(
      {
          uri: 'http://host.domain.tld/cgi-bin/ajax_script',
          responsetype: 'xml',
          callback: function( cXml ) { alert( cXml ); }
      },
      { mode: 'xml', param1: 'value1' }
  );

  // Call with parameters as array literal and XML response:
  oAJAX.call(
      {
          uri: 'http://host.domain.tld/cgi-bin/ajax_script',
          responsetype: 'xml',
          callback: function( cXml ) { alert( cXml ); }
      },
      [ 'mode','xml','param1','value1' ]
  );

  // Call with parameters as standard array with POST method
  oAJAX.call(
      {
          method: 'POST',
          uri: 'http://host.domain.tld/cgi-bin/ajax_script',
          callback: function( cResponse ) { alert( cResponse ); }
      },
      new Array( 'param1', 'value1' )
  );

  // Call with parameters as string
  oAJAX.call(
      {
          uri: 'http://host.domain.tld/cgi-bin/ajax_script',
          callback: function( cText ) { alert( cText ); }
      },
      'param1=value1&param2=value2'
  );

=head1 SEE ALSO

Official web page at L<http://www.sabadelli.it/edoardo/projects/javascript/ajax>

=head1 AUTHOR

Edoardo Sabadelli - L<http://www.sabadelli.it/edoardo>

=head1 COPYRIGHT

Copyright (c) 2006-2007 Edoardo Sabadelli. All rights reserved.

This module is free software; you can redistribute it and/or modify it
under the terms of the Artistic license.

=cut

*/
