//-------------------------------------------------------------------
// AJAX ToolKit Class [RP]
// It seems to fulfill it's raison d'être ;-)
//-------------------------------------------------------------------

AjaxClass = function() {
	// Version Information!
	var ClassName;						// [string]		Name of Class.
	var	VersionMajor;					// [integer]	Major version number of class.
	var VersionMinor;					// [integer]	Minor version number of class.
	var VersionBuild;					// [integer]	Build number of class.
	var VersionDate;					// [string]		Date of build of class; In format CCYY-MM-DD.
	this.ClassName						= 'AJAX Class';
	this.VersionMajor					= 2;
	this.VersionMinor					= 4;
	this.VersionBuild					= 20;
	this.VersionDate					= '2008-06-12';

	// Public
	var URL;							// [string]		AJAX URL.
	var Method;							// [string]		AJAX Method call type. Default is POST.
	var Async;							// [boolean]	If set to false, then the method must not return until the request has completed. Otherwise, it must return immediately.
	var ResponseType;					// [string]		Return XML (responseXML), Text (responseText) or None (nothing).
	var ReturnColumnNames;				// [boolean]	If set to True then will return datatable column names as an array in ColumnNames property.
	var ReturnPageInfo;					// [boolean]	If set to True then will return .
	var UseRandomSeed;					// [boolean]	Add a random seed to the URL to avoid any caching.
	var ErrorCode;						// [integer]	Class Error Code >0 if error. ReadOnly!
	var AlertOnError;					// [boolean]	Alert client on error. If false then only ErrorCode is set!
	var ExtendedErrorText;				// [string]		Any dynamic error text. ReadOnly!
	var IgnoreNativeCheck;				// [boolean]	Override the check for XMLHttpRequest object. Testing only!

	// Defaults (Public)
	this.URL = '';
	this.Method = 'POST';
	this.Async = true;
	this.ResponseType = 'xml';
	this.ReturnColumnNames = false;
	this.ReturnPageInfo = false;
	this.UseRandomSeed = false;
	this.AlertOnError = true;
	this.ExtendedErrorText = '';
	this.IgnoreNativeCheck = false;

	// Private
	var _Request;						// [object]		XML Request Object.
	var _GatewayURL;					// [string]		Internal AJAX URL.
	var _Messages;						// [array]		Internal array of messages.
	var _Response;						// [object]		Instance of AJAX Response Class.
	
	// Private (const)
	var _AlertHeader;					// [string]		MessageBox header text.
	var _ReadyState_Uninitialized;		// [integer]	State of AJAX object.
	var _ReadyState_Loading;			// [integer]	State of AJAX object.
	var _ReadyState_Loaded;				// [integer]	State of AJAX object.
	var _ReadyState_Interactive;		// [integer]	State of AJAX object.
	var _ReadyState_Complete;			// [integer]	State of AJAX object.
	var _ServerStatus_OK;				// [integer]	HTTP Response Code from server.
	var _ServerStatus_Unauthorized;		// [integer]	HTTP Response Code from server.
	var _ServerStatus_Forbidden;		// [integer]	HTTP Response Code from server.
	var _ServerStatus_NotFound;			// [integer]	HTTP Response Code from server.
	var _ServerStatus_InternalError;	// [integer]	HTTP Response Code from server.
	var _ServerStatus_NotImplemented;	// [integer]	HTTP Response Code from server.

	// Defaults (Private)
	this._Request = null;
	this._Messages = new Array();
	this._Response = new AjaxResponseClass();
	this._GatewayURL = '';
	this._AlertHeader = this.ClassName+' ('+this.VersionMajor+'.'+this.VersionMinor+'.'+this.VersionBuild+')';
	this._ReadyState_Uninitialized = 0;
	this._ReadyState_Loading = 1;
	this._ReadyState_Loaded = 2;
	this._ReadyState_Interactive = 3;
	this._ReadyState_Complete = 4;
	this._ServerStatus_OK = 200;
	this._ServerStatus_Unauthorized = 401;
	this._ServerStatus_Forbidden = 403;
	this._ServerStatus_NotFound = 404;
	this._ServerStatus_InternalError = 500;
	this._ServerStatus_NotImplemented = 501;
};

AjaxClass.prototype = {
	// Public
	AjaxRequest: function(opCode, callBack, postForm) {
		var postData = null;
		var self = this;

		this.ExtendedErrorText = '';

		if (window.XMLHttpRequest && this.IgnoreNativeCheck == false) // native XMLHttpRequest object. (IE7/Mozilla/Safari)
		{ this._Request = new XMLHttpRequest(); }
		else // IE/Windows ActiveX. (IE5.x/IE6)
		{
			try		// Newer version of XMLHTTP
				{ this._Request = new ActiveXObject('Msxml2.XMLHTTP'); }
			catch (e1) {
				try
					{ this._Request = new ActiveXObject('Microsoft.XMLHTTP'); }
				catch (e2)
					{ this._Request = null; }
			}
		}
		if (this._Request == null) {
			this._MyError(1004);
			return;
		}

		// Ajax State change function
		this._Request.onreadystatechange = function() {
			if (self._Request.readyState == self._ReadyState_Complete && self._CheckAjaxResponse()) {
				self._Response.Reset();
				self._Response.Text = self._Request.responseText;
				if(self._Request.responseXML) {
					self._Response.XML = self._Request.responseXML;
					self._Response.DataTable = self._ParseDataTableXML(self._Request.responseXML);
					self._Response.ColumnNames = self._ParseColumnNamesXML(self._Request.responseXML);
					self._InitResponsePageInfo(self._Request.responseXML, self._Response);
				}
				if (callBack != null) { callBack(self._Response); }
			}
			return;
		};

		// check URL
		if (this.URL == '') {
			this._MyError(1006);
			return;
		}
		this._GatewayURL = this.URL;
		this._GatewayURL += this._UrlSep(this._GatewayURL);
		this._GatewayURL += (opCode != '' ? 'opCode=' + opCode : '');
		this._GatewayURL += (this.UseRandomSeed ? this._UrlSep(this._GatewayURL) + 'RandomSeed=' + Math.random() * 5 : '');

		// init request
		this._Request.open(this.Method, this._GatewayURL, this.Async);
		this._Request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		// init form
		if (postForm != null) {
			postData = '';
			for (var i = 0; i < postForm.elements.length; i++) {
				if (postForm.elements[i].name != '__VIEWSTATE' && postForm.elements[i].name != '__EVENTVALIDATION') {
					if (
						(postForm.elements[i].type != 'checkbox' && postForm.elements[i].type != 'radio') ||
						(postForm.elements[i].type == 'checkbox' && postForm.elements[i].checked) ||
						(postForm.elements[i].type == 'radio' && postForm.elements[i].checked)
						) {
						postData += (postData.length ? '&' : '');
						postData += postForm.elements[i].name;
						postData += '=' + escape(postForm.elements[i].value);
					}
				}
			}
		}
		// send Request
		this._Request.send(postData);
	}
	,

	// Public
	ResetAjaxWebPage: function()
	{ _GatewayURL = this.URL; }
	,

	// Public
	ErrorText: function(errorCode) {
		var msg = '';
		if (this._Messages.length == 0)
		{ this._InitMessages(); }
		try { msg = this._Messages[errorCode]; }
		catch (err) { }
		if (typeof (msg) == 'undefined' || msg == '')
		{ msg = this._Messages[0]; }
		return msg;
	}
	,

	// Private
	_LoadXML: function(xml) {
		var xmlDoc;
		// code for IE
		if (document.all) {
			xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
			xmlDoc.async = false;
			xmlDoc.loadXML(xml);
			return xmlDoc;
		}
		// code for Mozilla, etc.
		else if (document.implementation && document.implementation.createDocument) {
			//create a DOMParser
			var objDOMParser = new DOMParser();
			//create new document from string
			xmlDoc = objDOMParser.parseFromString(xml, 'text/xml');
			return xmlDoc;
		}
		else
		{ this._MyError(1005); }
	}
	,

	// Private
	_ParseDataTableXML: function(doc) {
		var myTable = new Array();
		var rowList = doc.getElementsByTagName('row');
		var o;

		// Check for zero rows
		if (rowList.length > 0) {
			for (var y = 0; y < (rowList.length); y++) {
				myTable[y] = new Object();
				o = rowList[y];
				for (var x = 0; x < o.childNodes.length; x++) {
					if (o.childNodes[x].childNodes[0] == null)
					{ eval('myTable[y].' + o.childNodes[x].nodeName + '=\'\';'); }
					else
					{ eval('myTable[y].' + o.childNodes[x].nodeName + '=o.childNodes[x].childNodes[0].nodeValue;'); }
				}
			}
		}
		return myTable;
	}
	,

	//Private
	_ParseColumnNamesXML: function(doc) {
		var colList = doc.getElementsByTagName('ColumnName');
		var colNames = new Array();

		if (this.ReturnColumnNames) {
			for (var x = 0; x < colList.length; x++)
			{ colNames[x] = colList[x].childNodes[0].nodeValue; }
		}
		return colNames;
	}
	,

	//Private
	_InitResponsePageInfo: function(doc, response) {
		if (this.ReturnPageInfo) {
			try
				{ response.PageNo = doc.getElementsByTagName('PageNo')[0].childNodes[0].nodeValue; }
			catch (e) { }
			try
				{ response.TotalPages = doc.getElementsByTagName('TotalPages')[0].childNodes[0].nodeValue; }
			catch (e) { }
			try
				{ response.TotalRecords = doc.getElementsByTagName('TotalRecords')[0].childNodes[0].nodeValue; }
			catch (e) { }
		}
	}
	,

	// Private
	_ParseDataTableText: function(xmlText)
	{ return this._ParseDataTableXML(this._loadXML(xmlText)); }
	,

	// Private
	_CheckAjaxResponse: function() {
		var result = false;

		// check server status
		try {
			switch (eval(this._Request.status)) {
				case this._ServerStatus_NotImplemented:
					this._MyError(1001);
					break;
				case this._ServerStatus_InternalError:
					this.ExtendedErrorText = this._Request.statusText;
					this._MyError(1002);
					break;
				case this._ServerStatus_NotFound:
					this._MyError(1003);
					break;
				case this._ServerStatus_OK:
					result = true;
					break;
				default:
					this.ExtendedErrorText = 'Status Code: ' + this._Request.status + '\n';
					this.ExtendedErrorText += this._Request.statusText;
					this._MyError(1008);
					break;
			}
		}
		catch (e)
			{ this._MyError(1007); }

		// check return objects
		if (this.ResponseType.toLowerCase() == 'txt' && this._Request.responseText == null)
		{ result = false; }
		else if (this.ResponseType.toLowerCase() == 'xml' && this._Request.responseXML == null)
		{ result = false; }

		return result;
	}
	,

	_MyError: function(errorCode) {
		this.ErrorCode = errorCode;
		if (this.AlertOnError) {
			var msg = this._AlertHeader;
			msg += '\n';
			msg += '_____________________';
			msg += '\n';
			msg += this._Message(errorCode);
			msg += (this.ExtendedErrorText != '' ? '\n' + this.ExtendedErrorText : '');
			alert(msg);
		}
	}
	,

	// Private
	_InitMessages: function() {
		this._Messages[0] = 'Invalid Message ID/Error Code';
		this._Messages[1001] = 'Invalid OpCode';
		this._Messages[1002] = 'Server error returned.';
		this._Messages[1003] = 'Requested URL not found.';
		this._Messages[1004] = 'AJAX Not supported';
		this._Messages[1005] = 'Your browser cannot handle this script';
		this._Messages[1006] = 'Missing URL';
		this._Messages[1007] = 'Error trying to get Request Status.';
		this._Messages[1008] = 'Unknown Request Status.';
	}
	,

	// Private
	_Message: function(id) {
		var msg = '';
		if (this._Messages.length == 0)
		{ this._InitMessages(); }
		try { msg = this._Messages[id]; }
		catch (err) { }
		if (typeof (msg) == 'undefined' || msg == '')
		{ msg = this._Messages[0]; }
		return msg;
	}
	,

	// Private
	_UrlSep: function(url)
	{ return (url.indexOf('?') < 0 ? '?' : '&'); }
}

AjaxResponseClass = function() {
	// Version Information!
	var ClassName;						// [string]		Name of Class.
	var	VersionMajor;					// [integer]	Major version number of class.
	var VersionMinor;					// [integer]	Minor version number of class.
	var VersionBuild;					// [integer]	Build number of class.
	var VersionDate;					// [string]		Date of build of class; In format CCYY-MM-DD.
	this.ClassName						= 'AJAX Response Class';
	this.VersionMajor					= 1;
	this.VersionMinor					= 0;
	this.VersionBuild					= 0;
	this.VersionDate					= '2007-01-19';

	// Public
	var Text;							// [string]		AJAX ResponseText.
	var XML;							// [string]		AJAX ResponseXML.
	var DataTable;						// [array]		Two dimentional array representing a .NET DataTable.
	var ColumnNames;					// [array]		Array of column names from returned XML DataTable.
	var PageNo;							// [integer]	Current page number.
	var TotalPages;						// [integer]	Total number of pages.
	var TotalRecords;					// [integer]	Total number of records.
	
	// Defaults (Public)
	this.Text = '';
	this.XML = '';
	this.DataTable = new Array();
	this.ColumnNames = new Array();
	this.PageNo = 0;
	this.TotalPages = 0;
	this.TotalRecords = 0;
}

AjaxResponseClass.prototype = {
	// Public
	Reset : function() {
		this.Text = '';
		this.XML = '';
		this.DataTable = new Array();
		this.ColumnNames = new Array();
		this.PageNo = 0;
		this.TotalPages = 0;
		this.TotalRecords = 0;
	}
}
