﻿var SystemConstants = new SystemConstantsBase();
var MasterLib = new MasterLibBase();
var ExtraValidation = new ExtraValidationBase();
var Browser = new BrowserBase();
var MyXML = new MyXMLBase();
var AjaxValidations = new AjaxValidationsBase();
var Utility = new UtilityBase();
var DataConvert = new DataConvertBase();


/*
 * --------------------------------------------------------------------------------
 * System wide constants
 * --------------------------------------------------------------------------------
 */
function SystemConstantsBase()
{
	this.DebugMode						= false;						// enable debug mode

	this.VirtualFolder					= "/CostSegPro/";				// HARD-CODED: The Virtual Folder.

	this.DataStringArraySeparator		= "|";							// separator for data array
	this.ThousandSeparator				= ",";							// thousand separator
	this.DecimalSeparator				= ".";							// decimal separator
	this.DefaultDateSeparator			= "/";							// the default date separator.

	this.DecimalRegexp					= "^([0-9]+)?\.?[0-9]*$";
	this.DateSeparator					= "[\/\-]";						// acceptable date formats: MM/DD/YYYY or MM-DD-YYYY
	
	this.ChooseOneLabel					= " ";


	// there is a bug if EnableAutoFormatter is enabled.  The cursor does not 
	// appear on the textbox and text not selected when the control gets focus.
	//
	// a nice feature to have, but require more fixing...
	this.EnableAutoFormatter			= true;						// enable or disable the auto formatting feature

	this.EnableAnnoyingMessageBox		= true;

	this.FlashTimeout					= 0;							// 1000 is equivalent to one second.
	this.DelaySetFocus					= 0;

	this.PostBackParser_Delimiter		= "|";
	this.Argument_Delimiter				= "²";						// SystemConstants.Argument_Delimiter


	this.DisableSavingPrompts			= true;						// disable 'Save current XXX' confirm box

	this.AjaxCalls						= 0;

	this.AutoSuggestBoxShowAll			= false;

	this.EnableWaitOnSubmit				= false;

	this.SpecialEventID					= 0;						// 2=winclose; 1=others; 0=none

	this.OpenWindowFeatures				= "height=400,width=800,status=no,toolbar=no,menubar=no,location=no,resizable=yes,scrollbars=yes";

	this.RootURL = function RootURL(url)
	{
		return url.replace("~/", this.VirtualFolder);
	}
}

function ShowStatus(message, method)
{
	if (!SystemConstants.DebugMode)
		return false;

	window.status = "DebugMode: " + method + ": " + message;
	// then reset status after 5 seconds.
	setTimeout("window.status=''", SystemConstants.FlashTimeout);
	return true;
}

function OpenWindow(title, url, htmlContent, features, focus)
{
	if (typeof(htmlContent) == "undefined" || htmlContent == null)
		htmlContent = "";

	if (typeof(features) == "undefined" || features == null)
		features = SystemConstants.OpenWindowFeatures;

	if (typeof(focus) == "undefined" || focus == null)
		focus = false;

	var w = window.open(SystemConstants.RootURL(url), title, features);

	if (htmlContent != "")
	{
		w.document.write(htmlContent);
		w.document.close();
	}

	if (focus)
		w.focus();
}

function OpenModalWindow(url, args, width, height)
{
	if (!window.showModalDialog)
		throw "Sorry, modal window is not supported.";

	if (typeof(args) == "undefined" || args == null)
		args = "";

	var features = "dialogHeight:" + height + "px ; dialogWidth:" + width + "px ; center:1; status:no; scroll:yes; scrollbars:yes; resizable:1; titlebar:0; help:0;";

//	var w = window.showModelessDialog(SystemConstants.RootURL(url), args, features);
//	return null;
	return window.showModalDialog(SystemConstants.RootURL(url), args, features);
}

/*
 * --------------------------------------------------------------------------------
 * Common features in MasterPage
 * --------------------------------------------------------------------------------
 */
function MasterLibBase()
{
	this.PageOnUnload = function PageOnUnload()
	{
		try
		{
			MasterLib.HandleSpecialEvent();

			// cleanup routine.
			MasterLib.Cleanup();

			ExtraValidation = null;
			Browser = null;
			MyXML = null;
			AjaxValidations = null;
			Utility = null;
			DataConvert = null;

			//SystemConstants = null;
			MasterLib = null;
		}
		catch(ex)
		{
			// absorb exception, if any.
			if (SystemConstants.DebugMode && confirm("PageOnUnload: Debug?"))
			{
				debugger;
			}
		}
	}

	this.HandleSpecialEvent = function HandleSpecialEvent()
	{
		switch(SystemConstants.SpecialEventID)
		{
			/* event for before browser close */
			case 2:
				//alert("Attempting to save form, close project, and logout...");
				MasterLib.AutoSaveAndLogOut(false);
				break;

			/* event for before navigate away page */
			case 1:
				//alert("Attempting to save form...");
				//document.getElementById("ctl00_btnSaveForm").click();
				break;

			case 0:
				// nothing to do...
				break;

			/* ?? */
			default:
				//alert("unknown special event= " + SystemConstants.SpecialEventID);
				break;
		}
		SystemConstants.SpecialEventID = 0;
	}

	this.PageOnBeforeUnload = function PageOnBeforeUnload()
	{
		if (!SystemConstants.EnableAnnoyingMessageBox)
			return;

		if(window.event.clientY < 0) 
		{ 
			var msg = "MS/B highly recommends that you NOT use your browser navigation because data will be lost!";
			event.returnValue = msg;

			SystemConstants.SpecialEventID = 2;
			setTimeout("SystemConstants.SpecialEventID = 1;", 100);
		}

	}

	this.OpenHelpLink = function OpenHelpLink(/*string*/ lnk)
	{
		if (lnk == "")
		{
			alert("The help topic for this item is not available.");
			return false;
		}
		
		var url = "" + SystemConstants.VirtualFolder + lnk;
		OpenWindow("TaxSegProHelp", url, "", "height=400,width=800,status=no,toolbar=no,menubar=no,location=no,resizable=yes,scrollbars=yes", true);
		return false;
	}
	
	// WARNING: Please use exact case here!
	// the entry for the LHS, TOP navigator menu items, and help topic.
	// one entry consists of: CONTROL_ID, PAGE_TITLE
	var navControlsMatrixLength = 2;
	var navControls = new Array(
		 "ctl00_Menu1_GeneralInfo"			,"General Information"
		,"ctl00_Menu1_SiteWork"				,"Site Work"
		,"ctl00_Menu1_Building"				,"Building"
		,"ctl00_Menu1_Tenants"				,"Tenants"
		,"ctl00_Menu1_TenantTakeOff"		,"Tenant Take-Offs"
		,"ctl00_Menu1_Report"				,"Reports / Calculate"
		//,"ctl00_Topmenu1_menuTop_ctl00"		,"Projects"
		//,"ctl00_Topmenu1_menuTop_ctl01"		,"Tools"
		//,"ctl00_Topmenu1_menuTop_ctl02"		,"Help"
		//,"ctl00_Topmenu1_menuTop_ctl03"		,"Logout"
	);
	
	// the entry for the New Construction LHS menu, same structure as the navControls
	// one entry consists of: CONTROL_ID, PAGE_TITLE
	var navNCControls = new Array(
	    "ctl00_Menu1_GeneralInfo", "General Information"
	   , "ctl00_Menu1_CategoryIndirects", "Category Indirects"
	   , "ctl00_Menu1_ProjectIndirect", "Project Indirect"
	   ,"ctl00_Menu1_OwnerDirect"           ,"Owner Direct"
	   ,"ctl00_Menu1_Contractors"           ,"Contractors"
	   ,"ctl00_Menu1_SubContractor"        ,"Sub Contractors"
	   ,"ctl00_Menu1_Other"                 ,"Other"	   
	   ,"ctl00_Menu1_IndirectAllocation"   ,"Indirect Allocations"
	   ,"ctl00_Menu1_Report"                ,"Reports / Calculate"    
	);
	
	this.GetNavControlByPageTitle = function GetNavControlByPageTitle(pageTitle)
	{
		pageTitle = pageTitle.toUpperCase();

		for(var i = 0; i < navControls.length; i += navControlsMatrixLength)
		{
			if (navControls[i+1].toUpperCase() == pageTitle)
				return navControls[i];
		}

		return "";
	}
	
	this.GetNCNavControlByPageTitle = function GetNCNavControlByPageTitle(pageTitle)
	{
	    pageTitle = pageTitle.toUpperCase();
	    
	    for(var i = 0; i < navNCControls.length; i += navControlsMatrixLength)
	    {
	        if (navNCControls[i+1].toUpperCase() == pageTitle)
	            return navNCControls[i];
	    }
	    
	    return "";
	}
	
	this.AuthTimeOut = function AuthTimeOut(minutes)
	{
		var ms = (minutes) * (60 * 1000);
		setTimeout("MasterLib.AutoSaveAndLogOut(false)", ms);
	}

	this.AutoSaveAndLogOut = function AutoSaveAndLogOut(showPrompt)
	{
		// show prompt, if argument not specify.
		if (typeof(showPrompt) == "undefined")
			showPrompt = true;
	
		// turn off this to prevent the popup to appear.
		SystemConstants.EnableAnnoyingMessageBox = false;
	
		// perform only on Wizard page
		if (document.getElementById("ctl00_rdoLogOut") == null)
		{
			return;
		}

		// choose 'save' or 'discard' based on page completeness.
		document.getElementById("ctl00_rdoLogOut").checked = true;
		
		if (!showPrompt)
		{
			document.getElementById("ctl00_btnCloseProjectConfirmed").click();
		}
		else
		{
			document.getElementById("ctl00_btnCloseProject").click();
		}
	}
	
	this.InitializeCloseModalWindow = function InitializeCloseModalWindow()
	{
		// this code help prevent the ClosePanelDivPanel yellow box to appear.
		var o = document.getElementById("ClosePanelDivPanel");
		if (o == null)
		{
			ShowStatus("ClosePanelDivPanel not found", "InitializeCloseModalWindow");
			return;
		}

		// always select save, by default.
		MasterLib.EvaluateSaveOnClose(true);

		var extraMessage = document.getElementById("CloseProjectExtraMessage");
		if (!ExtraValidation.PageIsValid())
		{
			extraMessage.innerHTML = "<font color='red'><b>Changes to this page will not be saved.  Please complete all required fields before proceeding.</b></font>";
		}
		else
		{
			extraMessage.innerHTML = "";
		}
		
		var title = document.getElementById("CloseProjectTitle");
		if (document.getElementById("ctl00_rdoLogOut").checked)
		{
			title.innerHTML = "Close Project and Logout";
		}
		else
		{
			title.innerHTML = "Close Project";
		}

		var cancelButton = document.getElementById("ctl00_btnCloseProjectCanceled");
		cancelButton.onclick = null;
		cancelButton.onclick = function()
		{
			document.getElementById("ctl00_rdoLogOut").checked = false;
		}


		o.style.display = "";
		setTimeout("Browser.SetFocus('ctl00_btnCloseProjectCanceled')", 250);
	}

	function get_LastNavPage()
	{
		var i = Browser.getCookie("LHSLastNavPage");
		
		if (!isNaN(i))
			return Math.round(i);
		else
			return -1;
	}
	
	function set_LastNavPage(idx)
	{
		var i = Browser.getCookie("LHSLastNavPage");
		
		if (idx > i)
			Browser.setCookie("LHSLastNavPage", idx);
	}

	this.InitializeLHSNavigator = function(value)
	{
		Browser.setCookie("LHSLastNavPage", value);
	}
	
	this.ReevaluateNCNavigator = function ReevaluateNCNavigator()
	{
	    this.EvaluateNCNavigator(ExtraValidation.PageIsValid());
	}

	this.EvaluateNCNavigator = function EvaluateNCNavigator(/*bool*/value) {
	    var advValue = false;
	    var currentPageIndex = Math.round(navNCControls.length / navControlsMatrixLength); 	// ie: max value


	    for (var i = 0; i < navNCControls.length; i += navControlsMatrixLength) {
	        var control = document.getElementById(navNCControls[i]);
	        var pageTitle = navNCControls[i + 1];
	        var idx = Math.round(i / 2);

	        if (pageTitle == "Contractors")
	            pageTitle = "Master Contractors";

	        if (control == null)
	            throw "cannot find controlId: " + navNCControls[i];

	        if (pageTitle == document.title)
	            currentPageIndex = idx;

	        if (pageTitle == "Master Contractors")
	            pageTitle = "Contractors";

	        if (currentPageIndex == idx) {
	            // current page is diabled and selected.
	            SetNCNavLink(pageTitle, true);
	            control.className = "MenuItemSelected";
	            set_LastNavPage(idx);
	        }
	    }
	}

	this.ReevaluateLHSNavigator = function ReevaluateLHSNavigator()
	{
		this.EvaluateLHSNavigator(ExtraValidation.PageIsValid());
	}
	
	this.EvaluateLHSNavigator = function EvaluateLHSNavigator(/*bool*/ value)
	{
		var advValue = false;
		var currentPageIndex = Math.round(navControls.length / navControlsMatrixLength);		// ie: max value


//		// todo: bite me.
//		if (document.title == "General Information")
//		{
//			var o = document.getElementById(NxRef("ctl00$ContentPlaceHolder$hiddenhiddenLHSLastNavPage"));
//			set_LastNavPage(o.value);
//		}


		for(var i = 0; i < navControls.length; i += navControlsMatrixLength)
		{
			var control = document.getElementById(navControls[i]);
			var pageTitle = navControls[i+1];
			var idx = Math.round(i/2);

			if (control == null)
				throw "cannot find controlId: " + navControls[i];

			if (pageTitle == document.title)
				currentPageIndex = idx;

			if (currentPageIndex == idx)
			{
				// current page is diabled and selected.
				SetNavLink(pageTitle, true);
				control.className = "MenuItemSelected";
				set_LastNavPage(idx);
			}
			else if (idx < currentPageIndex)
			{
				// previous pages are enabled.
				SetNavLink(pageTitle, true);
			}
			else if ( (idx == currentPageIndex + 1) ||
					(currentPageIndex==0 && idx == currentPageIndex + 2) )	// code to enable both SiteWork and Building on completion of General Information.
			{
				// next page is determined by whether or not the page is completed.
				// Or from prior visit.
				SetNavLink(pageTitle, value || (idx <= get_LastNavPage()));

				// cannot do this, because it is possible that the page requirements can
				// switch from valid to invalid, vice versa, depending on user input.
				//if (value)
				//	set_LastNavPage(idx);
			}
			else
			{
				// following pages are disabled unless it was enabled from prior visit.
				SetNavLink(pageTitle, idx <= get_LastNavPage());
			}
		}
	}
	
	// pageTitle			= the page title.
	// value				= the new bool value
	function SetNavLink(pageTitle, value)
	{
		var controlId = GetNavControlByPageTitle(pageTitle);
		var o = document.getElementById(controlId);

		o.disabled = !value;
	}
	
	function SetNCNavLink(pageTitle, value)
	{
	    var controlId = GetNCNavControlByPageTitle(pageTitle);
	    var o = document.getElementById(controlId);

	    o.disabled = !value;
	}

	function NavLinkWasEnable(controlId)
	{
		var s = Browser.getCookie("NAV_" + controlId);
		return s == "true" ? true : false;
	}

	this.InitializeSaveOnClose = function InitializeSaveOnClose()
	{
		this.EvaluateSaveOnClose(ExtraValidation.PageIsValid());
	}


	this.EvaluateSaveOnClose = function EvaluateSaveOnClose(value)
	{
		try
		{
			//document.getElementById('ctl00_rdoSaveChanges').disabled = !value;
			document.getElementById('ctl00_rdoSaveChanges').checked = value;
			document.getElementById('ctl00_rdoDiscardChanges').checked = !value;
		}
		catch(ex)
		{
			if (SystemConstants.DebugMode && confirm("EvaluateSaveOnClose: Debug?"))
			{
				debugger;
			}
		}
	}


	this.PageOnLoad = function PageOnLoad()
	{
		this.InitializeCloseModalWindow();
		this.ReevaluateLHSNavigator();
		// TODO: set initial focus on the first input control...
	}


	this.PageOnBeforeSubmit = function PageOnBeforeSubmit()
	{
		// ----------------------------------------------------------
		// do the following actions before to the normal submit...
		// ----------------------------------------------------------


		// remove watermark.
		ExtraValidation.PreprocessWaterMarkControl();
	}


	this.AttachPageOnSubmit = function AttachPageOnSubmit()
	{
		this.GetAnonymousCode = function(func)
		{
			if (func == null)
				return "";

			if (typeof(func) != "function")
				return "";

			var s = func.toString();

			// remove phrase: function anonymous()\n{\n
			if (s.substr(0,23) == "function anonymous()\n{\n")
			{
				s = s.substr(23);
			}
			else
			{
				var regex = new RegExp("^[ \t]*function[ \t]*[^\(\)]*([ \t]*)[^{]*\{[ \t\r\n]*", "i");
				var results = regex.exec(s);

				if (results != null)
					s = s.substr(results[0].length);
			}

			// remove phrase: \n}
			if (s.substr(s.length-2, 2) == "\n}")
			{
				s = s.substr(0, s.length-2);
			}
			else
			{
				var regex = new RegExp("[ \t\r\n]*}[ \t]*$", "i");
				var results = regex.exec(s);

				if (results != null)
					s = s.substr(0, s.length - results[0].length);
			}

			return s;
		}

		this.CreateAnonymous = function(id, eventName, code)
		{
			if (document.getElementById(id) == null)
				return;

			var script = "document.getElementById('" + id + "')." + eventName + " = null;" +
						" document.getElementById('" + id + "')." + eventName + " = function() {" + code + "}";

			try
			{
				eval(script);
			}
			catch(ex)
			{
				if (SystemConstants.DebugMode)
					alert(ex + "\n\n" + script);
			}
		}

		var controls = Browser.GetPostBackControls();
		for(var i = 0; i < controls.length; i++)
		{
			var obj = document.getElementById(controls[i]);
			
			if (obj.CreatedDynamically)
				continue;
			
			var prevCode = this.GetAnonymousCode(obj.onclick)
			if (typeof(prevCode) == "undefined" || prevCode == null || prevCode == "undefined")
			{
				prevCode = "";
			}
			var code = "MasterLib.PageOnBeforeSubmit(); " + prevCode;
			this.CreateAnonymous(obj.id, "onclick", code);
		}
	}

	
//	this.DocumentOnKeyPressProcessor = function DocumentOnKeyPressProcessor()
//	{
////		// ignore the Enter key to prevent showing the Close yellow box...
////		if (event.keyCode == 13)
////			return false;

//		if (typeof(CustomDocumentOnKeyPressProcessor) != "undefined")
//		{
//			CustomDocumentOnKeyPressProcessor();
//		}
//	}
	
	this.CancelEvent = function CancelEvent(e)
	{
		var keyCode = e.keyCode;

		if (typeof(e.preventDefault) != "undefined")
		{
			e.preventDefault();
		}
		else
		{
			e.keyCode = 0;
			e.returnValue = false;
		}
		ShowStatus("event keyCode '" + keyCode + "' has been cancelled.", "CancelEvent");
	}
	
	this.DocumentOnKeyDownProcessor = function DocumentOnKeyDownProcessor(e)
	{
		e = (e) ? e : (event) ? event : null;
		if (e == null)
			return;

		switch (e.keyCode)
		{
			case 13:	// enter
			case 27:	// escape
				switch (e.srcElement.type)
				{
					case "text":
					case "textarea":
					case "password":
						// disable clear form via ESC key
						MasterLib.CancelEvent(e);
						return false;

					default:
						// escape anywhere is fine.
						break;
				}
				break;

			case 82:	// ctrl-R
				if (!e.ctrlKey)
					break;

				if (SystemConstants.DebugMode)
				{
					// allow event in debug mode.
					break;
				}

				// disable page refresh via CTRL-R
				MasterLib.CancelEvent(e);
				return false;

			case 8:		// backspace
				if (typeof(e.srcElement.type) == "undefined" || e.srcElement.type == "undefined")
				{
					// disable back button via BS
					MasterLib.CancelEvent(e);
					return false;
				}
				break;

			default:
				//ShowStatus("keyCode: " + e.keyCode, "DocumentOnKeyDownProcessor");
				break;
		}
	}

	this.AttachDocumentOnKeyPress = function AttachDocumentOnKeyPress()
	{
		//document.onkeypress = this.DocumentOnKeyPressProcessor;
		document.onkeydown = this.DocumentOnKeyDownProcessor;
	}

	this.Cleanup = function Cleanup()
	{
		//return;
		//ShowStatus("Unloading...", "MasterLib.Cleanup");

		// -------------------------------------------------		
		// sitework
		if (typeof(NewSiteWork) != "undefined")
			NewSiteWork = null;

		// -------------------------------------------------		
		// building
		if (typeof(Building.Elevator) != "undefined")
			Building.Elevator = null;
		if (typeof(Building.HVAC) != "undefined")
			Building.HVAC = null;
		if (typeof(Building.Misc) != "undefined")
			Building.Misc = null;
		if (typeof(Building.Wall) != "undefined")
			Building.Wall = null;
		if (typeof(Building) != "undefined")
			Building = null;
		if (typeof(BuildingAjaxValidation) != "undefined")
			BuildingAjaxValidation = null;

		// -------------------------------------------------		
		// tto
		if (typeof(NewTenantTakeOffs) != "undefined")
			NewTenantTakeOffs = null;

		// -------------------------------------------------		
		// autosuggestbox
		if (typeof(g_ASBObjects) != "undefined")
		{
			for(var i=0; i<g_ASBObjects.length; i++)
			{
				g_ASBObjects[i] = null;
			}
			g_ASBObjects = null;
		}

		if (false)
		{
			// -------------------------------------------------		
			// clean up controls that were ...
			// 1) created dynamically
			// 2) xml tags
			for(var i = 0; i < document.all.length; i++)
			{
				var obj = document.all[i];

				if (obj == null)
					continue;

				DetachEventHandler(obj);

				if (typeof(obj.CreatedDynamically) == "undefined" && obj.tagName != "xml")
					continue;

				Cleanup(obj);
			}
		}

		// -------------------------------------------------		
		// the DOM too.
		DetachEventHandler(document);

		// -------------------------------------------------		
		// master lib
		SystemConstants = null;
		//MasterLib = null;				// do this from caller.
		ExtraValidation = null;
		Browser = null;
		MyXML = null;
		AjaxValidations = null;
		Utility = null;
		DataConvert = null;
	}

	function DetachEventHandler(obj)
	{
		// de-reference all event handlers
		obj.onabort = null;
		obj.onblur = null;
		obj.onchange = null;
		obj.onclick = null;
		obj.ondblclick = null;
		obj.ondragdrop = null;
		obj.onerror = null;
		obj.onfocus = null;
		obj.onkeydown = null;
		obj.onkeypress = null;
		obj.onkeyup = null;
		obj.onload = null;
		obj.onmousedown = null;
		obj.onmousemove = null;
		obj.onmouseout = null;
		obj.onmouseover = null;
		obj.onmouseup = null;
		obj.onmove = null;
		obj.onreset = null;
		obj.onresize = null;
		obj.onselect = null;
		obj.onsubmit = null;
		obj.onunload  = null;

		obj.oninit = null;
		obj.onbeforeunload = null;
	}

	function Cleanup(obj)
	{
		// remove innerHTML off xml tags
		if (obj.tagName == "xml")
			obj.innerHTML = "";

		// bye bye
		obj = null;
	}
}

/*
 * --------------------------------------------------------------------------------
 * ExtraValidation
 * --------------------------------------------------------------------------------
 */
function ExtraValidationBase()
{
	this.Enable = function Enable(controlId, value)
	{
		// distinguish this method from the base method just in case we need to do more here...
		this.EnableValidators(controlId, value);

		Browser.EnableControl(controlId, value);

//		if (SystemConstants.DebugMode)
//			window.status = "Validation " + (value ? "is" : "is not") + " enabled for " + controlId;
	}

	this.EnableValidators = function EnableValidators(controlId, value, applyNow)
	{
		if (typeof(applyNow) == "undefined")
			applyNow = false;

		var validators = this.GetValidators(controlId);
		
		if (validators == null || validators.length == 0)
			return true;

		var results = true;

		for(var i = 0; (i < validators.length) && (results); i++)
		{
			var val = validators[i];

			if (applyNow)
			{
		        if (typeof(val.evaluationfunction) == "function")
				{
					var r = val.evaluationfunction(val);
					if (!r)
						results = false;
				}
			}
			else
			{
				// do not process any validation: just enable it for later process via onSubmit.
				val.enabled = (value != false);
			}

			// turn off the yellow box and yellow popup
			if (!value)
			{
				HideValidator(val);
			}
		}
		
		return results;
	}

	// id 
	this.WarningPopups = new Array();

	this.InitializeWarningPopups = function()
	{
		var c = 0;
	
		for(var i=0; i<document.all.length; i++)
		{
			var obj = document.all[i];
			
			if (obj.tagName.toUpperCase() != "TABLE")
				continue;

			var s = obj.innerHTML;

			// look for: <img height="8" src="/TaxSegPro/Images/warning.jpg" width="8" border="0">
			var warningImageRe = new RegExp("<img.+src=\".+warning.jpg\".+>", "i");
			if (s.match(warningImageRe) == null)
				continue;

			if (obj.id == "")
				obj.id = "v_popup_win" + c;

			this.WarningPopups[c] = obj.id;

			c++;
		}
		
		return c;
	}

	this.HideAllWarningPopups = function()
	{
		if (this.WarningPopups.length == 0)
		{
			var i = this.InitializeWarningPopups();
		}

		for(var i=0; i < this.WarningPopups.length; i++)
		{
			var obj = document.getElementById(this.WarningPopups[i]);

			if (obj.tagName.toUpperCase() != "TABLE")
				continue;

			//var s = obj.innerHTML;

			// hide it...
			obj.style.display = "none";
			obj.style.visibility = "hidden";
		}
	}


	this.HideValidator = function HideValidator(val)
	{
		var o = document.getElementById(val.controltovalidate);
		
		// un-yellow the text box.
		o.className = "";
	}


	this.GetValidators = function GetValidators(controlId)
	{
		if (typeof(document.getElementById(controlId).Validators) != "undefined")
			return document.getElementById(controlId).Validators;

		var results = new Array();
		var counter = 0;

		if (!ExtraValidation.ValidatorExists())
			return results;

		for(var i = 0; i < Page_Validators.length; i++)
		{
			var val = Page_Validators[i];
			var ctl = document.getElementById(val.controltovalidate);
			if (ctl.id == controlId)
				results[counter++] = val;
		}

		return results;
	}

	// perform client-side validation and show validation messages, if any.
	this.Validate = function Validate()
	{
		var results = false;

		this.PreprocessWaterMarkControl();
		this.PreprocessDisabledControls();

		results = Page_ClientValidate();
		
		//this.PostprocessWaterMarkControl();

		return results;
	}

	/*
	1) return true means, form is empty but existing grid has at least one row
	(apply to Building, Tenants, and TTO page only)
	
	2) return false means, page must go thru the usual form validation
	*/
	this.GridHasRecordsAndNoChange = function GridHasRecordsAndNoChange()
	{
		try
		{
			var unchanged = ExtraValidation.FormChanged();

			// perform usual validation, if form has been changed.
			if (unchanged)
				return false;

			var pageId = MasterLib.GetNavControlByPageTitle(document.title);
			/*
			 "ctl00_Menu1_GeneralInfo"			,"General Information"
			,"ctl00_Menu1_SiteWork"				,"Site Work"
			,"ctl00_Menu1_Building"				,"Building"
			,"ctl00_Menu1_Tenants"				,"Tenants"
			,"ctl00_Menu1_TenantTakeOff"		,"Tenant Take-Offs"
			,"ctl00_Menu1_Report"				,"Reports / Calculate"
			*/

			switch (pageId)
			{
				case "ctl00_Menu1_Building":
					gridId = NxRef("dgExistingBuildings");
					break;

				case "ctl00_Menu1_Tenants":
					gridId = NxRef("dgExistingTenants");
					break;

				case "ctl00_Menu1_TenantTakeOff":
					gridId = NxRef("DGExistingTakeOffs");
					break;

				default:
					/* does not apply to this page */
					/* return false so it goes thru the normal validation. */
					return false;
			}


			var rows = 0;
			var otherRows = 0;

			try
			{
				// exclude the theader, tfooter, and pager -- one row for each.
				rows = document.getElementById(gridId).rows.length - 3;
			}
			catch(ex)
			{
				// absorb error.
				rows = 0;
			}

			try
			{
				var objOtherRows = document.getElementById(NxRef("lblOtherGridCount"));
				if (objOtherRows != null)
					otherRows = parseInt(objOtherRows.innerText);
			}
			catch(ex)
			{
				// absorb error.
				otherRows = 0;
			}


			// check number of rows.
			return (rows + otherRows) > 0;
		}
		catch(ex)
		{
			alert(ex ? ex.message : ex);
		}
	}


	// ExtraValidation.FormChanged()
	// will check for data changes in AjaxValidation controls only!
	this.FormChanged = function FormChanged()
	// return bool
	{
		var results = false;
		var list = this.ValidatorControls();

		for(var i = 0; i < list.length; i++)
		{
			var o = Browser.GetObject(list[i]);

			if (typeof(o.OriginalText) == "undefined")
				continue;

			if (Browser.GetValue(list[i]) != o.OriginalText)
			{
				//ShowStatus("Control '" + o.id + "' was modified", "FormChanged");

//				if (SystemConstants.DebugMode)
//				{
//					if (o.Original != "")
//					{
//						o.className = "modified";
//						setTimeout("document.getElementById('" + o.id + "').className=''", SystemConstants.FlashTimeout);
//					}	
//				}

				results = true;
				break;
			}
		}

		return results;
	}

	this.ValidatorExists = function ValidatorExists()
	// return bool
	{
		if (typeof(Page_Validators) == "undefined" || Page_Validators == null || Page_Validators.length == 0)
		{
			return false;
		}
		else
		{
			return true;
		}
	}


	this.ValidatorControls = function ValidatorControls()
	{
		if (!ExtraValidation.ValidatorExists())
			return true;

		var results = new Array();

		for(var i = 0; i < Page_Validators.length; i++)
		{
			var item = Page_Validators[i].controltovalidate;

			if (Utility.ArrayContains(results, item) == -1)
				results.push(item);
		}

		return results;
	}

	this.PreprocessDisabledControls = function PreprocessDisabledControls()
	{
		if (!ExtraValidation.ValidatorExists())
			return true;

		for (var i = 0; i < Page_Validators.length; i++)
		{
			var val = Page_Validators[i];
			var ctl = document.getElementById(val.controltovalidate);
			
			if (!val.isvalid && (!ctl.enabled || ctl.disabled))
			{
				ctl.className = "";
				val.isvalid = true;
			}
		}
	}
	
	this.PreprocessWaterMarkControl = function PreprocessWaterMarkControl()
	{
		if (!ExtraValidation.ValidatorExists())
			return true;

		for (var i = 0; i < Page_Validators.length; i++)
		{
			var val = Page_Validators[i];
			var ctl = document.getElementById(val.controltovalidate);

			if (typeof(ctl.WatermarkText) == "undefined")
				continue;
			
			if (ctl.value == ctl.WatermarkText)
				ctl.value = "";
		}
	}
	
	this.PostprocessWaterMarkControl = function PostprocessWaterMarkControl()
	{
		if (!ExtraValidation.ValidatorExists())
			return true;

		for (var i = 0; i < Page_Validators.length; i++)
		{
			var val = Page_Validators[i];
			var ctl = document.getElementById(val.controltovalidate);
			
			if (typeof(ctl.WatermarkText) == "undefined")
				continue;

			if (ctl.value == "")
				ctl.value = ctl.WatermarkText;
		}
	}

	this.PageIsValid = function PageIsValid(hideErrors)
	{
		if (typeof(hideErrors) == "undefined")
			hideErrors = true;
	
		window.status = "";

		if (!ExtraValidation.ValidatorExists())
			return true;
	
		var validators = Page_Validators;

		if (hideErrors)
		{
			ExtraValidation.HideAllWarningPopups();
		}

//		this.PreprocessWaterMarkControl();
		this.PreprocessDisabledControls();

		for (var i = 0; i < validators.length; i++)
		{
			var val = validators[i];
			
			if (val.disabled)
				continue;
			if (val.enabled != null && !val.enabled)
				continue;
			
			var ctl = document.getElementById(val.controltovalidate);

			// special tag from AjaxValidateBase control.
			if (ctl.Required == "False")
				continue;

			// must handle this differently, to avoid displaying yellow validation in advance.
			if (val.id.indexOf("reqInput") != -1)
			{
				// handle watermark differently.
				if (typeof(ctl.WatermarkText) == "string" && ctl.value == ctl.WatermarkText)
				{
					return false;
				}

				if (ctl.value == "")
				{
					return false;
				}
			}
			else
			{
				if (!val.evaluationfunction(val))
				{
					return false;
				}
			}
		}

//		this.PostprocessWaterMarkControl();

		return true;
	}
}

/*
 * --------------------------------------------------------------------------------
 * Browser
 * --------------------------------------------------------------------------------
 */
function BrowserBase()
{
	/**
	* Sets a Cookie with the given name and value.
	*
	* name       Name of the cookie
	* value      Value of the cookie
	* [expires]  Expiration date of the cookie (default: end of current session)
	* [path]     Path where the cookie is valid (default: path of calling document)
	* [domain]   Domain where the cookie is valid
	*              (default: domain of calling document)
	* [secure]   Boolean value indicating if the cookie transmission requires a
	*              secure transmission
	*/
	this.setCookie = function setCookie(NameOfCookie, value, expiredays) 
	{
		var ExpireDate = new Date ();
		ExpireDate.setTime(ExpireDate.getTime() + (expiredays * 24 * 3600 * 1000));

		// The next line stores the cookie, simply by assigning 
		// the values to the "document.cookie" object.
		// Note the date is converted to Greenwich Mean time using
		// the "toGMTstring()" function.

		document.cookie = NameOfCookie + "=" + escape(value) + 
		((expiredays == null) ? "" : "; expires=" + ExpireDate.toGMTString());
	}


	/**
	* Gets the value of the specified cookie.
	*
	* name  Name of the desired cookie.
	*
	* Returns a string containing value of specified cookie,
	*   or null if cookie does not exist.
	*/
	this.getCookie = function getCookie(NameOfCookie)
	{ 
		if (document.cookie.length > 0) 
		{ 
			var begin = document.cookie.indexOf(NameOfCookie+"="); 
			if (begin != -1) 
			{ 
				begin += NameOfCookie.length+1; 
				var end = document.cookie.indexOf(";", begin);
				if (end == -1) 
					end = document.cookie.length;
				return unescape(document.cookie.substring(begin, end)); 
			} 
		}
		return null; 
	}


	/**
	* Deletes the specified cookie.
	*
	* name      name of the cookie
	* [path]    path of the cookie (must be same as path used to create cookie)
	* [domain]  domain of the cookie (must be same as domain used to create cookie)
	*/
	this.deleteCookie = function deleteCookie(name, path, domain)
	{
		if (getCookie(name))
		{
			document.cookie = name + "=" + 
				((path) ? "; path=" + path : "") +
				((domain) ? "; domain=" + domain : "") +
				"; expires=Thu, 01-Jan-70 00:00:01 GMT";
		}
	}

	this.EnableControl = function EnableControl(controlId, value)
	{
		if (OriginalState != null)
		{
			// must wait until the State completes...
			setTimeout("Browser.EnableControl('" + controlId + "', " + value + ")", 0);
			return;
		}

		var o = document.getElementById(controlId);
		if (o == null)
		{
			ShowStatus("control not found: " + controlId, "EnableControl");
			return false;
		}
		o.disabled = !value;
		o.enabled = value;
		return true;
	}

	var OriginalState = null;

	function SaveState(id, val)
	{
//		if (this.OriginalState == null)
//			this.OriginalState = new Array();

		var idx = OriginalState.length;
		OriginalState[idx] = id;
		OriginalState[idx+1] = val;
	}

	this.GetPostBackControls = function()
	{
		var results = new Array();
		var c = 0;

		for(var i=0; i < document.all.length; i++)
		{
			var o = document.all[i];

			if (o.id == "")
				continue;

			var isPostBack = false;

			switch (o.tagName.toUpperCase())
			{
				case "A":
				case "SELECT":
					isPostBack = true;
					break;

				case "INPUT":
					isPostBack = o.type != "hidden";
					break;

				default:
					isPostBack = false;
					break;
			}

			if (!isPostBack)
				continue;

			results[c++] = o.id;
		}

		return results;
	}


	this.EnablePostBackControls = function EnablePostBackControls(value)
	{
		OriginalState = new Array();
		
		for(var i=0; i < document.all.length; i++)
		{
			var o = document.all[i];

			if (o.id == "")
				continue;

			var isPostBack = false;

			switch (o.tagName.toUpperCase())
			{
				case "A":
				case "SELECT":
					isPostBack = true;
					break;

				case "INPUT":
					isPostBack = o.type != "hidden";
					break;

				default:
					isPostBack = false;
					break;
			}

			if (!isPostBack)
				continue;
			
			SaveState(o.id, o.disabled);
			o.disabled = !value;
		}
	}

//	this.EnableControls = function EnableControls(value)
//	{
//		OriginalState = new Array();

//		for(var i=0; i < document.all.length; i++)
//		{
//			var o = document.all[i];

//			if (o.id == "")
//				continue;

//			SaveState(o.id, o.disabled);

//			o.disabled = !value;
//		}
//	}

	this.ResetEnableControls = function ResetEnableControls()
	{
		if (OriginalState == null)
			return;

		for(var i=0; i<OriginalState.length; i+=2)
		{
			var o = document.getElementById(OriginalState[i]);
			var oflag = OriginalState[i+1];
			o.disabled = oflag;
		}

		OriginalState = null;

		// TODO: Need to re-evaluate the LHS nav requirements.
		MasterLib.ReevaluateLHSNavigator();
		//ExtraValidation.HideAllWarningPopups();
	}

	this.EnableControlViaRadioButtons = function EnableControlViaRadioButtons(control, radioButtonList)
	{
		var controlID;

		if (typeof(control) == "object")
			controlID = control.id;
		else
			controlID = control;

		ExtraValidation.HideAllWarningPopups();

		for(var i=0; i<radioButtonList.length; i+=2)
		{
			if (radioButtonList[i] == "" || radioButtonList[i+1] == "")
				continue;

			var radioButton = document.getElementById(radioButtonList[i]);
			var textBox = document.getElementById(radioButtonList[i+1]);

			if (textBox == null)
				continue;

			ExtraValidation.Enable(textBox.id, radioButton.id == controlID);
		}
	}


	this.CheckControl = function CheckControl(controlId, value)
	{
		var o = document.getElementById(controlId);
		if (o == null)
		{
			ShowStatus("control not found: " + controlId, "CheckControl");
			return false;
		}
		o.checked = value;
		return true;
	}
	
	this.SetFocus = function SetFocus(controlId)
	{
		var o = document.getElementById(controlId);
		if (o == null)
		{
			ShowStatus("control not found: " + controlId, "SetFocus");
			return false;
		}

		// cannot set focus to a 'disabled' control.
		if (o.disabled)
		{
			setTimeout("Browser.SetFocus('" + controlId + "')", 1000);
			return false;
		}
		if (o.enabled != null && !o.enabled)
			return false;


		// TODO: selecting the text and then blanking the value somehow hide the cursor.
		// don't select, for the time being.
		//o.select();
		o.focus();
		
		if (typeof(o.WatermarkText) != "undefined")
		{
			if (o.value == o.WatermarkText)
			{
				setTimeout("document.getElementById('" + o.id + "').value = ''", SystemConstants.DelaySetFocus);
			}
		}
		
		return true;
	}
	
	// an attempt to fix the hidden cursor on DateTextBox control after correcting a bad entry.
	this.SetFocusAndSelectAll = function SetFocusAndSelectAll(controlId)
	{
		var o = document.getElementById(controlId);
		if (o == null)
		{
			ShowStatus("control not found: " + controlId, "SetFocusAndSelectAll");
			return false;
		}
	
		var junks = o.value;
		o.value = "";
		o.blur();
		o.value = junks;
		o.focus();
		o.select();

		return true;
	}
	
	this.ForceOnBlur = function ForceOnBlur(controlId)
	{
		var control = document.getElementById(controlId);
		var forceEnable = false;

		if (control.disabled)
		{
			forceEnable = true;
			control.disabled = false;
		}

		control.focus();
		// must do something to help trigger the blur event.
		control.value = "";
		control.blur();
		
		if (forceEnable)
		{
			control.disabled = true;
		}
	}


	this.GetObject = function GetObject(clientId)
	// returns object
	{
		var obj = document.getElementById(clientId);
		if (obj == null)
		{
			throw "object not found: " + clientId;
		}
		return obj;
	}

	this.GetValue = function GetValue(clientId)
	// returns string
	{
		//return GetObject(clientId).value;
		var o = GetObject(clientId);
		var s = o.value;

		if ((typeof(o.WatermarkText) != "undefined") && (Utility.Trim(o.WatermarkText) != ""))
		{
			s = (s == o.WatermarkText) ? "" : s;
		}

		return s;
	}

	this.DumpObjects = function DumpObjects()
	{
		if (!SystemConstants.DebugMode)
			return false;

		var s = "<table border='1' cellpadding='5' cellspacing='0' width='100%'>";

		for(var i = 0; i < document.all.length; i++)
		{
			var obj = document.all[i];
			var data = escape(obj.innerHTML);
			var datalen = String(obj.innerHTML).length;

			s += "<tr>"
				+ "<td>" + i + "</td>"
				+ "<td>" + obj.tagName + "&nbsp;</td>"
				+ "<td>" + obj.id+ "&nbsp;</td>";
			
			if (datalen > 0)
			{
				s += "<td><input type='button' id='Button" + i + "' value='View' onclick='alert(unescape(TextBox" + i + ".value))'>"
					+ "<input type='hidden' id='TextBox" + i + "' value='" + data + "'>"
					+ " " + datalen + " byte(s)"
					+ "</td></tr>";
			}
			else
			{
				s += "<td>Empty</td></tr>";
			}
			
			window.status = "Dumping object " + i + " of " + document.all.length;
		}

		s += "</table>";
		OpenWindow("DumpObjects", "", s, "", false);
		return true;
	}

}



/*
 * --------------------------------------------------------------------------------
 * My XML version ...
 * --------------------------------------------------------------------------------
 */
function MyXMLBase()
{
	/*Creates Xml Object on basis of Xml Data passed
	and returns object loaded with passed xml*/
	this.CreateXmlObject = function CreateXmlObject(strXml)
	{
		var xmlDoc;
		
		/*Code for IE*/
		if(window.ActiveXObject)
		{
			xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async = false;
			xmlDoc.onreadystatechange = function()
				{
					if(xmlDoc.readyState != 4)
					{return(false);}
				}
			xmlDoc.loadXML(strXml);
		}
		/*Code for Mozilla etc.*/
		else if(document.implementation && document.implementation.createDocument)
		{
			xmlDoc = document.implementation.createDocument("","",null);
			xmlDoc.loadXML(strXml);
		}
		else
		{
			xmlDoc = null;
		}
		
		return(xmlDoc);
	}

	/*Returns the value in the Given Node for specified nodeName*/
	this.GetNodeValue = function GetNodeValue(xmlNode,nodeName)
	{
		var xmlResultNode = GetNode(xmlNode,nodeName);

		if(xmlResultNode != null)
		{
			//return(xmlResultNode.firstChild.nodeValue);
			if(xmlResultNode.firstChild != null)
			{
				return(xmlResultNode.firstChild.nodeValue);
			}
			else
			{
				return(null);
			}
		}
		else
		{
			return(null);
		}
	}

	/*returns the Specified node from passed xmlNode*/
	this.GetNode = function GetNode(xmlNode,nodeName)
	{
		var xmlChild = xmlNode.firstChild;
		
		while(xmlChild != null)
		{
			if(xmlChild.nodeName.toUpperCase() == nodeName.toUpperCase())
			{
				return(xmlChild);
			}
			
			xmlChild = xmlChild.nextSibling;
		}
		
		return(null);
	}

	/*returns the child node containing specified value for the id attribute*/
	this.GetNodeBasedOnAttribute = function GetNodeBasedOnAttribute(xmlNode,attrName,attrValue)
	{
		var xmlChild = xmlNode.firstChild;
		
		while(xmlChild != null)
		{
			if(GetXmlNodeAttributeValue(attrName,xmlChild) != null)
			{
				if(GetXmlNodeAttributeValue(attrName,xmlChild).toUpperCase() == attrValue.toUpperCase())
				{
					return(xmlChild);
				}
			}
		
			xmlChild = xmlChild.nextSibling;
		}
		
		return(null);
	}

	/*returns the Value of Specified Attribute ID from XmlNode passed*/
	this.GetXmlNodeAttributeValue = function GetXmlNodeAttributeValue(attrID,xmlNode)
	{
		for(var i = 0; i < xmlNode.attributes.length; i++)
		{
			if(xmlNode.attributes[i].name.toUpperCase() ==attrID.toUpperCase())
			{
				return(xmlNode.attributes[i].value);
			}
		}
		
		return(null);
	}

	function GetXMLDocument(xmlString)
	{
		var xmlDoc;

		// code for IE
		if (window.ActiveXObject)
		{
			xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async=false;
			xmlDoc.load(xmlString);
		}
		// code for Mozilla, etc.
		else if (document.implementation && document.implementation.createDocument)
		{
			xmlDoc= document.implementation.createDocument("","",null);
			xmlDoc.load(xmlString);
			xmlDoc.onload=getmessage
		}
		else
		{
			alert('Your browser cannot handle this script');
		}
	}
	
	function getXMLFirstChild(xmlDoc, columnName, idx)
	{
		return xmlDoc.getElementsByTagName(columnName)[idx].firstChild.nodeValue;
	}

}

// WARNING: for backward-compatible purposes!
function ExecuteXmlHTTPRequest(url,doFunction,objControl1,objControl2)
{
	this.Processor = function(sender, args)
	{
		doFunction(sender, objControl1, objControl2);
	}

	// using MasterLib ExecuteXMLRequest.
	ExecuteXMLRequest("GET", SystemConstants.RootURL(url), this.Processor, false);
}


// --------------------------------------------------
// the processorFunction must accept two arguments:
// --------------------------------------------------
// sender	- the xmlHttp object
// args		- args.Value is the responseText.
function ExecuteXMLRequest(method, url, processorFunction, showBusyFlag)
{
	// ---- begin of sanity checks ----
	if ((method.toLowerCase() != "get") && (method.toLowerCase() != "post"))
		throw "unknown method: " + method;

	if (url == "")
		throw "url is empty";

	if (typeof(processorFunction) != "function")
		throw "not a function: " + processorFunction;

	url = SystemConstants.RootURL(url);
	// ---- end of sanity checks ----
	
	
	var xmlHttp = null;
	var me = this;
	var args = {
		Value : "",
		Method : method,
		Url : url
	};
	
	// optional argument: showBusyFlag (default = true)
	showBusyFlag = (typeof(showBusyFlag) == "undefined") ?  true : showBusyFlag;

	this.GetXmlHttp = function()
	{
		var xmlHttp = null;

		if (window.ActiveXObject)
		{
			try
			{
				xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch(e)
			{
				try
				{
					xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
				}
				catch(e)
				{
				}
			}
		}
		else if (window.XMLHttpRequest)
		{
			try
			{
				xmlHttp = new XMLHttpRequest();
			}
			catch(e)
			{
			}
		}
		
		return xmlHttp;
	}

	this.RaiseOnReadyStateChangeEventHandler = function()
	{
		// 0 = Object is uninitialized
		// 1 = Request is loading
		// 2 = Request is fully loaded
		// 3 = Request is waiting for user interaction
		// 4 = Request is completed.

		switch (xmlHttp.readyState)
		{
			case 0:
				window.status = "Uninitialized, please wait..." + url;
				break;
			
			case 1:
				window.status = "Loading, please wait..." + url;
				break;
			
			case 2:
				window.status = "Loaded, please wait..." + url;
				break;
			
			case 3:
				window.status = "Waiting, please wait..." + url;
				break;

			case 4:
				window.status = "Processing..." + url;

				try
				{
					args.Value = xmlHttp.responseText;

					if (xmlHttp.status != 200)
						throw "status != 200";

					processorFunction(xmlHttp, args);

					if (showBusyFlag)
						AjaxValidations.ShowBusyStatus(false);
				}
				catch(ex)
				{
					if (ex != "cannot find controlId: ctl00_Menu1_SiteWork") 
					{					
					    if (!SystemConstants.DebugMode)
					    {
						    alert("The last action did not completed due to a server request error.  Please try again.");
					    }
					    else
					    {
						    alert("The last action did not completed due to a server request error.  Please try again. (ex='" + (ex) ? ex.message : ex + "' url='" + args.Url + "' value='" + args.Value + "')");
					    }
					}
				}

				window.status = "Done";
				xmlHttp = null;
				break;

			default:
				window.status = "Done";
				break;
		}
	}

	try
	{
		xmlHttp = this.GetXmlHttp();

		if (xmlHttp == null)
			throw "Cannot create XMLHTTP object";

		if (showBusyFlag)
			AjaxValidations.ShowBusyStatus(true);

		xmlHttp.open(method, url, true);
		xmlHttp.onreadystatechange = this.RaiseOnReadyStateChangeEventHandler;

		xmlHttp.send(null);
		return true;
	}
	catch (ex)
	{
		throw ex;
	}
}

/*
 * --------------------------------------------------------------------------------
 * My Validation code for AjaxValidator controls
 * --------------------------------------------------------------------------------
 */
function AjaxValidationsBase()
{
	// --------------------------------------------------------------------------------
	// local constants and variables
	// --------------------------------------------------------------------------------


	// --------------------------------------------------------------------------------
	// cache
	// --------------------------------------------------------------------------------
	var cacheStateAbbrList = null;					// array of Fipscode.


	// --------------------------------------------------------------------------------
	// public functions
	// --------------------------------------------------------------------------------
	this.ConvertClientIDToUniqueID = function ConvertClientIDToUniqueID(clientID)
	{
		return clientID.replace(/_/g, '$');
	}
	
	this.BusyStatus = false;
	this.ShowBusyStatus = function ShowBusyStatus(/*bool*/ workFlag)
	{
		if (workFlag)
		{
			if (this.BusyStatus == true)
				return;

			this.BusyStatus = true;
			//DivStatus("PLEASE WAIT...");
			Browser.EnablePostBackControls(false);
		}
		else
		{
			if (this.BusyStatus == false)
				return;

			Browser.ResetEnableControls(true);
			//DivStatus();
			this.BusyStatus = false;
		}
	}


	this.DivStatus = function DivStatus(msg)
	{
		var obj = document.getElementById("divStatus");
		if (obj == null)
		{
			//alert(msg);
			return;
		}
		
		if (typeof(msg) == "undefined")
		{
			obj.innerHTML = "";
			obj.style.display = "none";
		}
		else
		{
			obj.innerHTML = msg;
			obj.style.display = "";
		}
	}


	this.PostBackWithReply = function PostBackWithReply(obj, reply)
	{
		var objReply = document.getElementById(obj.ReplyControlID);
		if (objReply == null)
			throw "Reply control not found: " + obj.ReplyControlID;


		objReply.value = reply;

//		document.forms[0].submit();
//		return;

		if (typeof(__doPostBack) == "undefined")
		{
			if (document.forms.length == 0)
				throw "MyPostBack: no forms found!";

			if (SystemConstants.DebugMode)
				alert('using the form submit() method');

			document.forms[0].submit();
		}
		else
		{
			// mimic the standard post back.
			__doPostBack(ConvertClientIDToUniqueID(obj.id), "");
		}
	}

	this.DropDownList_ShowConfirmation = function DropDownList_ShowConfirmation(obj)
	{
		if (SystemConstants.DisableSavingPrompts)
		{
			// postback with Reply = true.  Always!
			PostBackWithReply(obj, true);
			return true;
		}

		this.UndoSelection = function()
		{
			// perform undo dropdownlist selection change, if enable.
			if (!DataConvert.ToBoolean(obj.UndoChangeIfCanceled))
				return;

			// ---------------------------------------------------------
			// current only support the DropDownList control, but
			// if required, other controls can be supported as well.
			// ---------------------------------------------------------

			if (obj.type == "select-one")
			{
				// this works only with the select tag
				for(var i=0; i<obj.options.length; i++)
				{
					//obj.options[i].selected = (obj.options[i].value == obj.OriginalValue);		// using OriginalValue
					obj.options[i].selected = obj.options[i].defaultSelected;						// using standard defaultSelected value.
				}
			}

			// radiobutton, textbox, etc...
		}

		// --------------------------------------------------------------------------------------
		// OVERRIDE: if enable, and if the form is unchanged, post back with InitialReply.
		// --------------------------------------------------------------------------------------
		if (DataConvert.ToBoolean(obj.CheckFormChangesFirst))
		{
			if (!ExtraValidation.FormChanged())
			{
				// --------------------------------------------------------------------------------------
				// give the custom functions the ability to change these properties: Reply and PostBack
				// --------------------------------------------------------------------------------------
				var args = {
						Reply			: DataConvert.ToBoolean(obj.InitialReply)
						, PostBack		: DataConvert.ToBoolean(obj.PostBackIfFormIsNotChanged)
					};

				// run the custom function, if defined, with the args parameter.  This function
				// can modify the Reply and PostBack values, based on other customizable logic.
				if (typeof(obj.OnFormNotChanged) == 'string' && obj.OnFormNotChanged != "")
				{
					eval(obj.OnFormNotChanged + '(obj, args)');
				}

				// cast values to ensure data integrity.
				args.PostBack = DataConvert.ToBoolean(args.PostBack);
				args.Reply = DataConvert.ToBoolean(args.Reply);
				
				if (args.PostBack)
				{
					PostBackWithReply(obj, args.Reply);
					return false;
				}

				ShowStatus("Nothing to do.  (Form not modified and postback disabled.)", "DropDownList_ShowConfirmation");

				this.UndoSelection();
				return false;	// nothing to do, return false to caller.
			}
		}


		// --------------------------------------------------------------------------------------
		// get the user response, if enable, otherwise use the InitialReply as the reply.
		// --------------------------------------------------------------------------------------
		var reply = DataConvert.ToBoolean(obj.InitialReply);

		if (DataConvert.ToBoolean(obj.Confirm))
		{
			reply = confirm(obj.ConfirmationMessage);
		}


		// --------------------------------------------------------------------------------------
		// give the custom functions the ability to change these properties: Reply and PostBack
		// --------------------------------------------------------------------------------------
		var args = {
				Reply			: reply
				, PostBack		: DataConvert.ToBoolean(obj.InitialPostBack)
			};

		// --------------------------------------------------------------------------------------
		// run custom functions, OnOkay or OnCancel, based on user response.
		// --------------------------------------------------------------------------------------
		if (reply)
		{
			// mimicking a post back with CausesValidation=true, if enable.
			if (DataConvert.ToBoolean(obj.CausesValidation))
			{
				// the form must be complete in order to proceed.
				if (!ExtraValidation.Validate())
				{
					// Validation failed: undo the dropdownlist selection change, and return false to the caller.  (No postback!)
					this.UndoSelection();
					return false;
				}
			}

			// The form has met all validation checking, and is qualified for post back.
			args.PostBack = true;

			// run the custom function, if defined, with the args parameter.  This function
			// can modify the Reply and PostBack values, based on other customizable logic.
			if (typeof(obj.OnOkay) == 'string' && obj.OnOkay != "")
			{
				eval(obj.OnOkay + '(obj, args)');
			}
		}
		else
		{
			// undo the dropdownlist selection change
			this.UndoSelection();

			// A post back option is opened for customization even if Reply = false.  The following
			// technique can be used to enable/disable post back:
			//
			// 1) Set the obj.InitialPostBack property (default is false)
			// 2) Set the args.PostBack parameter inside the custom OnCancel function.

			// run the custom function, if defined, with the args parameter.
			if (typeof(obj.OnCancel) == 'string' && obj.OnCancel != "")
			{
				eval(obj.OnCancel + '(obj, args)');
			}
		}

		// --------------------------------------------------------------------------------------
		// do post back, if enable.
		// --------------------------------------------------------------------------------------
		
		// cast values to ensure data integrity.
		args.PostBack = DataConvert.ToBoolean(args.PostBack);
		args.Reply = DataConvert.ToBoolean(args.Reply);
		
		if (args.PostBack)
		{
			PostBackWithReply(obj, args.Reply);
			return args.PostBack;
		}

		ShowStatus("Confirmation action was canceled.", "DropDownList_ShowConfirmation");

		this.UndoSelection();
		// return Reply to the caller.
		return args.Reply;
	}

	// Button and LinkButton should behave exactly like a DropDownList, except for the Undo feature.
	this.Button_ShowConfirmation = this.DropDownList_ShowConfirmation;
	this.LinkButton_ShowConfirmation = this.DropDownList_ShowConfirmation;

	this.ValidateCreditCardNumber = function(sender, args)
	{
		try
		{
			args.IsValid = false;
			var value = args.Value.toUpperCase();

			if (value.length == 0 || value.length > 16)
				throw "Credit card must be a number with 16 digits or less";

			// 16-digits or less
			var regex = new RegExp("^[0-9]+$");
			args.IsValid = regex.test(value);

			// must contain a series of X followed by a 4-digit number.
			if (!args.IsValid)
			{
				regex = new RegExp("^[X]+[0-9]{4}$");
				args.IsValid = regex.test(value);
			}
		}
		catch (ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}


	/// validate state abbreviation (FIPSCODE) code
	this.ValidateStateAbbr = function(sender, args)
	// returns bool
	{
		try
		{
			var value = args.Value.toUpperCase();

			if (value == "")
				return false; // nothing to do...

			if (value.length != 2)
				throw "State abbreviation must be a 2-character code";

			args.IsValid = false;

			GetStateAbbrList();

			for(var i = 0; i<cacheStateAbbrList.length; i++)
			{
				if (cacheStateAbbrList[i] == value)
				{
					args.IsValid = true;
					break;
				}
			}
		}
		catch (ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}


	/// validate and reformat the 5 or 6-digit zipcode
	this.ValidateAndReformatZipcode = function(sender, args)
	// returns bool
	{
		try
		{
			if (args.Value == "")
				return false; // nothing to do...

			var obj = Browser.GetObject(sender.controltovalidate);
			var value = obj.value;
			var regex;

			switch (value.length)
			{
				case 5:
					// US postal code: must be a 5-digit numeric.
					var regex = new RegExp("^[0-9][0-9][0-9][0-9][0-9]$");
					args.IsValid = regex.test(value);
					// no reformatting here...
					break;

				case 6:
				case 7:
					// Canadian postal code: A#A #A#			(where A=alpha, #=number)
					regex = new RegExp("^[A-Z][0-9][A-Z][ ]?[0-9][A-Z][0-9]$");
					args.IsValid = regex.test(value.toUpperCase());
					
					if (args.IsValid && value.length == 6)
					{
						obj.value = value.substr(0,3) + " " + value.substr(3,3);
					}
					break;

				default:
					throw "invalid length of " + value.length;
			}
			
		}
		catch(ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}

	this.ValidateNumberRange = function(sender, args)
	{
		try
		{
			if (args.Value == "")
				return false; // nothing to do...

			var obj = Browser.GetObject(sender.controltovalidate);
			var min = parseFloat(obj.MinValue);
			var max = parseFloat(obj.MaxValue);
			var value = parseFloat(args.Value.replace(",",""));

			if (obj.AllowDecimal == "true")
			{
				var numDigits = parseInt(obj.NumberDecimals);
				// perform digit truncation here then update obj.value.
				value = obj.value = Utility.KeepDecimalPlace(value, numDigits);
			}
			else
			{
				// truncate decimal, if any.
				value = obj.value = Math.round(value);
			}

			args.IsValid = (value >= min && value <= max);
		}
		catch(ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}


	/// validate input to be consisted of digits, then reformat with commas for readability.
	this.ValidateAndReformatNumber = function(sender, args)
	// returns bool
	{
		try
		{
			if (args.Value == "")
				return false; // nothing to do...

			var obj = Browser.GetObject(sender.controltovalidate);

			// Preprocess: comma is allowed as input but here we strip them out; hence,
			// keeping only the numbers (and maybe decimal).
			//
			// Craveat: does not verify the position of commas.
			var value = 1 * args.Value.replace(new RegExp(SystemConstants.ThousandSeparator, "g"), "");
			var regex = new RegExp(SystemConstants.DecimalRegexp);

			var numberDecimals = 0;
			
			if (DataConvert.ToBoolean(obj.AllowDecimal))
			{
				numberDecimals = parseInt(obj.NumberDecimals);
				value = Utility.KeepDecimalPlace(value, numberDecimals);
			}

			if (regex.test(value))
			{
				value = Utility.NumComma(value, numberDecimals);
				obj.value = value;
				args.IsValid = true;
			}
			else
			{
				args.IsValid = false;
			}
		}
		catch(ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}


	/// validate and reformat the telephone field accordingly.
	this.ValidateAndReformatPhone = function(sender, args)
	{
		try
		{
			// remove all non-numerical characters, and if the remaining is 10-digit, format and pass it.
			
			var formatChars = Array("\\-", "\\.", "\\(", "\\)", " ");
			var value = Utility.gsub("[^0-9]+", "", args.Value);

			var regex = new RegExp("^[0-9]{10}$");
			args.IsValid = regex.test(value);

			if (args.IsValid)
			{
				value = "(" + value.substr(0,3) + ") " + value.substr(3,3) + " " + value.substr(6,4);
				Browser.GetObject(sender.controltovalidate).value = value;
			}
		}
		catch (ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}


	/// compare this date value with another date value.
	this.DateCompare = function(sender, args)
	// returns bool
	{
		try
		{
			var value = args.Value;
			
			if (value == "")
				throw "date compare tokens not initalized";

			var tokens = value.split(",");
			if (tokens.length != 3)
				throw "expecting 3 tokens, but found " + value.length;
			
			var date1x = document.getElementById(tokens[0]);
			var date2x = document.getElementById(tokens[2]);

			if (date1x == null)
				throw "date1x not found";
			if (date2x == null)
				throw "date2x not found";

			if (date1x.value == "" && date1x.Required.toLowerCase() == "false")
			{
				args.IsValid = true;
				return;
			}

			if (date2x.value == "" && date2x.Required.toLowerCase() == "false")
			{
				args.IsValid = true;
				return;
			}


			var date1 = Utility.ComparableDate(date1x.value);
			var date2 = Utility.ComparableDate(date2x.value);
			
			switch (tokens[1])
			{
				case "Equal":
					args.IsValid = (date1 == date2);
					break;
				case "LesserThan":
					args.IsValid = (date1 < date2);
					break;
				case "LesserThanOrEqualTo":
					args.IsValid = (date1 <= date2);
					break;
				case "GreaterThan":
					args.IsValid = (date1 > date2);
					break;
				case "GreaterThanOrEqualTo":
					args.IsValid = (date1 >= date2);
					break;
				case "NotEqual":
					args.IsValid = (date1 != date2);
					break;
				default:
					throw "invalid operand: " + tokens[1];
			}
		}
		catch (ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}

	/// validate date accuracy for value.
	this.ValidateDate = function(sender, args)
	// returns bool
	{
		try
		{
			var value = args.Value;

			if (value == "")
				return false; // nothing to do...

			if (SystemConstants.EnableAutoFormatter)
			{
				// if the user types in 8 numbers, it automatically adds the date separators.
				// for example: 12252000 becomes 12/25/2000.
				var regex = new RegExp("^[0-9]{8}$");
				if (regex.test(value))
				{
					value = value.substr(0,2) + SystemConstants.DefaultDateSeparator + value.substr(2,2) + SystemConstants.DefaultDateSeparator + value.substr(4,4);
					//Browser.GetObject(sender.controltovalidate).value = value;
				}
			}

			args.IsValid = Utility.IsValidDate(value);

			if (args.IsValid && SystemConstants.EnableAutoFormatter)
			{
				//value = Utility.ZeroFill(mm,2) + SystemConstants.DefaultDateSeparator + Utility.ZeroFill(dd,2) + SystemConstants.DefaultDateSeparator + Utility.ZeroFill(yy,4);
				Browser.GetObject(sender.controltovalidate).value = value;
			}

			//args.IsValid = true;
		}
		catch(ex)
		{
			set_ErrorMessage(sender, ex);
			args.IsValid = false;
		}
		return args.IsValid;
	}



	// --------------------------------------------------------------------------------
	// private functions
	// --------------------------------------------------------------------------------


	function GetStateAbbrList()
	{
		if (cacheStateAbbrList != null)
			return true;

		// bypass the AJAX feature and return the hard-coded array list.
		var results = "AL|AK|AZ|AR|CA|CO|CT|DE|DC|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY" +
						"|AB|BC|MB|NB|NL|NS|NT|NU|ON|PE|QC|SK|YT";	// added Canadian Provinces

		cacheStateAbbrList = new String(results).split(SystemConstants.DataStringArraySeparator);
		return true;


		this.Processor = function(sender, args)	
		{
			// TODO: Needs an XML Parser for Firefox!
			if (args.Value.substr(0,6) != "<?xml ")
			{
				alert("not xml");
			}

			var xmlRoot = sender.responseXML.documentElement;
			var results = "";

			for(var i = 0; i <xmlRoot.childNodes.length; i++)
			{
				results += xmlRoot.childNodes[i].text + SystemConstants.DataStringArraySeparator;
			}

			cacheStateAbbrList = new String(results).split(SystemConstants.DataStringArraySeparator);
		}

		ExecuteXMLRequest("GET", SystemConstants.RootURL("~/asb_includes/GetStaticData.asmx/GetStateAbbrList"), this.Processor);
	}

	this.set_ErrorMessage = function set_ErrorMessage(sender, message)
	{
		sender.innerText = message;
		sender.errormessage = message;
		
		var obj = document.getElementById(sender.controltovalidate);
		ShowStatus(message, obj.title);
	}

	// --------------------------------------------------------------------------------
	// main code
	// --------------------------------------------------------------------------------
	//GetStateAbbrList();								// generate and cache the Fipscode.
}


function DataConvertBase()
{
	// return the initialValue, if specified, otherwise return the default.
	function ReturnDefault(initialValue, defaultValue)
	{
		if ((initialValue == null) && (defaultValue == null))
			throw "ReturnDefault: Both initialValue and defaultValue cannot be null!";

		else if (initialValue != null)
			return initialValue;

		else if (defaultValue != null)
			return defaultValue;
	}

	// value is required, and initialValue can be optional.
	this.ToBoolean = function ToBoolean(value, initialValue)
	{
		try
		{
			return String(value).toLowerCase() == "true";
		}
		catch (ex)
		{
			return ReturnDefault(initialValue, false);
		}
	}
	
	this.ToNumber = function ToNumber(value, initialValue)
	{
		// the modular formula for numeric testing was borrowed from MicrosoftAjaxWebForms.js
		if (value % 1 === 0)
			return Math.max(value, 0);

		else if (initialValue % 1 === 0)
			return Math.max(initialValue,0);

		else
			return 0;
	}
}


function UtilityBase()
{
	this.IsLeapYear = function IsLeapYear(yy)
	// returns bool
	{
		return (yy % 400 == 0 || (yy % 4 == 0 && yy % 100 != 0))
	}

	this.Quoted = function Quoted(value)
	{
		var s = new String(value);
		var regex = new RegExp("'", "ig");
		return s.replace(regex, "\\'");
	}

	this.GetDropDownText = function GetDropDownText(controlId)
	{
		var control = document.getElementById(NxRef(controlId));
		if (control == null)
			return "";
		return control.options[control.selectedIndex].text;
	}

	this.GetDropDownValue = function GetDropDownText(controlId)
	{
		var control = document.getElementById(NxRef(controlId));
		if (control == null)
			return "";
		return control.options[control.selectedIndex].value;
	}




	this.GetValue = function GetValue(control)
	{
		if (control == null)
			return "";
		else if (typeof(control) == "string")
			return control;
		else if (typeof(control) == "number")
			return control;
		else if (control.type == "select-one")
			return control.options[control.selectedIndex].text;
		else if (typeof(control.value) != "undefined")
			return control.value;
		else
			return control.innerHTML;
	}

	// ex: Utility.CreateArgument("NO", "abc", "xyz", "0");
	this.CreateArgument = function CreateArgument(/* arguments... */)
	{
		var delim = SystemConstants.Argument_Delimiter;
		var results = "";

		for(var i=0; i<arguments.length; i++)
		{
			if (arguments[i] == null)
				continue;

			if (results.length > 0)
				results += delim;

			results += this.GetValue(arguments[i]);
		}

		return results;
	}

	this.Trim = function Trim(value)
	{
		var s = new String(value);
		var regex = new RegExp("^[ \t]+|[ \t]+$", "ig");
		return s.replace(regex, "");
	}

	this.gsub = function gsub(findStr, replaceStr, value)
	{
		var regex = new RegExp(findStr, "ig");
		return value.replace(regex, replaceStr);
	}

	// Zero fill.  (If len > 0, append zeros after the value.  If len < 0, insert zeros before value.)
	this.ZeroFill = function ZeroFill(value, len)
	{
		var appendMode = true;
		if (len < 0)
		{
			len = Math.abs(len);
			appendMode = false;
		}

		var v = new String(value);

		while (v.length < len)
		{
			if (appendMode)
				v = "0" + v;
			else
				v = "" + v + "0";
		}
		return v;
	}
	

	this.ComparableDate = function ComparableDate(value)
	{
		var d = new Date(value);
		// return yyyymmdd
		return (d.getFullYear()*10000) + ((1+d.getMonth())*100) + d.getDate() + "";
	}

	this.NumComma = function NumComma(number, numberDecimals)
	// returns string
	{
		// -------------------------------------------------------------------------
		// handle for numbers with decimal
		{
			var tokens = new String(number).split(SystemConstants.DecimalSeparator);

			if (tokens.length == 1)
			{
				if (numberDecimals > 0)
				{
					// append the decimals...
					return "" + this.NumComma(tokens[0],0) + SystemConstants.DecimalSeparator + Utility.ZeroFill(0, -numberDecimals);
				}
				else
				{
					// nothing special
				}
			}
			else if (tokens.length == 2)
			{
				// process the whole number, then append the decimal digits.
				return "" + this.NumComma(tokens[0],0) + SystemConstants.DecimalSeparator +  Utility.ZeroFill(tokens[1], -numberDecimals);
			}
			else
			{
				throw "found too many decimal separators";
			}
		}
		// -------------------------------------------------------------------------

		str = new String(number);
		var val = new String();
		
		var num = str.length % 3;
		if (num == 0)
			num = 3;

		while (str.length > 0)
		{
			val += str.substring (0, num) + SystemConstants.ThousandSeparator;
			str = str.substring (num);
			num = 3;
		}
		return val.substring (0, val.length - 1);
	}

	// TODO: this method is kinda slow.
	this.ArrayContains = function ArrayContains(array, item, index, delimiter)
	{
		try
		{
			if (typeof(index) == "undefined" || index == null)
				index = -1;

			if (typeof(delimiter) == "undefined" || delimiter == null)
				delimiter = "|";

			for(var i = 0; i < array.length; i++)
			{
				var arrItem = array[i];

				if (index != -1)
				{
					var item0 = new String(arrItem).split("|");
					arrItem = item0[index];
				}

				if (arrItem == item)
					return i;
			}

			return -1;
		}
		catch(ex)
		{
			return -1;
		}
	}
	
	this.NumberRange = function NumberRange(value, min, max)
	{
		return value >= min && value <= max;
	}

	this.IsValidDate = function(value)
	{
		try
		{
			// TODO: Need to verify that separators are the same type.

			var tokens = value.split(new RegExp(SystemConstants.DateSeparator));
			
			if (tokens.length != 3)
				throw "invalid date: expecting 3 date separators, but found " + tokens.length;

			var mm = tokens[0];
			var dd = tokens[1];
			var yy = tokens[2];
			
			// -------------------------------------------------------------------------
			// apply business rules
			{

				// verify yy
				if (yy.length != 4)
					throw "year must be 4-digit";

				// verify mm
				if (mm < 1 || mm > 12)
					throw "month is must be between 1 and 12";

				var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
				daysInMonth[1] += Utility.IsLeapYear(yy) ? 1 : 0;	// apply leap year algorithm to February.


				// verify dd
				if (dd < 1 || dd > daysInMonth[mm-1])
					throw "day is not valid for given month";
			}
			// -------------------------------------------------------------------------

			// looking good.
			return true;
		}
		catch(ex)
		{
			return false;
		}
	}
	
	this.KeepDecimalPlace = function(value, numDigits)
	{
		value = parseFloat(value);
		numDigits = parseInt(numDigits);

		if (numDigits == 0)
		{
			return Math.round(value);
		}

		var denom = 1;
		for(var i=0; i<numDigits; i++)
		{
			denom *= 10;
		}

		return Math.round(value * denom) / denom;
	}
}


function NxRef(oldname)
{
	var obj;
	var newname;

	// if exist, use it ...
	obj = document.getElementById(oldname);
	if (obj != null)
		return oldname;

	// Content_
	if (oldname.substr(0,8) != "Content_")
	{
		oldname = "Content_" + oldname;
	}

	// control inside a panel?
	newname = oldname.replace("Content_", "ctl00_ContentPlaceHolder_");
	obj = document.getElementById(newname);
	if (obj != null)
		return newname;

    {
	    // control is a AjaxValidations user control?
	    var newname2 = newname + "_txtInput";
	    obj = document.getElementById(newname2);
	    if (obj != null)
		    return newname2;
    }
  
    {
	    // control is a AjaxValidations user control?
	    var newname2 = newname + "_ddlInput";
	    obj = document.getElementById(newname2);
	    if (obj != null)
		    return newname2;
    }

	throw "NxRef fail to locate control id = " + oldname;
}


// ******************************************************************************
// WARNING: Do not create a 'global' instance of this function!
//
// FYI: Because this function stores and maintains local fields, the callers
// should create a new instance of this function for each individual uses.
//
//function BlahBlahBlah()
//{
//	var parser = new PostBackParserBase();
//	string = parser.Pack(array);
//	array = parser.Unpack(string);
//}
// ******************************************************************************


function PostBackParserBase()
{
	var pos;
	var token;
	var DELIMITER = SystemConstants.PostBackParser_Delimiter;

	// parse a data block and return an array of string.
	this.Unpack = function Unpack(value)
	{
		var max = 0;
		var results = new Array();
		pos = 0;

		while (pos < value.length)
		{
			var len = GetLength(value);

			// advance past the delimiter.
			if (value.substr(pos,1) != DELIMITER)
			{
				throw "expected delimiter not found!";
			}
			pos++;

			var data = value.substr(pos,len);

			// advance past the data portion.
			pos += len;

			// advance past the delimiter.
			if (pos < value.length && value.substr(pos,1) != DELIMITER)
			{
				throw "expected delimiter not found!";
			}
			pos++;

			results[max++] = data;
		}
		return results;
	}
	
	function GetLength(value)
	{
		var pos2 = value.indexOf(DELIMITER, pos);
		var len = pos2 - pos;


		var results;
		if (len == 0)
			results = value.subString(pos);
		else
			results = value.substr(pos, len);

		// test for a number.
		if (results % 1 !== 0)
			throw "invalid number";

		pos += len;
		return Math.max(results,0);
	}

	// packs an array of string into a data block
	this.Pack = function Pack(values)
	{
		var results = "";
		for(var i = 0; i < values.length; i++)
		{
			if (i > 0)
				results += "|";
			results += values[i].length + "|" + values[i];
		}
		return results;
	}
}

function ToogleSection(targetControlID, expandedText, collapsedText, collapsed,
	enabled, expandControlID, collapseControlID, textLabelID,
	imageControlID, expandedImage, collapsedImage,
	currentModeControlID)
{
	var target = document.getElementById(targetControlID);
	if (target == null) return;

	var image = document.getElementById(imageControlID);
	if (image == null) return;

	var text = document.getElementById(textLabelID);
	if (text == null) return;

	var currentMode = document.getElementById(currentModeControlID);
	if (currentMode == null) return;

	if (target.style.display == "")
	{
		// hide it...
		target.style.display = "none";
		image.src = SystemConstants.RootURL(expandedImage);
		text.innerText = expandedText;
	}
	else
	{
		// show it...
		target.style.display = "";
		image.src = SystemConstants.RootURL(collapsedImage);
		text.innerText = collapsedText;
	}
	currentMode.value = target.style.display == "none" ? "hidden" : "visible";
}
