	// This file contains the data validation JavaScript functions
	// It is included in the HTML pages with forms that need these
	// data validation routines.


// DEFINE VARIABLES

// whitespace characters
var whitespace = " \t\n\r";



/****************************************************************/

// PURPOSE:  Check to see if the string passed in is a valid time.
//	A valid time is defined as a string which is postfixed with either
//  "PM" or "AM".  Next it checks to see if there is a colon in the
//  string.  If there is, it makes sure that at least one digit preceeds
//  it and two proceed it.

	function IsTime(strTime)
	{
		var strTestTime = new String(strTime);
		strTestTime.toUpperCase();

		var bolTime = false;

		if (strTestTime.indexOf("PM",1) != -1 || strTestTime.indexOf("AM",1))
			bolTime = true;

		if (bolTime && strTestTime.indexOf(":",0) == 0)
			bolTime = false;

		var nColonPlace = strTestTime.indexOf(":",1);
		if (bolTime && ((parseInt(nColonPlace) + 5) < (strTestTime.length - 1) || (parseInt(nColonPlace) + 4) > (strTestTime.length - 1)))
			bolTime = false;


		return bolTime;
	}

/****************************************************************/

function replaceAll (s, fromStr, toStr)
{
	var new_s = s;
	for (i = 0; i < 100 && new_s.indexOf (fromStr) != -1; i++)
	{
		new_s = new_s.replace (fromStr, toStr);
	}
	return new_s;
}

/****************************************************************/

/* PURPOSE:  Since we are using the single tick mark as the
	string delimiter to construct our SQL queries, a string with
	a tick mark in it will cause a SQL error.  Therefore we replace
	all "'" with "''", which eliminates the possibility of a SQL error.
*/

function sqlSafe (s)
{
	var new_s = s;
	new_s = replaceAll (new_s, "'", "|");
	new_s = replaceAll (new_s, "|", "''");
	new_s = replaceAll (new_s, "\"", "|");
	new_s = replaceAll (new_s, "|", "''");
	return new_s;
}

/****************************************************************/

function makeSafe (i)
{
	i.value = sqlSafe (i.value);
}

/****************************************************************/

// Check whether string s is empty.

function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}

/****************************************************************/

function checkLength(s,max){
	var ilength =s.length;
	
	if (ilength > max) {
		return true;
		}	
	else{
		return false;
		}
	
}
// Returns true if string s is empty or 
// whitespace characters only.

function isWhitespace (s)

{   var i;

    // Is s empty?
    if (isEmpty(s)) return true;

    // Search through string's characters one by one
    // until we find a non-whitespace character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {   
	// Check that current character isn't whitespace.
	var c = s.charAt(i);

	if (whitespace.indexOf(c) == -1) return false;
    }

    // All characters are whitespace.
    return true;
}

/****************************************************************/

// VerifyEmailAddress (FieldName)
// 
// This script is written to check the syntax of a domestic email
// address (.com, .edu, .net, .org, .gov) and check for the
// existence of at least one ".",  only one "@" and ensures
// there is no embedded spaces.


function VerifyEmailAddress(objField)
{
  var Reason  = "Email Address entered incorrectly.  Please Ok to re-enter or Cancel to continue.\n\nReason:"
  var Success = "Email Address entered Correctly!\n\nScott G. Walch\nsgw@CyberNext.com"
  var checkStr = objField.value;
  var ix = (checkStr.length - 4)
  var RC = true;
  var x = AtSignValid = DoublePeriod = PeriodValid = SpaceValid = ExtValid = RL = 0;

  for (i = 0;  i < checkStr.length;  i++)
  {
    if (checkStr.charAt(i) == '@')
      AtSignValid++;
    else if (checkStr.charAt(i) == '.')
    {
      if (x == (i-1))
        DoublePeriod++;
      else
      {
        x = i;
        PeriodValid++;
      }
    }
    else if (checkStr.charAt(i) == ' ')
      SpaceValid ++;
  }
  if (checkStr.indexOf(".com", ix) > -1)
    ExtValid++;
  else if (checkStr.indexOf(".edu", ix) > -1)
    ExtValid++;
  else if (checkStr.indexOf(".net", ix) > -1)
    ExtValid++;
  else if (checkStr.indexOf(".org", ix) > -1)
    ExtValid++;
  else if (checkStr.indexOf(".gov", ix) > -1)
    ExtValid++;
  RL = Reason.length;
  if (AtSignValid != 1)
    Reason += "\nOnly one '@' allowed, " + AtSignValid + " found.";
  if (PeriodValid == 0)
    Reason += "\nAddress must contain at least one period.";
  if (SpaceValid > 0)
    Reason += "\nNo Spaces allowed. Address contains " + SpaceValid + " space";
  if (SpaceValid > 1)
    Reason += "s.";
  if (DoublePeriod > 0)
    Reason += "\nAddress contains multiple periods in a row.";
  if (ExtValid == 0)
    Reason += "\nInvalid Domain Suffix entered.\n(Valid: .com, .edu, .net, .org, .gov)";
  if (checkStr.length > 120)
    Reason += "\nPlease limit the Email Address to 120 characters.";

  if (RL != Reason.length)
  {
    alert(Reason);
    objField.focus();
    RC = false;
   }
  else
    RC = true;
  return(RC);
}

/****************************************************************/

// isEmail (FieldName [, BOOLEAN emptyOK])
// 
// Email address must be of form a@b.c ... in other words:
// * there must be at least one character before the @
// * there must be at least one character before and after the .
// * the characters @ and . are both required
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isEmail (FieldName)
{	var defaultEmptyOK = true;
	var s = FieldName.value;
	if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);

    // is s whitespace?
    if (isWhitespace(s)) 
	{	alert("Invalid Email: It can not be whitespace.");
		FieldName.select();
		return false;
	}
    
    // there must be >= 1 character before @, so we
    // start looking at character position 1 
    // (i.e. second character)
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@"))
	{	alert("You need to enter a valid email address.");
		FieldName.select()
		return false;
	}
    else i += 2;

    // look for .
    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

	// there must be no ; or ,
	// users entering 2 email addresses
	if ((s.indexOf(";") != -1) || (s.indexOf(",") != -1))
	{	alert("You need to enter only one valid email address.");
		FieldName.select();
		return false;
	}

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != "."))
	{	alert("You need to enter a valid email address.");
		FieldName.select();
		return false;
	}
    else return true;
}

//**********************************************************************
// same function as isEmail, only removes message lines, can be called 
// in other functions
function isEmailB (FieldName)
{	var defaultEmptyOK = true;
	var s = FieldName.value;
	if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);
   
    // is s whitespace?
    if (isWhitespace(s)) 
	{//	alert("Invalid Email: It can not be whitespace.")
	//	FieldName.foucs();
		return false;
	}
    
    // there must be >= 1 character before @, so we
    // start looking at character position 1 
    // (i.e. second character)
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@"))
	{//	alert("You need to enter a valid email address.")
	//	FieldName.foucs();
		return false;
	}
    else i += 2;

    // look for .
    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != "."))
	{//	alert("You need to enter a valid email address.")
	//	FieldName.foucs();
		return false;
	}
    else return true;
}

function isEmailC (FieldName)
{	var defaultEmptyOK = true;
	var s = FieldName.value;
	if (isEmpty(s)) 
       if (isEmailC.arguments.length == 1) return defaultEmptyOK;
       else return (isEmailC.arguments[1] == true);
   
    // is s whitespace?
    if (isWhitespace(s)) 
	{	alert("Invalid Email: It can not be whitespace.");
		FieldName.select();
		return false;
	}
    
    // there must be >= 1 character before @, so we
    // start looking at character position 1 
    // (i.e. second character)
    var i = 1;
    var sLength = s.length;

    // look for @
    while ((i < sLength) && (s.charAt(i) != "@"))
    { i++
    }

    if ((i >= sLength) || (s.charAt(i) != "@"))
	{	alert("You need to enter a valid email address.");
		FieldName.select()
		return false;
	}
    else i += 2;

    // look for .
    while ((i < sLength) && (s.charAt(i) != "."))
    { i++
    }

    // there must be at least one character after the .
    if ((i >= sLength - 1) || (s.charAt(i) != "."))
	{	alert("You need to enter a valid email address.");
		FieldName.select();
		return false;
	}

		//the first four characters cannot be "www."
	if (s.indexOf("www.") != -1) {
		alert ("\nWARNING: The email address you entered starts with 'www.'  Unlike web pages, email addresses typically do not start with 'www.' (e.g., bob@aol.com).  If your email is correct, disregard this message.")
		//FieldName.select();
		return false;
	}
	 else return true;

}

/****************************************************************/

// Checks to see if a required field is blank.  If it is, a warning
// message is displayed...

function ForceSelected(objField, FieldName)
{
	for (var i=0;i < objField.length;i++ )
	{
		if (objField[i].checked) {
			return true;
		}
	}

	alert("You need to select whether you want to pay for this relative or friend");
	return false;


}

/****************************************************************/

// Checks to see if a required field is blank.  If it is, a warning
// message is displayed...

function ForceEntry(objField, FieldName)
{
	var strField = new String(objField.value);
	if (isWhitespace(strField)) {
		alert("You need to enter information for " + FieldName);
		objField.focus();
		objField.select();
		return false;
	}

	return true;
}
		
/****************************************************************/

// Returns true if the string passed in is a valid number
//  (no alpha characters), else it displays an error message

function ForceNumber(objField, FieldName)
{
	var strField = new String(objField.value);
	var blsuccess= true;
	if (isWhitespace(strField)) {
		//alert('Please enter the capacity value.\n');	
		//objField.focus();
		blsuccess=true;
	}
	var i = 0;
	if (blsuccess){
		for (i = 0; i < strField.length; i++)
			if (strField.charAt(i) < '0' || strField.charAt(i) > '9') {
			
				objField.select();
				blsuccess = false;
			}
	}
		if (!blsuccess){
		alert(FieldName + " must be a valid numeric entry.  Please do not use commas or dollar signs or any non-numeric symbols.");
		objField.value="";
		objField.focus();
		}
	return blsuccess;
}

/****************************************************************/

// Returns true if the string passed in is a valid money
//  (no alpha characters except a decimal place), 
//   else it displays an error message
	
function ForceMoney(objField, FieldName)
{
	var strField = new String(objField.value);
	var blsuccess=true;
	
	if (isWhitespace(strField)) {
		alert('Please enter a cost value.\n');	
		objField.focus();
		blsuccess=false;
	}	
	if (blsuccess){
		var i = 0;
	
		for (i = 0; i < strField.length; i++)
			if ((strField.charAt(i) < '0' || strField.charAt(i) > '9') && (strField.charAt(i) != '.') && (strField.charAt(i) != '$')) {
				alert(FieldName + " must be a valid numeric entry.  Please do not use commas or dollar signs or any non-numeric symbols.");
				objField.value = "";
				objField.focus();
				return false;
			}
	}
	return blsuccess;
}


/****************************************************************/

// Right trims the string...  Useful for SQL datatypes of CHAR

function RTrim(strTrim)
{
	var str = new String(strTrim);
	var i = 0;
	var c = "";
	var endpos = 0

	for (i = str.length; i >= 0 && endpos == 0; i = i - 1) {
		c = str.charAt(i);
		if (whitespace.indexOf(c) == -1)
			endpos = i;
	}

	return str.substring(0,endpos+1);
}

/****************************************************************/

/* PURPOSE:  Returns true if the string is a valid date number.
	A method is passed in (1 = month, 2 = day).  If the string is
	nonnumeric, false is passed back.  If the day in the date string
	is greater than 31, false is returned.  If the month is greater
	than 12, an error is returned.
*/

function isDateNumber(strNum,method)
{
	var str = new String(strNum);
	var i = 0;

	if (isNaN(parseInt(str)) || parseInt(str) < 0) return false;

	if (method == 2)
		if (parseInt(str) > 31 || parseInt(str) < 1)
			return false;
	if (method == 1)
		if (parseInt(str) > 12 || parseInt(str)< 1)
			return false;

	for (i = 0; i < str.length; i++)
		if (str.charAt(i) < '0' || str.charAt(i) > '9')
			return false;


	return true;
}

/****************************************************************/

// Displays an alert box with the passed in string...

function PromptErrorMsg(Field,strError)
{
	alert("You have entered an invalid date for " + strError + ".  Please make sure your date format is in M/D/YY format.");
	Field.focus();
}

/****************************************************************/

/* PURPOSE: Checks to see if the string is a valid date.  A valid
	date is defined as any of the following:

		MM/DD/YY, MM/DD/YYYY, M/D/YY, M/D/YYYY,
		MM-DD-YY, MM-DD-YYYY, M-D-YY, M-D-YYYY
*/

function ForceDate(strDate,strField)
{
	var str = new String(strDate.value);

	if (isWhitespace(str)) {
		return true;
		// if the field is empty, just return true...
	}

	var i = 0, count = str.length, j = 0;
	while ((str.charAt(i) != "/" && str.charAt(i) != "-") && i < count)
		i++;

	if (i == count || i > 2) {
		PromptErrorMsg(strDate,strField);
		strDate.value = "";    //reset the date
		return false;
	}

	var addOne = false;
	if (i == 2) addOne = true;

	if (!isDateNumber(str.substring(0,i),1)) {
		PromptErrorMsg(strDate,strField);
		strDate.value = "";    //reset the date
		return false;
	}

	j = i+1;
	i = 0;

	while ((str.charAt(i+j) != "/" && str.charAt(j+i) != "-") && i+j < count)
		i++;

	if (i+j == count || i > 2) {
		PromptErrorMsg(strDate,strField);
		strDate.value = "";    //reset the date
		return false;
	}

	if (!isDateNumber(str.substring(j,i+j),2)) {
		PromptErrorMsg(strDate,strField);
		strDate.value = "";    //reset the date
		return false;
	}

	j = i+3;
	i = 0;

	if (addOne) j++;

	while (i+j < count)
		i++;


	if (i != 2 && i != 4) {
		PromptErrorMsg(strDate,strField);
		strDate.value = "";    //reset the date
		return false;
	}

	if (!isDateNumber(str.substring(j,i+j),3)) {
		PromptErrorMsg(strDate,strField);
		strDate.value = "";    //reset the date
		return false;
	}

	return true;
}


//Another Date Validation function

function isDateString(stringValue) {

		// this function is designed to mimic the "date" portion of the
		// VBScript IsDate() function, allowing dates to be validated
		// with JavaScript in browsers before you run into a problem
		// in ASP pages with date database columns or the VBScript
		// CDate() function; an exception is that string months
		// ("Jan," etc.) are not accepted
		
		// this function does not handle BC dates or dates past 12/31/9999
		
		// you obviously want to strip the comments from production scripts
		
		// create a String object
		var theString = new String(stringValue);
		//var theString = objField.value;
		// determine the delimiter character (must be "/" "-" or space)
		var delimiterCharacter
		if ( theString.indexOf('/') > 0 )
			delimiterCharacter = '/';
		else
			if ( theString.indexOf('-') > 0 )
				delimiterCharacter = '-';
			else
				if ( theString.indexOf(' ') > 0 )
					delimiterCharacter = ' ';
				else
					return false;
					
		// split the string into an array of tokens
		var theTokens = theString.split(delimiterCharacter);
		
		// there must be either two or three tokens
		if ( theTokens.length < 2 || theTokens.length > 3 )
			return false;
		
		// convert the tokens to String objects, which will be needed later,
		// stripping a single leading 0
		var tokenIndex;
		for ( tokenIndex = 0; tokenIndex < theTokens.length; tokenIndex++ ) {
			theTokens[tokenIndex] = new String(theTokens[tokenIndex])			
			if ( theTokens[tokenIndex].charAt(0) == '0' )
				theTokens[tokenIndex] = theTokens[tokenIndex].substring(1, theTokens[tokenIndex].length);
		}

		// all of the tokens must be positive integers
		for ( tokenIndex = 0; tokenIndex < theTokens.length; tokenIndex++ ) {
			if ( ! isNonnegativeInteger(theTokens[tokenIndex]) )
				return false;
		}
		
		// we need to identify the year, month, and day tokens
		var numericValue;
		var yearTokenIndex = -1;
		var monthTokenIndex = -1;
		var dayTokenIndex = -1;
		for ( tokenIndex = 0; tokenIndex < theTokens.length; tokenIndex++ ) {
					
			// convert the value
			numericValue = parseInt(theTokens[tokenIndex], 10);
					
			// could this token be a month?
			if ( numericValue <= 12 ) {
					
				// yes; do we already have a month?
				if ( monthTokenIndex == -1 ) {
						
					// no; assign this token to the month and continue
					monthTokenIndex = tokenIndex;
					continue;
				}
				else {
							
					// we already have a month; this token could
					// also be the day; do we already have a day?
					if ( dayTokenIndex == -1 ) {
						
						// no; assign this token to the day and continue
						dayTokenIndex = tokenIndex;
						continue;
					}
					else {
							
						// we already have a day; this token could
						// also be the year; do we alreay have a year?
						if ( yearTokenIndex == -1 ) {
						
							// no; assign this token to the year and continue
							dayTokenIndex = tokenIndex;
							continue;
						}
					}
				}
			}
			else {
						
				// the value is too large for a month;
				// could this token be a day?
				if ( numericValue <= 31 ) {
						
					// yes; do we already have a day?
					if ( dayTokenIndex == -1 ) {
						
						// no; assign this token to the day and continue
						dayTokenIndex = tokenIndex;
						continue;
					}
					else {
							
						// we already have a day; this token could
						// also be the year; do we alreay have a year?
						if ( yearTokenIndex == -1 ) {
						
							// no; assign this token to the year and continue
							dayTokenIndex = tokenIndex;
							continue;
						}
					}
				}
				else {
						
					// the value is too large for a day;
					// could this token be a year?
					if ( numericValue <= 9999 ) {
					
						// yes; do we already have a year?
						if ( yearTokenIndex == -1 ) {
						
							// no; assign this token to the year
							yearTokenIndex = tokenIndex;
						}
					}
				}
			}
		}	// end of for loop
		
		// evaluate, based on the number of tokens
		if ( theTokens.length == 2 ) {
			
			// two tokens can be either a month/year combination or a month/day
			// combination with the current year assumed; either way, we must have
			// a month
			if ( monthTokenIndex == -1 )
				
				// no month
				return false;
				
			// do we have a year?
			if ( ! (yearTokenIndex == -1) ) {
			
				// yes; month/year combination; must be okay
				return true;
			}
			else
				
				// no year; do we have a day?
				if ( ! (dayTokenIndex == -1) ) {
				
					// yes; month/day combination; get the current year
					var today = new Date();
					var currentYear = today.getYear();

					// make sure it's a valid date (we were testing days using
					// 31, and that might be too many for the month)
					return isDate(currentYear, theTokens[monthTokenIndex], theTokens[dayTokenIndex]);
				}
				else
				
					// we have neither a year nor a day
					return false;
		}
		else {
			
			// three tokens; we should have found tokens for year, month, and day
			if ( yearTokenIndex == -1 || monthTokenIndex == -1 || dayTokenIndex == -1 )
				
				// missing one or more
				return false;
			else
				
				// found all; however, VBScript can only handle the following sequences
				if ( monthTokenIndex == 0 ) {
					
					// must be m/d/y
					if ( dayTokenIndex != 1 || yearTokenIndex != 2)
						return false;
				}
				else
					if ( dayTokenIndex == 0 ) {
				
						// must be d/m/y
						if ( monthTokenIndex != 1 || yearTokenIndex != 2)
							return false;
					}
					else
						if ( yearTokenIndex == 0 ) {
				
							// must be y/m/d
							if ( monthTokenIndex != 1 || dayTokenIndex != 2)
								return false;
						}
						else
						
							// something is wrong
							return false;
				
				// make sure it's a valid date (we were testing days using a value
				// of 31, and that might be too many for the actual month)
				return isDate(theTokens[yearTokenIndex], theTokens[monthTokenIndex], theTokens[dayTokenIndex]);
		}
	}

	function isTimeString(stringValue) {

		// this function is designed to mimic the "time" portion of the
		// VBScript IsDate() function, allowing times to be validated
		// with JavaScript in browsers before you run into a problem
		// in ASP pages with date database columns or the VBScript
		// CDate() function
		
		// you obviously want to strip the comments from production scripts
		// and place this function in the library file

		// create a String object
		var theString = new String(stringValue);
		
		// the string must have either two (hours and minutes) or three
		// (hours, minutes and seconds) tokens, delimited by ":";
		// split the string into an array of tokens
		var theTokens = theString.split(':');
		if ( theTokens.length < 2 || theTokens.length > 3 )
			return false;
		
		// convert the tokens to String objects, which will be needed later,
		// stripping whitespace
		var firstToken = new String(theTokens[0])
		firstToken = trim(firstToken);
		var middleToken;
		if ( theTokens.length == 3 ) {
			middleToken = new String(theTokens[1])
			middleToken = trim(middleToken);
		}
		var lastToken = new String(theTokens[theTokens.length - 1])
		lastToken = trim(lastToken);

		// the first token (hours) must be an integer between 0 and 23
		if ( ! isInteger(firstToken) )
			return false;
		if ( ! isIntegerInRange(firstToken, 0, 23) )
			return false;
		
		// are there three tokens?
		if ( theTokens.length == 3 ){
		
			// the middle token (minutes) must be an integer between 0 and 59
			if ( ! isInteger(middleToken) )
				return false;
			if ( ! isIntegerInRange(middleToken, 0, 59) )
				return false;
		}
			
		// the first one or two characters of the last token (either minutes
		// and optional am/pm indicator or seconds and am/pm indicator) must
		// be digits
		if ( ! isDigit(lastToken.charAt(0)) )
			return false;
		
		// the first character is a digit; split the last token into the minutes
		// or seconds value and the indicator; depending on the second character
		var lastValue;
		var ampmIndicator;
		if ( isDigit(lastToken.charAt(1)) ) {
			lastValue = new String(lastToken.substring(0, 2));
			if ( lastToken.length >= 3 )
				ampmIndicator = new String(trim(lastToken.substring(2, lastToken.length)));
			else
				ampmIndicator = new String();
		}
		else {
			lastValue = new String(lastToken.substring(0, 1));
			if ( lastToken.length >= 2 )
				ampmIndicator = new String(trim(lastToken.substring(1, lastToken.length)));
			else
				ampmIndicator = new String();
		}
		ampmIndicator = ampmIndicator.toUpperCase();
		
		// the last value must be between 0 and 59
		if ( ! isIntegerInRange(lastValue, 0, 59) )
			return false;
		
		// check the am/pm indicator, if there is one
		if ( ampmIndicator.length > 0 )
			if ( ! ( ampmIndicator == "AM" || ampmIndicator == "PM" ) )
				return false;
				
		// valid time
		return true;
	}

	// most of the following was derived from Netscape's FormChek.js
	// library, which should be reviewed for documentation and comments

	var daysInMonth = makeArray(12);
	daysInMonth[1] = 31;
	daysInMonth[2] = 29;
	daysInMonth[3] = 31;
	daysInMonth[4] = 30;
	daysInMonth[5] = 31;
	daysInMonth[6] = 30;
	daysInMonth[7] = 31;
	daysInMonth[8] = 31;
	daysInMonth[9] = 30;
	daysInMonth[10] = 31;
	daysInMonth[11] = 30;
	daysInMonth[12] = 31;

	var whitespace = " \t\n\r";

	function charInString(c, s) {
		for (i = 0; i < s.length; i++) {
			if (s.charAt(i) == c)
				return true;
	    }
	    return false
	}

	function daysInFebruary(year) {
	    return ( ((year % 4 == 0) && ((!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 );
	}

	function isDate(year, month, day) {
	    if ( ! ( isYear(year) && isMonth(month) && isDay(day) ) ) return false;
	    var intYear = parseInt(year);
	    var intMonth = parseInt(month);
		var intDay = parseInt(day);
	    if ( intDay > daysInMonth[intMonth] ) return false; 
	    if ( ( intMonth == 2 ) && ( intDay > daysInFebruary(intYear) ) ) return false;
	    return true;
	}

	function isDay(s) {
	    return isIntegerInRange(s, 1, 31);
	}

	function isDigit(c) {
		return ( ( c >= "0" ) && ( c <= "9" ) )
	}

	function isInteger(s) {
		var i;
	    for ( i = 0; i < s.length; i++ )
	    {   
	        var c = s.charAt(i);
	        if ( ! isDigit(c) ) return false;
	    }
	    return true;
	}

	function isIntegerInRange(s, a, b) {
	    if ( ! isInteger(s) ) return false;
	    var num = parseInt (s);
	    return ( ( num >= a ) && ( num <= b ) );
	}

	function isMonth(s) {
	    return isIntegerInRange (s, 1, 12);
	}

	function isNonnegativeInteger(s) {
	    return ( isSignedInteger(s) && ( parseInt(s) >= 0 ) );
	}

	function isSignedInteger(s) {
	    var startPos = 0;
	    if ( ( s.charAt(0) == "-" ) || ( s.charAt(0) == "+" ) )
	       startPos = 1;    
	    return ( isInteger(s.substring(startPos, s.length)) )
	}

	function isYear(s) {
		if ( ! isNonnegativeInteger(s) ) return false;
	    return ( (s.length == 2) || (s.length == 4) );
	}

	function lTrim(s) {
		var i = 0;
	    while ( (i < s.length) && charInString(s.charAt(i), whitespace) )
	       i++;
	    return s.substring(i, s.length);
	}

	function makeArray(n) {
	   for ( var i = 1; i <= n; i++ ) {
	      this[i] = 0
	   } 
	   return this
	}

	function rTrim(s) {
		var i = 0;
	    while ( (i < s.length) && charInString(s.charAt(i), whitespace) )
	       i++;
	    return s.substring(i, s.length);
	}

	function trim(s) {
		return lTrim(rTrim(s));
	}
	
// actual call to the validation function 
	function validateDate(objField,strField) {

		// get the value
		var stringValue = objField.value;
		
		if (isDateString(stringValue))
		{
		return true;
		} else{
			alert("You have entered an invalid date for " + strField + ".  Please make sure your date format is in MM/DD/YY format.");
			objField.focus();
			return false;
			}
	}

	function validateTime(objField,strField) {

		// get the value
		var stringValue = objField.value;
		
		if (isTimeString(stringValue))
		{
		return true;
		} else{
			alert("You have entered an invalid time for " + strField + ".");
			objField.focus();
			return false;
			}
	}



/****************************************************************/

// This function determines if the string passed in is a valid
// US zip code.  It accepts either ##### or #####-####.  If the
// string is valid, it returns true, else false.

function isZipcode(strZip)
{
	var s = new String(strZip);

	if (s.length != 5 && s.length != 10)
		// inappropriate length
		return false;


	for (var i=0; i < s.length; i++)
		if ((s.charAt(i) < '0' || s.charAt(s) > '9') && s.charAt(i) != '-')
			return false;

	return true;
}

//JavaScript Metropolitan Zip Code Validation Script
//It accepts ##### or #####-#### or #####-####-##. If the string is valid, it 
//returns true, otherwise false
//validageZip (objField AS TEXT INPUT NAME)

function validateZip(objField)	{
	var s = objField.value;
	
	if (s != "")
		{
		//XXXXX
		if (s.length==5)
			{
			if (isNaN(s))
				{
				alert("The \"Mailing Zip Code\" must be numeric");
				objField.select();
				return false;
				}
			}
		//XXXXX-XXXX
		else if (s.length==10)
			{
			var m_zipTokens2 = s.split("-");
				
			if (m_zipTokens2.length==2 && m_zipTokens2[0].length==5 && m_zipTokens2[1].length==4)
				{
				if (isNaN(m_zipTokens2[0]) || isNaN(m_zipTokens2[1]))
					{
					alert("The \"Mailing Zip Code\" must be in the proper format.\n (Ex. 33486-0000 or 33486-0000-00)");
					objField.select();
					return false;
					}
				}
			}
		//XXXXX-XXXX-XX
		else if (s.length==13)
			{
			var m_zipTokens3 = s.split("-");

			if (m_zipTokens3.length==3 && m_zipTokens3[0].length==5 && m_zipTokens3[1].length==4 && m_zipTokens3[2].length==2)
				{
					
				if (isNaN(m_zipTokens3[0]) || isNaN(m_zipTokens3[1]) || isNaN(m_zipTokens3[2]))
					{
					alert("The \"Mailing Zip Code\" must be in the proper format.\n (Ex. 33486-0000 or 33486-0000-00)");
					objField.select();
					return false;
					}
				}
			else
				{
				alert("The \"Mailing Zip Code\" must be in the proper format.\n (Ex. 33486-0000 or 33486-0000-00)");
				objField.select();
				return false;
				}
			}
		else
			{
			alert("The \"Mailing Zip Code\" must be in the proper format.\n (Ex. 33486-0000 or 33486-0000-00)");
			objField.select();
			return false;
			}
		}
		if (s!="")
			{
			//alert("The Zip Code you entered is in the correct format!");
			return true;
			}
}

/****************************************************************/

// This function ensures that a field is less than or equal to the
// Length passed in.  You must call this function with the element
// name in your form (for example: "ForceLength(document.forms[0].txtElement)"
// as opposed to "ForceLength(document.forms[0].txtElement.value)"
// If the field's value is too large, an error message is displayed
// and false is returned, else true is returned.

function ForceLength(objField, nLength, strWarning)
{
	var strField = new String(objField.value);

	if (strField.length > nLength) {
		alert(strWarning);
		return false;
	} else
		return true;
}


/*
There are three functions in this set for credit card validation.
The main function is:

validateCard(cardNumber,cardType,cardMonth,cardYear)
	parameters:
		all paramaters are string values.
		Month & Year come from the select input fields in the form, so they are defined.
		cardType can be:
			'a' for American Express
			'd' for Discover
			'm' for MasterCard
			'v' for Visa
	description:
		This function will check string length, valid characters, specific credit card prefixes and test
		the Mod 10 (LUHN Formula) for validating possible credit card numbers.  This function can only
		authorize that the given card data is potentially valid.  You would still need to run actual
		card validation routines to verify the actual account.
	returns:
		this function returns true if the card number could be valid for the card type and expiration date.
		false otherwise.	

supporting functions:

mod10( cardNumber )
	parameters:
		this function takes the text string card number and runs the Mod 10 formula on its respective digits.
	description:
		Mod 10 is the check digit formula for the supported cards these functions attempt to validate.
	returns:
		this function returns true if the number passes the check digit test.
		false otherwise.

expired( cardMonth, cardYear )
	parameters:
		this function takes the text string values given by the html form.
	description:
		this function basically will check to make sure todays date is less than the expiration date the user inputs.
		this function is not locked into using 2 digit dates.
	returns:
		this fucntion returns true if the card is expired.
		false otherwise.

*/

function mod10( cardNumber ) { // LUHN Formula for validation of credit card numbers.
	var ar = new Array( cardNumber.length );
	var i = 0,sum = 0;
	for( i = 0; i < cardNumber.length; ++i ) {
		ar[i] = parseInt(cardNumber.charAt(i));
	}
	for( i = ar.length -2; i >= 0; i-=2 ) {  // you have to start from the right, and work back.
		ar[i] *= 2;							 // every second digit starting with the right most (check digit)
		if( ar[i] > 9 ) ar[i]-=9;			 // will be doubled, and summed with the skipped digits.
	}										 // if the double digit is > 9, add those individual digits together 
	for( i = 0; i < ar.length; ++i ) {
		sum += ar[i];						 // if the sum is divisible by 10 mod10 succeeds
	}
	return (((sum%10)==0)?true:false);	  	
}

function expired( month, year ) {
	var now = new Date();							// this function is designed to be Y2K compliant.
	var expiresIn = new Date(year,month,0,0,0);		// create an expired on date object with valid thru expiration date
	expiresIn.setMonth(expiresIn.getMonth()+1);		// adjust the month, to first day, hour, minute & second of expired month
	if( now.getTime() < expiresIn.getTime() ) return false;
	return true;									// then we get the miliseconds, and do a long integer comparison
}

function validateCard(cardNumber,cardType,cardMonth,cardYear) {
	if( cardNumber.length == 0 ) {						//most of these checks are self explanitory
		alert("Please enter a valid card number.");
		return false;				
	}
	for( var i = 0; i < cardNumber.length; ++i ) {		// make sure the number is all digits.. (by design)
		var c = cardNumber.charAt(i);
		if( c < '0' || c > '9' ) {
			alert("Please enter a valid card number.  Use only digits.  Do not use spaces or hyphens.");
			return false;
		}
	}
	var length = cardNumber.length;			//perform card specific length and prefix tests
	switch( cardType ) {
		case 'a':
			if( length != 15 ) {
				alert("Please enter a valid American Express Card number.");
				return;
			}
			var prefix = parseInt( cardNumber.substring(0,2));
			if( prefix != 34 && prefix != 37 ) {
				alert("Please enter a valid American Express Card number.");
				return;
			}
			break;
		case 'd':
			if( length != 16 ) {
				alert("Please enter a valid Discover Card number.");
				return;
			}
			var prefix = parseInt( cardNumber.substring(0,4));
			if( prefix != 6011 ) {
				alert("Please enter a valid Discover Card number.");
				return;
			}
			break;
		case 'm':
			if( length != 16 ) {
				alert("Please enter a valid MasterCard number.");
				return;
			}
			var prefix = parseInt( cardNumber.substring(0,2));
			if( prefix < 51 || prefix > 55) {
				alert("Please enter a valid MasterCard Card number.");
				return;
			}
			break;
		case 'v':
			if( length != 16 && length != 13 ) {
				alert("Please enter a valid Visa Card number.");
				return;
			}
			var prefix = parseInt( cardNumber.substring(0,1));
			if( prefix != 4 ) {
				alert("Please enter a valid Visa Card number.");
				return;
			}
			break;
	}
	if( !mod10( cardNumber ) ) {                             		// run the check digit algorithm
		alert("Sorry!  This is not a valid credit card number.");
		return false;
	}
	if( expired( cardMonth, cardYear ) ) {							// check if entered date is already expired.
		alert("Sorry!  The expiration date you have entered would make this card invalid.");
		return false;
	}
	
	return true; // at this point card has not been proven to be invalid
}


// isAlphanumeric (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is English letters 
// (A .. Z, a..z) and numbers only.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
//
// NOTE: Need i18n version to support European characters.
// This could be tricky due to different character
// sets and orderings for various languages and platforms.


// Returns true if character c is an English letter 
// (A .. Z, a..z).
//
// NOTE: Need i18n version to support European characters.
// This could be tricky due to different character
// sets and orderings for various languages and platforms.

function isLetter (c)
{   return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) )
}



function isAlphanumeric (s)

{   
// VARIABLE DECLARATIONS

var digits = "0123456789";

var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"

var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"


// whitespace characters
var whitespace = " \t\n\r";

	var i;

    if (isEmpty(s)) 
       if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphanumeric.arguments[1] == true);

    // Search through string's characters one by one
    // until we find a non-alphanumeric character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number or letter.
        var c = s.charAt(i);

        if (! (isLetter(c) || isDigit(c) || c=="-" || c=="_") )
        return false;
    }

    // All characters are numbers or letters.
    return true;
}

