﻿/**
 * Copyright (c) 2006, Entriq, Inc.
 * All rights reserved.
 *
 * File name: Ajax.js
 * File identifier: 
 * Abstract: declare ajax class for remote server call
 *
 * Currently Edition:1.1.0.0
 * Author: Chen Gang
 * Finish date: 2006/04/14
 */

/**
 * @fileoverview This file includes Ajax class used for remote service call
 * @author Chen Gang
 * @version 1.1.0.0
 */

var Ajax = {
	/**
	 * function to create a cross-browsers XMLHttp object
	 * @return an XMLHttp object instance
	 */
	getTransport: function()
	{
		var xmlHttp = false;

		/*@cc_on @*/
		/*@if (@_jscript_version >= 5) 
			// JScript gives us Conditional compilation, we can cope with old IE versions. 
			// and security blocked creation of the objects. 
			try
			{ 
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 
			}
			catch (e)
			{ 
				try
				{ 
					xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 
				}
				catch (E)
				{ 
					xmlHttp = false; 
				} 
			} 
		@end @*/

		if (!xmlHttp && typeof XMLHttpRequest!='undefined')
		{ 
			xmlHttp = new XMLHttpRequest(); 
		} 

		return xmlHttp;
	},

	/**
	 * function to initialize the Ajax.Request options parameters
	 * @param options, the orginal options parameters
	 * @return an XMLHttp object instance
	 */
	initOptions : function(options)
	{
		var orgOptions =
			{
				method:       'post',
				asynchronous: true,
				parameters:   '',
				cache:        false
			}

		for (property in options)
		{
			orgOptions[property] = options[property];
		}

		return orgOptions;
	}
}

/**
 * @class an AJAX class
 * @param url url of remote page
 * @param options a multidata collection datatype
 * @constructor
 */
Ajax.Request = function(url, options)
{
	this.url = url;

	// create a XMLHttp object
	this.transport = Ajax.getTransport();

	// initation its parameters
	this.options = Ajax.initOptions(options);

	/** resposed text content of remote page */
	this.responseText = null;
	/** resposed XML content of remote page */
	this.responseXml = null;

	// create two variables to reference the request object itself and the xmlhttp object
	// used for xmlhttp object onreadystatechange event call
	var thisObj = this;
	var xmlhttp = this.transport;

	/**
	 * function to call a remote url
	 * @param url the remote url that be called, optional
	 */
	this.request = function(url)
	{
		this.responseText = null;
		this.responseXml = null;
		var options = this.options;
		
		if (url == null)
		{
			url = this.url;
		}

		var parameters = this.options.parameters || '';
		if (parameters.length > 0)
		{	
			parameters += '&_=';
		}

		try
		{
			this.url = url;
			var postUrl = url;
			if (this.options.method == 'get' && parameters.length > 0)
			{
				postUrl = this.url + (this.url.match(/\?/) ? '&' : '?') + parameters;
			}
			if (this.options.cache == false)
			{
				postUrl += (postUrl.match(/\?/) ? '&' : '?') + "random=" + Math.random();
			}

			xmlhttp.open(this.options.method, postUrl, this.options.asynchronous);

			xmlhttp.onreadystatechange = function()
			{
				var readyState = xmlhttp.readyState;
				if (readyState == 4 && xmlhttp.status >= 200 && xmlhttp.status < 300)
				{
					thisObj.responseText = xmlhttp.responseText;
					thisObj.responseXml = xmlhttp.responseXml;
					if(options["onSuccess"])
					{
						options["onSuccess"](xmlhttp);
					};
				}

				if (readyState == 4 && !(xmlhttp.status >= 200 && xmlhttp.status < 300))
				{
					if (options['onFailed'])
					{
						options['onFailed'](xmlhttp);
					}
				}

				if (readyState != 0)
				{
					var event = Ajax.Request.Events[readyState];
					if (options['on' + Ajax.Request.Events[readyState]])
					{
						options['on' + Ajax.Request.Events[readyState]](thisObj);
					}
				}
			}

			this.setRequestHeaders();

			var body = this.options.postBody ? this.options.postBody : parameters;
			this.transport.send(this.options.method == 'post' ? body : null);
			
			if (this.options.asynchronous == false)
			{
				if (this.transport.readyState == 4 && this.transport.status >= 200 && this.transport.status < 300)
				{
					this.responseText = this.transport.responseText;
					this.responseXml = this.transport.responseXml;
				}
			}
		}
		catch (e)
		{
		}
	}

	/**
	 * function to send request headers to remote url
	 * @private
	 */
	this.setRequestHeaders = function()
	{
		var requestHeaders = ['X-Requested-With', 'XMLHttpRequest'];

		if (this.options.method == 'post')
		{
			requestHeaders.push('Content-type', 'application/x-www-form-urlencoded');

			/* Force "Connection: close" for Mozilla browsers to work around
			* a bug where XMLHttpReqeuest sends an incorrect Content-length
			* header. See Mozilla Bugzilla #246651.
			*/
			if (this.transport.overrideMimeType)
			{
				requestHeaders.push('Connection', 'close');
			}
		}

		if (this.options.requestHeaders)
		{
			requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
		}

		for (var i = 0; i < requestHeaders.length; i += 2)
		{
			this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
		}
	}
}

Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];