//==================================================================================================================================
// JAVASCRIPT FUNCTION LIBRARY FOR FIELD VALIDATION (FV)...
//==================================================================================================================================
//----------------------------------------------------------------------------------------------------------------------------------
// BEGIN HELPER FUNCTIONS - These functions do not display any alert messages, they simply return values or boleans...
//----------------------------------------------------------------------------------------------------------------------------------

/*Formats a JavaScript date object to a MM/DD/YYYY format string*/
function formatDate(dtValue)
{
	var strFormattedDate;
	/*JavaScript uses 0 to 11 for months, so add 1*/
	var strMonth = new String(dtValue.getMonth() + 1);
	var strDay = new String(dtValue.getDate());
	var strYear = new String(dtValue.getFullYear());
	if(strMonth.length == 1)
	{
		strMonth = '0' + strMonth;
	}
	if(strDay.length == 1)
	{
		strDay = '0' + strDay;
	}
	strFormattedDate =  strMonth + '/' + strDay + '/' + strYear;
	return strFormattedDate;
}

/*Returns the number of decimal places after the period in a number string*/
function getDecimalPlaces(theValue)
{		
	var myExp = /\./;
	if(myExp.exec(theValue))
	{
		var right = RegExp.rightContext;
		return right.length;
	}
	return 0;
}

/* Checks to see if one value is between two other values [Accepts integers, floats, and strings] */
function isBetween(theValue, low, high)
{
	var result = false;
	if(theValue >= low && theValue <= high)
	{
		result = true;
	}
	return result;
}

/* Accepts an array.  Checks whether the first element is found in the rest of the elements. */
function isIn(arrValues)
{
	var result = false;
	for(var x=1; x<arrValues.length; x++)
	{
		if(arrValues[0] == arrValues[x])
		{
			result = true;
		}
	}
	return result;
}

/* Check to see if a number is an integer */
function isInt(theValue)
{
	var result = true;
	var myExp = /^(\-)?\d+$/;  //Accept an optional "-" at the beginning of the value and at least 1 digit at the end.
	if(!myExp.test(theValue) || isNaN(theValue))
	{
		result = false;
	}
	return result;
}

/* Checks to see if a value is null or whitespace */
function isNull(theValue)
{
	var result = false;
	var myExp = /\S/;
	if(theValue == null || theValue.length == 0 || !myExp.test(theValue))
	{
		result = true;
	}
	return result;
}

/* Used to numerically sort an array:  arrayName.sort(numberSort) */
function numberSort(a, b)
{
	return a - b;
}

/* Given a string of a date in 'MM/DD/YYYY' format, determine if the date is valid [handles Leap Years and such] */
function isDateValid(strDate)
{
	var blnIsValid = true;
	// Extract the values from the strDate parameter...
	var intMonths = strDate.substr(0, 2);		
	var intDays = strDate.substr(3, 2);
	var intYears = strDate.substr(6, 4);
	var maxDays = getMaxDaysForMonthThisYear(intMonths, isLeapYear(intYears));

	// Remove the 0 at the beginning if there is one...
	intMonths = intMonths.substr(0, 1)==0 ? intMonths.substr(1, 1) : intMonths;
	intDays = intDays.substr(0, 1)==0 ? intDays.substr(1, 1) : intDays;		

	// Check range for months field...
	if(!isBetween(intMonths, 1, 12))
	{
		blnIsValid = false;
	}
	// Check range for days field...
	if(!isBetween(intDays, 1, maxDays))
	{
		blnIsValid = false;
	}		
	return blnIsValid;
}

/* Funciton determines if a given year is a leap year or not.*/
function isLeapYear(intYear)
{
	var isLeap = false;
	//Leap Year: In the Gregorian calendar: any year divisible by 4 except centenary years not divisible by 400
	if(intYear % 400 == 0)
	{
		isLeap = true;
	}
	else if(intYear % 100 == 0)
	{
		isLeap = false;
	}
	else if(intYear % 4 == 0)
	{
		isLeap = true;
	}
	else
	{
		isLeap = false;
	}
	return isLeap;
}

// Determines the maximum number of days for a given month...	
function getMaxDaysForMonthThisYear(intMonth, isLeap)
{
	var maxDays = 0;
	// Months of January, March, May, July, August, October, December (7).
	if(intMonth == 1 || intMonth == 3 || intMonth == 5 || intMonth == 7 || intMonth == 8 || intMonth == 10 || intMonth == 12)
	{
		maxDays = 31;
	}
	// Month of February with leap year handdling...
	else if(intMonth == 2)
	{
		if(isLeap == true)
		{
			maxDays = 29;
		}
		else
		{
			maxDays = 28;
		}
	}
	else
	// Months of April, June, September and November (4).
	{
		maxDays = 30;
	}												
	return maxDays;
}

/* Function to verify a minimum length string was entered in a text box
   IN: a string
	   required length
   OUT: true if at least minimum length, false if not.
   AUTHOR: Simona Popescu and Tim Haak   DATE: 1/7/2004 	UPDATED: n/a */
function minLen(theValue, intMinLen)
{	
	if(theValue.length < intMinLen)
	{
		return false
	}
	else
	{
		return true;
	}
}

// Function returns the minimal value if a given list...
function largestValue()
{
	var largest = arguments[0];
	for(var k = 1; k < arguments.length; k++)
	{
		if(arguments[k] > largest)
		{
			largest = arguments[k];
		}
	}
	return largest;
}

// Function returns the minimal value if a given list...
function smallestValue()
{
	var smallest = arguments[0];
	for(var k = 1; k < arguments.length; k++)
	{
		if(arguments[k] < smallest)
		{
			smallest = arguments[k];
		}
	}
	return smallest;
}
//----------------------------------------------------------------------------------------------------------------------------------
// END OF HELPER FUNCTIONS - These functions do not display any alert messages, they simply return values or boleans...
//----------------------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------------------
// BEGIN FIELD VALIDATION FUNCTIONS
//----------------------------------------------------------------------------------------------------------------------------------

/* Checks to see if the date in question is between a lower and an upper bound 
   Can be used to replace old fv.date_future:  use CF function dateAdd("m", # of months, visit_date)
   to determine upper bound */
function dateRange(txtField, strMinDate, strMaxDate)
{
	if(txtField.value.length > 0)
	{
		if(formatDateField(txtField))
		{
			var dtValue = new Date(txtField.value);
			var dtMinDate = new Date(strMinDate);
			var dtMaxDate = new Date(strMaxDate);		
			if(!isBetween(dtValue, dtMinDate, dtMaxDate))
			{
				raiseErrorOnForm(txtField);
				alert('Invalid date.  Date should be between ' + formatDate(dtMinDate) + ' and ' + formatDate(dtMaxDate));
				txtField.focus();
				txtField.select();
			}
		}
	}
}

function formatDateField(txtField)
{
	var strTemp = txtField.value;
	var intLength = strTemp.length;
	if(intLength > 0)
	{
		// If there are 8 characters (01012003), format MM/DD/YYYY
		if(intLength == 8)
		{
			txtField.value = strTemp.substr(0,2) + "/" + strTemp.substr(2,2) + "/" + strTemp.substr(4,4);
		}
		// If there are 7 characters (1012003), format 0M/DD/YYYY
		else if(intLength == 7)
		{
			txtField.value = "0" + strTemp.substr(0,1) + "/" + strTemp.substr(1,2) + "/" + strTemp.substr(3,4);
		}
		// If there are 9 characters (1/01/2003), format 0M/DD/YYYY
		else if(intLength == 9)
		{
			txtField.value = "0" + strTemp;
		}
		// Check if date is valid
		if(!isDateValid(txtField.value))
		{
			alert('This is not a valid date.');
			txtField.focus();
			txtField.select();
			return false;
		}
		else
		{
			return true;
		}
	}
}

/*Check if the value of the field is in the range between the low and high integer value*/
function inRange(txtField, intLow, intHigh)
{
	if(txtField.value.length > 0)
	{	
		if((!isBetween(txtField.value, intLow, intHigh) || !isInt(txtField.value)))
		{
			alert('This field should be between ' + intLow + ' and ' + intHigh + ' inclusive, with no decimals.');
			txtField.focus();
			txtField.select();
			return false;
		}
	}
	return true; // Means that there were no problems...
}

// Accepts an arbitrary number of arguments, all input field references whose values are required in the form...
// Can be called from an object itself: onBlur="requiredField(this)"
// or from a different object (i.e. button): onClick="requiredField(txtProtNum, txtCntrNum, txtSubjId)"
//
//Updated by Tim Haak and Simona Popescu to handle required radio buttons.
function requiredField()
{
	var myRegExp = /\S/;
	var maxLen = arguments.length;
	var missingFields = 0;
	var firstError = -1;

	for(var x = 0; x < maxLen; x++)
	{
		//Added by Tim Haak and Simona Popescu to handle required radio buttons
		//If radio group has no value and is not disabled, check for error
		if(arguments[x].type == null && arguments[x][0].type == "radio" && !arguments[x][0].disabled)
		{

			var rdbLen = arguments[x].length;
			var missingFound = 0;
			
			for(var j = 0; j < rdbLen; j++)
			{
				if(!arguments[x][j].checked)
				{
					missingFound++;
				}
			}
			
			if(missingFound == rdbLen)
			//The number missing is equal to the length of the radio button group array
			{
				missingFields++;
				//Set to true since the missing field is a radio button or checkbox
				if(firstError == -1)
				{
					firstError = x;
				}
			}	
		}
		else
		{
			// if the field is blank or contains only white space and is not disabled, mark it as an error
			if((arguments[x].value == null || arguments[x].value.length == 0 || !myRegExp.test(arguments[x].value)) && !arguments[x].disabled)
			{
				missingFields++;
				if(firstError == -1)
				{
					firstError = x;
				}
			}
		}
	}
	// if at least one required field is blank and checkError returns true, throw error
	if(missingFields > 0)
	{
		alert('You must complete all required fields before proceeding');
		if(arguments[firstError].type == null && arguments[firstError][0].type == "radio")
		//If the missing field is a radio button use the first radio button in that group to give focus to
		{
			arguments[firstError][0].focus();
			arguments[firstError][0].select();
		}
		else
		{
			arguments[firstError].focus();
			// if the field is not a select box, also select the value
			if(arguments[firstError].type != "select-one" && arguments[firstError].type != "select-multiple")
			{
				arguments[firstError].select();
			}
		}
		// return false so that submit buttons will not submit
		return false;
	}
	// otherwise, all required fields have been entered
	else
	{
		return true;
	}
}
function formatDollarAmount(objField)
{
	var myRegExp = /[$,]/g; // allows us to get rid of $'s and commas...
	objField.value = objField.value.replace(myRegExp, '');
	var myExp = /\./;
	myExp.exec(Number(objField.value).toFixed(2));
	var intAfterDecimal = RegExp.rightContext;
	
	strTemp = String(parseInt(objField.value, 10));
	strTemp2 = "";
	var counter = 0;
	for(var k = strTemp.length-1; k >= 0; k--)
	{
		strTemp2 = strTemp.charAt(k) + strTemp2;
		counter++;
		if(counter % 3 == 0 && counter != strTemp.length)
		{
			strTemp2 = ',' + strTemp2;
		}
	}
	objField.value = "$" + strTemp2 + "." + intAfterDecimal;
}

// Expand/collapse menues...
function expandCollapse(strExpandCollapseImageID, strContentID)
{
	// Regular expression to find out which state(expanded|collapsed) the block is in...
	strPattern = /iconExpand.jpg/; 
	if(strPattern.test($(strExpandCollapseImageID).src))
	{
		$(strExpandCollapseImageID).src = "/resources/images/iconCollapse.jpg";
		$(strContentID).style.display='block';
	}
	else
	{
		$(strExpandCollapseImageID).src = "/resources/images/iconExpand.jpg";
		$(strContentID).style.display='none';
	}
}
//----------------------------------------------------------------------------------------------------------------------------------
// END FIELD VALIDATION FUNCTIONS
//----------------------------------------------------------------------------------------------------------------------------------