// declare constants:
var KDCALC_FORM = "KDCALC_FORM_";

// declare variables:
var KDCalcJSAdapter;

var kdcalcHandle = null;
var findKDCalcTries = 0;

var chartMgrHandle = null;

var findChartMgrTries = 0;

var FIRST_ELEMENT = 0;

// declare local variables:
var dirty; // boolean

// declare functions:

/************************************************************************/
/** 						FIND KDCALC METHODS							*/
/************************************************************************/
function getKDCalcJSAdapter()
{
	if (KDCalcJSAdapter == null)
	{
		if(getKDCalcHandle() != null)
			KDCalcJSAdapter = getKDCalcHandle().getKDCalcJSAdapter();
	}
	
	/*if(KDCalcJSAdapter == null)
	{
		alert("Error loading KDCalc -- please reload the page.");
	}*/
	
	return KDCalcJSAdapter;
}

function getKDCalcHandle()
{
	if (kdcalcHandle == null)
	{
		kdcalcHandle = getKDCalc();
	}
	return kdcalcHandle;
}

function findKDCalc(win)
{
	while ((win.KDCalc == null) && (win.parent != null) && (win.parent != win))
	{
		findKDCalcTries++;
		// Note: 7 is an arbitrary number, but should be more than sufficient
		if (findKDCalcTries > 7) 
		{
			//alert("Error finding KDCalc -- too deeply nested.");
			return null;
		}
		win = win.parent;
	}
	return win.KDCalc;
}

function getKDCalc()
{
	var theKDCalc = findKDCalc(window);
	if ((theKDCalc == null) && (window.opener != null) && (typeof(window.opener) != "undefined"))
	{
		theKDCalc = findKDCalc(window.opener);
	}
	/*if (theKDCalc == null)
	{
		alert("Unable to find KDCalc");
	}*/
	return theKDCalc;
}

function getChartMgrHandle()
{
	if (chartMgrHandle == null)
	{
		chartMgrHandle = getChartMgr();
	}
	return chartMgrHandle;
}

function findChartMgr(win)
{
	while ((win.ChartMgr == null) && (win.parent != null) && (win.parent != win))
	{		
		findChartMgrTries++;
		// Note: 7 is an arbitrary number, but should be more than sufficient
		
		if (findChartMgrTries > 7) 
		{
			alert("Error finding ChartMgr -- too deeply nested.");
			return null;
		}
		win = win.parent;
	}	
	return win.ChartMgr;
}

function getChartMgr()
{	
	var theChartMgr = findChartMgr(window);
	if ((theChartMgr == null) && (window.opener != null) && (typeof(window.opener) != "undefined"))
	{
		theChartMgr = findChartMgr(window.opener);
	}
	if (theChartMgr == null)
	{
		//alert("Unable to find ChartMgr");
	}	
	return theChartMgr;//theChartMgr;
}


/************************************************************************/
/** 						TOOLBAR METHODS 							*/
/************************************************************************/
function doSave()
{
	//document.execCommand("SaveAs");
	window.open("saveDialog.htm", "loadSave", "status=no,toolbar=no,scrollbars=no,menubar=no,resizable=no,width=435,height=420");
}

function doLoad()
{
	window.open("loadDialog.htm", "loadSave", "status=no,toolbar=no,scrollbars=no,menubar=no,resizable=no,width=435,height=420");
}

function doPrintPreview()
{
	var OLECMDID = 7;
	/* OLECMDID values:
	* 6 - print
	* 7 - print preview
	* 8 - page setup (for printing)
	* 1 - open window
	* 4 - Save As
	* 10 - properties
	*/
	try
	{
		var PROMPT = 1; // 1 PROMPT & 2 DONT PROMPT USER
		var oWebBrowser = document.getElementById("WebBrowser1");
		if(oWebBrowser == null)
		{
			var sWebBrowser = '<OBJECT ID="WebBrowser1" WIDTH=0 HEIGHT=0 CLASSID="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2"></OBJECT>';
			document.body.insertAdjacentHTML('beforeEnd', sWebBrowser);
			oWebBrowser = document.getElementById("WebBrowser1");
		}
		oWebBrowser.ExecWB(OLECMDID,PROMPT);
	}
	catch(e)
	{
		//e.message;
		alert("Error with Print Preview, opening Print dialog.");
		print();
	}
}

function doRecalc()
{
	markClean();
	populateInterface();

	//populateKDCalc(component);
}

function doReset()
{
	KDCalcJSAdapter.reset();
	populateInterface();
}

function doHelp()
{
	window.open("help.htm", "helpDialog", "status=no,toolbar=no,scrollbars=yes,menubar=no,resizable=no,width=435,height=420");
}

function changeZoom(val)
{
	var divColl = document.all.tags("DIV");
	var len =  divColl.length;
	for(var i=0; i < len; i++)
	{
		var name = divColl[i].id;
		if(name.lastIndexOf("Tab") != name.length -3)
		{
			divColl[i].style.zoom = val + "%";
		}
	}
	//sheetDiv.style.zoom = val;
}

/************************************************************************/
/** 						CORE METHODS 								*/
/************************************************************************/

/**
 * init() should be called in the HTML's body "onLoad" event 
 * @see <body>
 */
function init(zoomVal)
{

	if(!navigator.javaEnabled())
	{
	   alert("Java must be enabled for this page to load.");
	}
	
	if(zoomVal) 
	{
		var i = 0;
		var zoomLevel;
		
		zoomLevel = zoomCtrl.options[i].value;
		while(zoomLevel < zoomVal)
		{
			zoomLevel = zoomCtrl.options[i].value;
			i++;
		}
		//alert(zoomVal + " " + zoomLevel +" "+ i);
		zoomCtrl.selectedIndex = i-1;
		changeZoom(zoomLevel);
	}
	
	populateInterface();
	
	setTimeout("initCharts()", 1000);
	
	var comp = getCalcForm().elements[FIRST_ELEMENT];
	//if(comp != null)
	//	comp.focus();
}

function initCharts()
{
	// register and populate the charts
	var Mgr = getChartMgrHandle();
	Mgr.PopulateCharts();
}


/**
 * Method returns a reference to the generated KDCalc form.
 */ 
function getCalcForm()
{
	// find the form starting with "KDCALC_FORM"
	var len = document.forms.length;
	for(j=0; j< len; j++)
	{
		var theForm = document.forms[j];
		if(theForm.name.indexOf(KDCALC_FORM) != -1)
		{
			return theForm;
		}
	}
}

/**
 * Method called when focus is given to a form element.
 */
function doFocus(component, event)
{
	unformat(component);
}

/**
 * Method called when a change happens to an input cell.
 */
function doChange(component, event)
{
	// push the value into KDCalc
	populateKDCalc(component);
	
	// handle any linked controls:
	if(component.linkCtrl != null)
	{
		var controlRef = getCalcForm().elements[component.linkCtrl];
		
		//alert(controlRef.name + " -> " + controlRef.type);
		if(controlRef.type == "checkbox")
		{
			controlRef.value = component.value;
			
			// set the hidden field value:
			//var hdnCtrlStr = "hdn" + component.id.substr(3);
			//var hdnCtrlRef = getCalcForm().elements[hdnCtrlStr];
			//hdnCtrlRef.value = component.value;
			
			var val = component.value.toUpperCase();
			if(val == "FALSE" || val == '0' || val == "")
				controlRef.checked = false;
			else
				controlRef.checked = true;
			
			// like Excel uppercase TRUE or FALSE
			if(val == "FALSE" || val == "TRUE")
				component.value = val;
		}
		else if(controlRef.type == "radio")
		{
			controlRef.value = component.value;
			
			// set the hidden field value:
			//var hdnCtrlStr = "hdn" + component.name.substr(3);
			//var hdnCtrlRef = getCalcForm().elements[hdnCtrlStr];
			//hdnCtrlRef.value = component.value;

			var val = component.value.toUpperCase();
			if(val == "FALSE" || val == '0' || val == "")
				controlRef.checked = false;
			else
				controlRef.checked = true;
			
			// like Excel uppercase TRUE or FALSE
			if(val == "FALSE" || val == "TRUE")
				component.value = val;

			var args = new Array(3);
			parseSheetRowCol(controlRef.id, args);
			getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
			
			// change the rest of the radio buttons:
			var rbtnGroup = getCalcForm().elements[controlRef.name];
			
			for(var i = 0; i < rbtnGroup.length; i++)
			{
				var tmpBtn = rbtnGroup[i];
				if(tmpBtn != controlRef)
				{
					if (tmpBtn.checked)
						val = "TRUE";
					else
						val = "FALSE";
					
					//var hdnStr = "hdn" + tmpBtn.id.substr(3);
					//var hdnRef = getCalcForm().elements[hdnStr];
					//if(hdnRef != null)
					//	hdnRef.value = val;
					
					var linkStr = "lnk" + tmpBtn.id.substr(3);
					var linkRef = getCalcForm().elements[linkStr];
					if(linkRef != null)
						linkRef.value = val;

					// push value changes into KDCalc
					var args = new Array(3);
					parseSheetRowCol(tmpBtn.id, args);
					getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
				}
			}



		}
		//else if(controlRef.name.substr(3) == "ddl")
		// select-one or select-multiple
		else if(controlRef.type.indexOf("select") == 0)
		{
			// loop through and look for the value, if it's there then set it, otherwise don't
			var len = controlRef.length;
			//alert("in select: " + len);
			for (var i=0; i < len ; i++)
			{
				if(controlRef.options[i].value == component.value)
				{
					controlRef.value = component.value;
					break;
				}
			}
		}
		//else if(controlRef.name.substr(3) == "opt")
		else if(controlRef.type == "hidden") // for form option buttons
		{
			// controlRef = "hdn" + controlRef.name.substr(3);
			controlRef.value = component.value;
		}
		else if(controlRef.type == "text" || controlRef.type == "textarea")
		{
			controlRef.value = component.value;
		}
		else if(controlRef.type == "toggle")
		{
			// toggle button uses methods
			controlRef.setValue(component.value);
		}
		else if(controlRef.type == "scroll" || controlRef.type == "spinner" )
		{
			// toggle button uses methods
			controlRef.setValue(component.value);
		}
	}
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}


/**
 * Method called when a form element looses focus.
 */
function doBlur(component, event)
{
	if(component.type == "text")
	{
		populateKDCalc(component);
		//reformat(component);
		if(autoSubmit)
			doRecalc();
		else
			markDirty();
	}
}

/**
 * Method called when a key down happens on a form element.
 */
function doKeyDown(component, event)
{
	checkDel(component, event);
}


/**
 * Pull all necessary values from KDCalc and push them in to the interface.
 */
function populateInterface()
{
	// Code added by Aleks for charting:
	var Mgr = getChartMgrHandle();
	Mgr.PopulateCharts();

	// loop through all controls
	// if it starts with ctl
	// parse out sheet, row, col
	// get the text from that sheet, row, and col
	var theForm = getCalcForm();
	var jsKDCalcAdapt = getKDCalcJSAdapter();
	if(jsKDCalcAdapt == null) return;
	
	var args = new Array(3);
	var len = theForm.length;
	for(i = 0; i <= len; i++)
	{
		try
		{
			var field = theForm.elements[i];
			if(field == null)
				continue;
			
			// use the type instead of the prefix?
			if(field.name.indexOf("ctl") == 0 || field.name.indexOf("lnk") == 0 )
			{
				parseSheetRowCol(field.name, args);
				//alert(field.name +" -> " + Number(args[0]) + ", " + Number(args[1]) + ", " + Number(args[2]));
				var val = jsKDCalcAdapt.getFormattedTextI(args[0], args[1], args[2]);
				
				if(field.format>0)
				{
					if(validateNumeric(val) || validateCurrency(val) || validatePercent(val) || validateDate(val))
						field.style.textAlign='right';
					else
						field.style.textAlign='left';
				}
				field.value = val;
			}
			else if(field.name.indexOf("ddl") == 0)
			{
				//if(field.listFillRange != null)
				if(field.getAttribute('listFillRange') != null)
				{
					var isFrmCtrl = field.getAttribute('isFormCtrl');
					//var rng = field.listFillRange.split(",");
					var rng = field.getAttribute('listFillRange').split(",");
					getOptions(field, Number(rng[0]), Number(rng[1]), Number(rng[2]), Number(rng[3]), Number(rng[4]), isFrmCtrl);
				}
				
				parseSheetRowCol(field.name, args);
				var val = jsKDCalcAdapt.getTextI(args[0], args[1], args[2]);
				field.value = val;
				// populate options
			}
			else if(field.name.indexOf("chk") == 0)
			{
				parseSheetRowCol(field.name, args);
				var val = jsKDCalcAdapt.getTextI(args[0], args[1], args[2]);
				if (val == "TRUE" || val > 0 || val < 0) // or any # except 0
					field.checked = true;
				else
					field.checked = false;
			}
			else if(field.name.indexOf("hdn") == 0)
			{
				var controlStr = "tgl" + field.name.substr(3);
				var controlRef = theForm.elements[controlStr];
				
				/*if(controlRef == null)
				{
					controlStr = "scr" + field.name.substr(3);
					controlRef = theForm.elements[controlStr];
				}
				if(controlRef == null)
				{
					controlStr = "spn" + field.name.substr(3);
					controlRef = theForm.elements[controlStr];
				}*/
				
				if(controlRef != null)
				{
					parseSheetRowCol(controlRef.name, args);
					var val = jsKDCalcAdapt.getTextI(args[0], args[1], args[2]);
					controlRef.setValue(val);
				}
			}
			else if(field.id.indexOf("rbt") == 0)
			{
	//alert("radio load: " + field.id);
				parseSheetRowCol(field.id, args);
				var val = jsKDCalcAdapt.getTextI(args[0], args[1], args[2]);
				if (val == "TRUE" || val > 0 || val < 0) // or any # except 0
					field.checked = true;
				else
					field.checked = false;
			}
			else if(field.id.indexOf("opt") == 0)
			{
				parseSheetRowCol(field.id, args);
				var val = jsKDCalcAdapt.getTextI(args[0], args[1], args[2]);
				if (val == field.value)
					field.checked = true;
				else
					field.checked = false;
			}
		}
		catch(exception)
		{
			//alert("exception:" + field.name);
		}
	}//for
	
	callKDSpecialFuncs();
}

/**
 * Pushes changed values in Interface into KDCalc.
 */
function populateKDCalc(component)
{
	var args = new Array(3);
	parseSheetRowCol(component.name, args);
	if(args != null) 
	{
		var val = component.value;
		if(val == null || val == "")
			val = "";
		//alert("populate: " + args[0] + ", " + args[1] + ", " + args[2] + ", " + val);
		getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
	}
}


/**
 * Returns a string listing all of the options for a Select control.
 */
function getOptions(selectObj, sheetIndex, tlRow, tlCol, brRow, brCol, isFormControl)
{
	var jsKDCalcAdapt = getKDCalcJSAdapter();
	if(jsKDCalcAdapt == null) return;
	
	var i = 0;
	//var curIndex = selectObj.selectedIndex;
	
	for(var row = tlRow; row <= brRow; row ++)
	{
		for(var col = tlCol; col <= brCol; col++)
		{
			var newVal = jsKDCalcAdapt.getTextI(sheetIndex, row ,col);
			var curVal = selectObj.options[i];
			if (curVal == null)
			{
				// first load
				if(isFormControl)
					selectObj.options[i] = new Option(newVal, i+1);
				else
					selectObj.options[i] = new Option(newVal, newVal);
			}
			else if (curVal != newVal)
			{
				// change captions/values if necessary
				selectObj.options[i].text = newVal;
				if(!isFormControl)
					selectObj.options[i].value = newVal;
				// form control value = i+1 <- no change
			}
			i++;
		}
	}
	//selectObj.selectedIndex = curIndex;
}

/************************************************************************/
/** 					FORM ELEMENT METHODS 							*/
/************************************************************************/

/**
 * Called when a checkBox is clicked.
 */
function checkBoxClick(control)
{
	var val = "FALSE";
	if (control.checked)
		val = "TRUE";
	
	// set the value of the hidden form field
	//var hdnStr = "hdn" + control.id.substr(3);
	//var hdnRef = getCalcForm().elements[hdnStr];
	//if(hdnRef != null)
		//hdnRef.value = val;
	
	// set the value of the linked cell
	var controlStr = "lnk" + control.name.substr(3);
	var controlRef = getCalcForm().elements[controlStr];
	if(controlRef != null)
		controlRef.value = val;
	
	// push any linked control value changes into KDCalc
	var args = new Array(3);
	parseSheetRowCol(control.name, args);
	getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
	
	// redisplay the sheet or just mark dirty?
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

/**
 * Handle an OLE radio button click.
 */
function radioBtnClick(control)
{
	var rbtnGroup = getCalcForm().elements[control.name];
	var val;
	
	for(var i = 0; i < rbtnGroup.length; i++)
	{
		var tmpBtn = rbtnGroup[i];
		
		if (tmpBtn.checked)
			val = "TRUE";
		else
			val = "FALSE";
		
		//var hdnStr = "hdn" + tmpBtn.id.substr(3);
		//var hdnRef = getCalcForm().elements[hdnStr];
		//if(hdnRef != null)
		//	hdnRef.value = val;
		
		var controlStr = "lnk" + tmpBtn.id.substr(3);
		var controlRef = getCalcForm().elements[controlStr];
		if(controlRef != null)
			controlRef.value = val;
		
		// push value changes into KDCalc
		var args = new Array(3);
		parseSheetRowCol(tmpBtn.id, args);
		getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
	}
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

/**
 * Handle a forms option button click.
 */
function optionBtnClick(control)
{
	var rbtnGroup = getCalcForm().elements[control.name];
	
	var val;
	for(var i = 0; i < rbtnGroup.length; i++)
	{
		var tmpBtn = rbtnGroup[i];
		if (tmpBtn.checked)
			val = tmpBtn.value;
	}
	
	//var hdnStr = "hdn" + tmpBtn.id.substr(3);
	//var hdnRef = getCalcForm().elements[hdnStr];
	//if(hdnRef != null)
		//hdnRef.value = val;
	
	var controlStr = "lnk" + control.id.substr(3);
	var controlRef = getCalcForm().elements[controlStr];
	if (controlRef != null)
		controlRef.value = val;
	
	// push any linked control value changes into KDCalc
	var args = new Array(3);
	parseSheetRowCol(tmpBtn.id, args);
	getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

/**
 * Handle changing a textbox
 */
function textBoxChanged(control)
{
	// set the value of the linked cell
	var controlStr = "lnk" + control.name.substr(3);
	var controlRef = getCalcForm().elements[controlStr];
	
	if(controlRef != null)
		controlRef.value = control.value;
	
	// push any linked control value changes into KDCalc
	populateKDCalc(control);
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

/**
 * Handle a ddl or listbox changing.
 */
function lboxChanged(control)
{
	// set the value of the linked cell
	var controlStr = "lnk" + control.name.substr(3);
	var controlRef = getCalcForm().elements[controlStr];
	
	if(controlRef != null)
		controlRef.value = control.value;

	// push any linked control value changes into KDCalc
	populateKDCalc(control);
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

function buttonClick(control)
{
	// insert custom macro code here
	alert("buttonClick event: " + control.name);
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

function toggleClick(control)
{
	var val = control.getValue();
	
	// set the value of the linked cell
	var linkedStr = control.getLinkedCell();
	var linkedCell = getCalcForm().elements[linkedStr];
	if(linkedCell != null)
		linkedCell.value = val;

	// push any linked control value changes into KDCalc
	var args = new Array(3);
	parseSheetRowCol(control.name, args);
	getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

function scrollClick(control)
{
	var val = control.getValue();
	
	//alert("scrollClick: " + control);
	var linkedStr = control.getLinkedCell();
	var linkedCell = getCalcForm().elements[linkedStr];
	if(linkedCell != null)
		linkedCell.value = val;
	
	// push any linked control value changes into KDCalc
	var args = new Array(3);
	parseSheetRowCol(control.name, args);
	getKDCalcJSAdapter().setValueI(args[0], args[1], args[2], val);
	
	if(autoSubmit)
		doRecalc();
	else
		markDirty();
}

/**
 * If the delete key is pressed when selecting a validation drop down, set the value to blank.
 */
function checkDel(control, evt)
{
	if(control.type.indexOf("select") == 0)
	{
		if(evt.keyCode == 46 || evt.keyCode == 8) //46 - Delete, 8 - backspace
		{
			control.value = "";
			populateKDCalc(control);
			if(autoSubmit)
				doRecalc();
			else
				markDirty();
		}
	}
}


/************************************************************************/
/** 						UTILITY METHODS 							*/
/************************************************************************/

/**
 * parses out the sheet, row, col from a control's name ctlS01R00004C003 is sheet 1, row 4, col 3 
 */
function parseSheetRowCol(sName, args)
{
	var tmpStr;
	// validate
	if(sName.length != 16)
	{
		args = null;
		return;
	}
	// remove the first 3 letters:
	tmpStr = sName.substr(2);
	// parse out the sheet, row, col:
	args[0] = Number(tmpStr.substr(tmpStr.indexOf("S")+1, 2));
	args[1] = Number(tmpStr.substr(tmpStr.indexOf("R")+1, 5));
	args[2] = Number(tmpStr.substr(tmpStr.indexOf("C")+1, 3));
}

/**
 * Called to mark the sheet ready for recalc.
 */
function markDirty()
{
	if(!dirty)
	{
		if(document.title.lastIndexOf("*") != document.title.length-1)
			document.title = document.title +"*";
		var btn = document.getElementById("recalcBtn");
		btn.style.color='#FF0000';
		btn.style.fontWeight="bold";
		dirty = true;
	}
}

/**
 * Called to mark the sheet clean - just been recalculated.
 */
function markClean()
{
	if(dirty)
	{
		document.title = document.title.substring(0, document.title.indexOf("*"));
		var btn = document.getElementById("recalcBtn");
		btn.style.color='#FFFFFF';
		btn.style.fontWeight="normal";
		dirty = false;
	}
}

/************************************************************************/
/** 						FORMAT METHODS 								*/
/************************************************************************/

/**
 * When a user clicks on an input box, unformat the input so the user changes the underlying value.
 */
function unformat(component)
{
	if(getKDCalcJSAdapter() != null)
	{
		var args = new Array(3);
		parseSheetRowCol(component.name, args);
		var tmpStr = getKDCalcJSAdapter().getTextI(args[0], args[1], args[2]);
		component.value = tmpStr;
		component.select();
	}
}

/**
 * Validates that a string contains only valid numbers.
 */
function validateNumeric(sVal)
{
	// 					-9. or 99.	   | -9 or 99  | -.9 or .99  |  w/ commas...
	var objRegExp  =  /(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)|^-?\d{1,3}(,\d{3})*\.?\d*$/;
	return objRegExp.test(sVal);
}

/**
 * Validates that a string contains only valid currency.
 */
function validateCurrency(sVal)
{
	// NOTE: Need to add internationalization support for: £, ¥, €
	//negative sign, decimals, or () negative markers are optional
	var objRegExp = /^-?\$\(?\d{1,3}(,\d{3})*\.?\d*\)?$/;
	
	return objRegExp.test(sVal);
}

/**
 * Validates that a string is a percentage
 */
function validatePercent(sVal)
{
	// 					-9. or 99.	   | -9 or 99  | -.9 or .99  |  w/ commas...
	var objRegExp = /^-?\d{1,3}(,\d{3})*\.?\d*%$/;
	return objRegExp.test(sVal);
}

/**
 * Validates that a string is a date, time, or datetime
 * from http://www.regexlib.com
 */
function validateDate(sVal)
{
	var objRegExp = /^((\d{2}(([02468][048])|([13579][26]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|([1-2][0-9])))))|(\d{2}(([02468][1235679])|([13579][01345789]))[\-\/\s]?((((0?[13578])|(1[02]))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\-\/\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\-\/\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\s(((0?[1-9])|(1[0-2]))\:([0-5][0-9])((\s)|(\:([0-5][0-9])\s))([AM|PM|am|pm]{2,2})))?$/;
	return objRegExp.test(sVal);
}


/************************************************************************/
/** 					SPECIAL METHODS 								*/
/************************************************************************/

// called from populateInterface
function callKDSpecialFuncs()
{
	try
	{
		// loop through all of the special funcs in KDCalc Engine
		var curFuncName;
		var jsKDCalcAdapt = getKDCalcJSAdapter();
		if(jsKDCalcAdapt == null) return;
		var len = jsKDCalcAdapt.getSpecialFuncCount();
		
		for(var i=0; i<len; i++)
		{
			var aFunc = jsKDCalcAdapt.getSpecialFunc(i);
			var result = aFunc.getResult();
			
			if(result.indexOf("KD_HideSheet") != -1)
			{
				try
				{
					eval(result);
				}
				catch(exception)
				{
					//alert("Error: " + exception.number + " " + exception.description);
				}
			}
		}
	}catch(exception){}
	
	var adiv = document.getElementById("sheetTabs");
	adiv.style.display = "";
}

function KD_HideSheet(sheet, cond)
{
	//alert("hide sheet: " + sheet + ": " + cond);
	var adiv = document.getElementById(sheet);
	if (cond == true)
		adiv.style.display = "none";
	else
		adiv.style.display = "";
}
