// JScript 文件
/**
 * -------------------------------------------------------------------
 * 
 * 版权所有:		使用与转载需注明出处
 * Generator:		MallZ.com 2008
 * Description:		DvAjax 是对一些 Ajax 常用操作的封装(注：当前版本不支持 XmlHttp 池)
 * WebSite:			http://www.mall-z.com/
 * Author:			林子(11403891@QQ.com)
 * Creation Date:	2008-9-16
 * Version:			1.0 Beta2
 * Modified Date:	林子(11403891@QQ.com) @2008-9-17
 * 
 * -------------------------------------------------------------------
 */
function DvAjax() {	
// Private Fields
	var _XmlHttp = null;
	var _IsDisposed = false;
	var _RequestHeaders = ({'Count' : 0, 'Items' : {}});
	var _UserName = '', _UserPassword = '';

// Public Methods
	/**
	 * Description 发送 HTTP 请求。
	 *
	 * 例子：
	 *   使用回调函数的例子：
	 *		var ajax = new DvAjax();
	 *		ajax.Request('post', 'http://……', 'boardi=1&topicid=100&boardtype=' + escape('版面名称'), function (xmlHttp) {
	 *			try
	 *			{
	 *				if ('0' === xmlHttp.responseText)
	 *				{
	 *					// Something to do
	 *				}
	 *				else
	 *				{
	 *					// Something to do
	 *				}
	 *			}
	 *			finally
	 *			{
	 *				xmlHttp.abort();
	 *			}
	 *		}, true);
	 *  不使用回调函数的例子
	 *		var ajax = null;
	 *		try
	 *		{
	 *			var xml_http = ajax.Request('post', 'http://……', 'boardi=1&topicid=100&boardtype=' + escape('版面名称'), null, true);
	 *			if ('0' === xml_http.responseText)
	 *			{
	 *				// Something to do
	 *			}
	 *			else	// 
	 *			{
	 *				// Something to do
	 *			}
	 *		}
	 *		finally
	 *		{
	 *			if (null !== ajax)
	 *			{
	 *				ajax.Dispose();
	 *				ajax = null;
	 *			}
	 *		}
	 *
	 * @author 林子(11403891@QQ.com)
	 * @param string HTTP 请求的方法
	 * @param string HTTP 请求的 URL 地址
	 * @param string 要发送的数据
	 * @param string 回调函数（接受一个 XmlHttp 类型的参数）
	 * @param bool 是否禁用 XmlHttp 的缓存
	 * @return mixed 如果未指定回调函数，则返回一个 XmlHttp 实例的引用
	 */
	this.Request = function (method, url, data, callBack, disableCache) {
		// 参数合法性判断
		if ('string' !== typeof(method))
		{
			throw new Error('参数 method 必须是一个字符串类型的值！');
		}
		// 参数合法性判断
		if ('string' !== typeof(url))
		{
			throw new Error('参数 url 必须是一个字符串类型的值！');
		}
		
		// 处理 method 参数
		method = method.toLowerCase();
		if ('get' !== method && 'post' !== method)
		{
			method = 'get';
		}
		
		// 执行一些初始化操作
		_InitXmlHttp();
		
		var async = ('function' === typeof(callBack));
		try
		{
			// 判断是否使用异步 XmlHttp 请求，如果是，则设置回调函数
			if (async)
			{
				_XmlHttp.onreadystatechange = function () {
					if (4 == _XmlHttp.readyState)
					{
						callBack(_XmlHttp);
					}
				};
			}
						
			// 打开 XmlHttp
			if ('get' === method && 'string' === typeof(data) && data.length > 0)
			{
				_XmlHttp.open(method, url + ((-1 === url.indexOf('?')) ? '?' + data : '&' + data), async, _UserName, _UserPassword);
			}
			else
			{
				_XmlHttp.open(method, url, async, _UserName, _UserPassword);
			}
			
			if (_RequestHeaders.Count > 0)
			{
				for (var key in _RequestHeaders.Items)
				{
					_XmlHttp.setRequestHeader(key, _RequestHeaders.Items[key]);
				}
			}
			
			// 如果参数 disableCache 被设置为 true，则不缓存 XmlHttp 请求
			if (true === disableCache)
			{
				_XmlHttp.setRequestHeader('If-Modified-Since', '0');
			}
			
			if ('undefined' === typeof(data) || '' === data)
			{
				data = null;
			}
			
			if ('get' === method)
			{
				_XmlHttp.send(data);
			}
			else
			{
				_XmlHttp.send(data);
			}
		}
		catch ($e)
		{
			_XmlHttp.abort();
			throw $e;
		}
		
		// 如果未设置为异步 XmlHttp 请求，则返回 XmlHttp 实例的引用
		if (!async)
		{
			return _XmlHttp;
		}
	};
	
	/**
	 * Description 自动获取 Form 表单的数据并发送到服务端
	 *
	 * 例子：
	 *   使用回调函数的例子：
	 *		var ajax = new DvAjax();
	 *		ajax.SubmitForm(document.forms['myform'], function (xmlHttp) {
	 *			try
	 *			{
	 *				if ('0' === xmlHttp.responseText)
	 *				{
	 *					// Something to do
	 *				}
	 *				else
	 *				{
	 *					// Something to do
	 *				}
	 *			}
	 *			finally
	 *			{
	 *				xmlHttp.abort();
	 *			}
	 *		}, true);
	 *  不使用回调函数的例子
	 *		var ajax = null;
	 *		try
	 *		{
	 *			var xml_http = ajax.Request(document.forms['myform'], null, true);
	 *			if ('0' === xml_http.responseText)
	 *			{
	 *				// Something to do
	 *			}
	 *			else
	 *			{
	 *				// Something to do
	 *			}
	 *		}
	 *		finally
	 *		{
	 *			if (null !== ajax)
	 *			{
	 *				ajax.Dispose();
	 *				ajax = null;
	 *			}
	 *		}
	 *
	 * @author 林子(11403891@QQ.com)
	 * @param object 要获取的表单对象的引用
	 * @param Function 要使用的回调函数（小技巧，可以传递匿名函数）
	 * @param bool 当值为 true 时，表示禁用 XmlHttp 的缓存功能
	 * @return mixed 当没有指定回调函数时，将返回 XmlHttp 对象的引用，否则返回 void
	 */
	this.SubmitForm = function (form, callBack, disableCache) {
		// 检查参数 form 是否是有效的表单对象的引用(此处的检查较简单)
		if (!form || 'undefined' === typeof(form.tagName) || 'form' !== form.tagName.toString().toLowerCase() || 'undefined' === typeof(form.elements))
		{
			throw new Error('参数 form 不是有效的表单元素的引用！');
		}
		
		var enctype = form.enctype.toString().trim().toLowerCase();
		if ('multipart/form-data' === enctype)
		{
			throw new Error('不支持带有文件上传功能的表单！');
		}
		
		// 执行一些初始化操作
		//_InitXmlHttp();
		
		// 从 form 表单取得要提交的地址
		var url = form.action.toString().trim();
		if ('' === url)						// form.action 未填写
		{
			url = window.location.href;
		}
		else if ('?' === url.charAt(0))	// form.acton 的第一个字符是“?”
		{
			url = window.location.href.replace(window.location.search, '') + url;
		}
		
		// 从 form 表单取得 method 的值
		var method = form.method.toString().trim().toLowerCase();
		if ('get' !== method && 'post' !== method)
		{
			method = 'get';
		}
		
		// 处理 form 表单要提交的数据
		var data = '', seperator = '', ele = null, type = '';
		for (var i = 0; i < form.elements.length; i++)
		{
			ele = form.elements[i];
			if (ele.disabled)
			{
				continue;			
			}
			else if ('' === ele.name)
			{
				continue;
			}
			else if ('select' === ele.name && -1 === ele.selectedIndex)
			{
				continue;
			}
			if(ele.type)
			{
			    type = ele.type.toString().toLowerCase();
			    if ('checkbox' === type && !ele.checked)
			    {
				   continue;
			    }
			    else if ('radio' === type && !ele.checked)
		        {
				   continue;
			    }
			}
			data += seperator + ele.name + '=' + escape(ele.value);
			seperator = '&';
		}
		
		// 设置 Cookie
		if (document.cookie)
		{
			this.SetRequestHeader('Cookie', document.cookie);
		}
		// 设置 Content-Type
		this.SetRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		// 发送 HTTP 请求
		return this.Request(method, url, data, callBack, disableCache);
	};
	
	/**
	 * Description 设置 HTTP 请求的头
	 *
	 * 例子：
	 *		var ajax = new DvAjax();
	 *		ajax.SetRequestHeader('Content-Type', 'text/html');
	 *		// 将 cookie 信息也传递过去(注：ajax.SubmitForm()方法的内部实现已支持自动传递 cooki)
	 *		ajax.SetRequestHeader('Cookie', document.cookie);
	 *		ajax.Request('post', 'http://……', 'boardi=1&topicid=100&boardtype=' + escape('版面名称'), function (xmlHttp) {
	 *			try
	 *			{
	 *				if ('0' === xmlHttp.responseText)
	 *				{
	 *					// Something to do
	 *				}
	 *				else
	 *				{
	 *					// Something to do
	 *				}
	 *			}
	 *			finally
	 *			{
	 *				xmlHttp.abort();
	 *			}
	 *		}, true);
	 *
	 * @author 林子(11403891@QQ.com)
	 * @param object 要获取的表单对象的引用
	 * @param Function 要使用的回调函数（小技巧，可以传递匿名函数）
	 * @param bool 当值为 true 时，表示禁用 XmlHttp 的缓存功能
	 * @return mixed 当没有指定回调函数时，将返回 XmlHttp 对象的引用，否则返回 void
	 */
	this.SetRequestHeader = function (name, value) {
		// 参数判断
		if ('string' !== typeof(name))
		{
			throw new Error('参数 name 不是合法的字符串类型的变量！');
		}
		if ('string' !== typeof(value))
		{
			throw new Error('参数 value 不是合法的字符串类型的变量！');
		}
				
		_RequestHeaders.Count = _RequestHeaders.Count + 1;
		_RequestHeaders.Items[name] = value;
	};
	
	/**
	 * Description 设置请求所需的用户名和密码
	 *
	 * 例子：
	 *		var ajax = new DvAjax();
	 *		ajax.SetRequestHeader('Content-Type', 'text/html');
	 *		ajax.SetLoginInfo('UserName', 'UserPassword');
	 *		ajax.Request('post', 'http://……', 'boardi=1&topicid=100&boardtype=' + escape('版面名称'), function (xmlHttp) {
	 *			try
	 *			{
	 *				if ('0' === xmlHttp.responseText)
	 *				{
	 *					// Something to do
	 *				}
	 *				else
	 *				{
	 *					// Something to do
	 *				}
	 *			}
	 *			finally
	 *			{
	 *				xmlHttp.abort();
	 *			}
	 *		}, true);
	 *
	 * @author 林子(11403891@QQ.com)
	 * @param object 要获取的表单对象的引用
	 * @param Function 要使用的回调函数（小技巧，可以传递匿名函数）
	 * @param bool 当值为 true 时，表示禁用 XmlHttp 的缓存功能
	 * @return mixed 当没有指定回调函数时，将返回 XmlHttp 对象的引用，否则返回 void
	 */
	this.SetLoginInfo = function (userName, userPassword) {
		if ('string' !== typeof(userName))
		{
			return false;
		}
		if ('string' !== typeof(userPassword))
		{
			return false;
		}
		
		_UserName = userName;
		_UserPassword = userPassword;
	};
	
	/**
	 * Description 仅释放 XmlHttp 所占用的资源。
	 * @author 林子(11403891@QQ.com)
	 * @return void
	 */
	this.Abort = function () {
		if (null != _XmlHttp)
		{
			_XmlHttp.abort();
		}
	};
	
	/**
	 * Description 释放 XmlHttp 所占用的资源，并且使当前实例不可用。
	 * @author 林子(11403891@QQ.com)
	 * @return void
	 */
	this.Dispose = function () {
		if (null == _XmlHttp)
		{
			return;
		}
		try
		{
			// 将所有状态设为默认
			_Initialize();
			// 设置 _IsDisposed 为 true
			_IsDisposed = true;
			// 释放 XmlHttp 对象所占用的资源
			_XmlHttp.abort();
			// 取消回调，便于下次使用
			_XmlHttp.onreadystatechange = null;
		}
		catch ($e)
		{
		}
	};
	
// Private Methods
	/**
	* Description 创建一个 XmlHttp 的实例
	* @author 林子(11403891@QQ.com)
	* @return object 成功创建则返回 XmlHttp 的一个实例
	*/
	function _CreateXmlHttp() {
		if (window.XMLHttpRequest)
		{
			return new XMLHttpRequest();
		}
		//var msxml = ['Microsoft.XMLHTTP', 'MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
		var msxml = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'];
		for (var i = 0; i < msxml.length; i++)
		{
			try
			{
				return new ActiveXObject(msxml[i]);
			}
			catch($e)
			{
			}
		}
		return null;
	}
	
	/**
	 * Description 初始化操作
	 * @author 林子(11403891@QQ.com)
	 * @return void
	 */
	function _Initialize()
	{
		// 为 String 类型的原型增加一个 trim()
		if (!('trim' in String.prototype))
		{
			String.prototype.trim = function () {
				return this.replace(/(^\s*)|(\s*$)/g, '');
			};
		}
		//_IsDisposed = false;
		_RequestHeaders = ({'Count' : 0, 'Items' : {}});
	}
	// 初始化
	_Initialize();
	
	function _InitXmlHttp()
	{
		// 判断是否已调用过 Dispose()，如果是，则势出异常
		if (true === _IsDisposed)
		{
			throw new Error('已调用过 Dispose 方法！');
		}
		// 初始化私有变量 _XmlHttp
		if (null == _XmlHttp)
		{
			_XmlHttp = _CreateXmlHttp();
			if (null == _XmlHttp)
			{
				throw new Error('您的浏览器不支持或未启用 XmlHttp！');
			}
		}
		
		// 如果 _XmlHttp.readyState 的值为4，表明上次对 this.Request 的调用已结束，需要关闭 HTTP 连接，然后直接返回 _XmlHttp
		if (4 == _XmlHttp.readyState)
		{
			_Initialize();
			_XmlHttp.abort();
			return _XmlHttp;
		}
	}
}
