[code]
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 )
{
	// C O N S T R U C T O R //
	this.setTarget(f_szTarget);

	if ( !this.getTransport() )
	{
		alert('No AJAX supported for this browser!');
	}

	this.setOptions(f_arrOptions);

	this.request();
};

Ajax.prototype = {
	// MEMBERS //

	// PROPERTIES
	/**
	 * @brief		xmlhttp
	 * @type		object
	 * @desc		The XmlHttp object that actually does the request. What kind of object this is, depends on the browser used.
	 * 
	 */
	'xmlhttp'		: null,
	/**/

	/**
	 * @brief		target
	 * @type		string
	 * @desc		The URL of the page the request is sent to. The HTTP headers are built by XmlHttp (browser dependant).
	 * 
	 */
	'target'		: '',
	/**/

	/**
	 * @brief		asynchronous
	 * @type		boolean
	 * @desc		Whether the ajax request is asynchronous. Since the A in _A_jax stands for _A_synchronous, the default is set to true.
	 * 
	 */
	'asynchronous'	: true,
	/**/

	/**
	 * @brief		method
	 * @type		string
	 * @desc		The HTTP request method.
	 * 
	 */
	'method'		: 'POST',
	/**/

	/**
	 * @brief		params
	 * @type		string
	 * @desc		The query string to act as post body.
	 * 
	 */
	'params'		: '',
	/**/

	/**
	 * @brief		onComplete
	 * @type		function
	 * @desc		The function to execute when the ajax request is made and status 4 is returned.
	 * 
	 */
	'onComplete'	: function(){},
	/**/

	/**
	 * @brief		busy
	 * @type		float
	 * @desc		The 'session id' of the current 'session'.
	 * 				It's compared to Ajax.busy (the static one).
	 * 
	 */
	'busy'			: 0,
	/**/


	// METHODS //
	'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 )
	{
		// Method
		if ( f_arrOptions['method'] )
		{
			this.method = f_arrOptions['method'];
		}

		// Parameters
		if ( f_arrOptions['params'] )
		{
			this.params = f_arrOptions['params'];
		}
/*		else if ( f_arrOptions['parameters'] )
		{
			this.params = f_arrOptions['parameters'];
		}*/

		// Completion function
		if ( f_arrOptions['onComplete'] && "function" == typeof f_arrOptions['onComplete'] )
		{
			this.onComplete = function(){ f_arrOptions['onComplete']( this.xmlhttp ) };
		}
/*		else if ( f_arrOptions['onCompletion'] && "function" == typeof f_arrOptions['onCompletion'] )
		{
			this.onComplete = function(){ f_arrOptions['onCompletion']( this.xmlhttp ) };
		}*/

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

		return true;
	},

	'request': function()
	{
		// Create 'session id'
		rnd			= Math.random();
		Ajax.busy	= rnd;
		this.busy	= rnd;

		// Start request
		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()
	{
		// Ajax statusses:
		// 0 - Means it's ready to go (uninitialized)
		// 1 - Loading
		// 2 - Finished loading
		// 3 - Almost ready for use
		// 4 - Loading is complete and ready to be dealt with.

		if ( 1 == this.xmlhttp.readyState )
		{
			Ajax.arrHandlers['onStart'](this.xmlhttp); // You might want to _not_ pass this.xmlhttp to the onStart handler function
		}
		else if ( 4 == this.xmlhttp.readyState )
		{
			// Execute the user's onComplete post-ajax function
			this.onComplete();

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

			// Execute the user's onComplete handler
			Ajax.arrHandlers['onComplete'](this.xmlhttp); // You might want to _not_ pass this.xmlhttp to the onComplete handler function
		}
	}

};

// STATIC METHODS //
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;
};
[/code]