/******************************************************************************/
// This file contains the following validation wrapper functions
// 			initValidation()
// 			warnUser()
//
// This file contains the following validation functions
//			isEmail(field, type)
//			isUSZipCode(field, type)
//			isUSPhone(field, type)
//			isUSState(field, type)
//			isUSStateDD(field, type)
//			isText(field, type)
//			isConfirmedPassword(field, field)
//			isValid_RB(frm, btnName)
//			isValid_DD(field, type)
//
// This file contains the following PRIVATE helper functions
// 			isBlank(str)
//			validatePattern(pattern, msg1, msg2, field, type)
//
// This file also contains the following utility JavaScript functions
//			ltrim(str)
//			rtrim(str)
//			trim(str)
// 			stripCharsInBag(str, bag)
// 			stripCharsNotInBag(str, bag)
// 			stripWhitespace(str)

/******************************************************************************/
// Global Variable Declarations
var errmsg;
var focusset;

var WHITESPACE = " \t\n\r";

/******************************************************************************/
// This function initializes the global variables to set up for validation.
function initValidation()
{
	errmsg = '';
	focusset = false;
}

/******************************************************************************/
// This function displays a warning if any of the validation routines failed to
// validate.
function warnUser()
{
	// If there was an error alert the user.
	if (errmsg)
		alert('The following error(s) occurred:\n'+errmsg);
		
	// If the error msg is blank return true to submit the form.
	return (errmsg == '');
}

function isEmail(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Ensures that a string contains a valid email address.  If a bad value is
//		found it will attach a message to the global error string. 
//
// VALID PATTERNS: 
//		xxx@yyy.zzz
//		- the characters "@" and "." are both required.
// 		- there must be at least one character before the "@"
// 		- there must be at least one character before and after the "."
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
//
// NOTE:
//		This only validates that the email address is in the correct form.  It
//		does not validate existance of the domain.
{
	// Declare the email regular expression.
	var pattern=/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9])+$/;
	
	// Declare the messages
	var msg1=' - An email address is required.\n';
	var msg2=' - The email address entered is invalid.\n';
	
	// Trim any extraneous whitespace
	field.value = trim(field.value);

	// Validate the pattern
	validatePattern(pattern, msg1, msg2, field, type);	
}

function isUSZipCode(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Ensures that a string contains a valid US zip code.  If a bad value is
//		found it will attach a message to the global error string. 
//
// VALID PATTERNS: 
//		99999 or 99999-9999
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
{
	
	// Declare the zip code regular expression.
	var pattern=/(^\d{5}$)|(^\d{5}-\d{4}$)/;

	// Declare the messages
	var msg1=' - A zip code is required.\n';
	var msg2=' - The zip code must be in the form "99999 or 99999-9999".\n';
	
	// Trim any extraneous whitespace
	field.value = trim(field.value);

	// Validate the pattern
	validatePattern(pattern, msg1, msg2, field, type);	
}

function isUSPhone(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Validates that a string contains valid US phone pattern.  If a bad string
//		is found it will attach a message to the global error string. 
//
// VALID PATTERNS: 
//		Any pattern containing 10 digits
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
{

	// Declare the phone regular expression.
	var pattern=/^\(?(\d{3})\)?[\.\-\/ ]?(\d{3})[\.\-\/ ]?(\d{4})$/	

	// Declare the messages
	var msg1=' - A phone number is required.\n';
	var msg2=' - The phone number must have ten digits.\n';

	// Remove any extraneous whitespace
  field.value = stripCharsNotInBag (field.value, "1234567890")
	
	// If the string is optional and it is blank then exit quietly. 
	if((type == 'opt') && (isBlank(field.value))){return;}

	// If the string is required and it is blank flag an error and exit.
	if((type == 'req') && (isBlank(field.value))) 
	{
		errmsg += msg1; 
		if(!focusset){field.focus(); focusset = true;}
		return;
	}

	// Test the string against the regular expression
	// .exec will return NULL if no pattern matches
	valPh = pattern.exec(field.value)

	if (valPh) 
 	{
		// If the phone number is valid reformat it.
		field.value = "(" + valPh[1] + ") " + valPh[2] + "-" + valPh[3]
	}
	else 
 	{
		// Otherwise, if the string does not match the pattern flag an error.
		if (!(pattern.test(field.value)))
		{
			errmsg += msg2; 
			if(!focusset){field.focus(); focusset = true;}
		}
	}
}

function isUSState_DD(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Ensures that a drop down list contains a valid state abbreviation.  If a  
//		bad value is found it will attach a message to the global error string. 
//
// VALID PATTERNS:
//    All fifty states plus Washington D.C.  See NOTES below. 
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
//
// NOTES:
//	The drop down list must be populated with the values shown below.  Other is
//  used as the default value if no state is chosen to allow an error check to 
//	occur.
//							|AK|AL|AR|AZ|CA|CO|CT|DC|DE|FL|
//							|GA|HI|IA|ID|IL|IN|KS|KY|LA|MA|
//							|MD|ME|MI|MN|MO|MS|MT|NB|NC|ND|
//							|NH|NJ|NM|NV|NY|OH|OK|OR|PA|RI|
//							|SC|SD|TN|TX|UT|VA|VT|WA|WI|WV|
//							|WY|Other|
{	
	// Declare the message.
	var msg1=' - A state is required.\n';
	
	// Get the value of the selected drop down list item
	var val = field.options[field.selectedIndex].value;

	// If the string is optional then exit quietly. 
	if(type == 'opt'){return;}

	// If the string is required and it is blank flag an error and exit.
	if((type == 'req') && (val == 'Other')) 
	{
		errmsg += msg1; 
		if(!focusset){field.focus(); focusset = true;}
		return;
	}	
}

function isText(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Validates that a string contains some text.  If a bad string is
//		found it will attach a message to the global error string.
//
// VALID PATTERNS: 
//		Any text.
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
//
{
	// Trim any extraneous whitespace
	field.value = trim(field.value);

	// If the string is optional and it is blank then exit quietly. 
	if((type == 'opt') && (isBlank(field.value))){return;}

	// If the string is required and it is blank flag an error and exit.
	if((type == 'req') && (isBlank(field.value))) 
	{
		errmsg += ' - The ' + field.id + ' is required.\n'; 
		if(!focusset){field.focus(); focusset = true;}
		return;
	}	
}

function isInteger(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Ensures that a string contains a valid US zip code.  If a bad value is
//		found it will attach a message to the global error string. 
//
// VALID PATTERNS: 
//		99999 or 99999-9999
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
{
	
	// Declare the zip code regular expression.
	var pattern=/[0-9]*/;

	// Declare the messages
	var msg1=' - A ' + field.id + ' is required.\n';
	var msg2=' - The ' + field.id + ' must be in the form "99999 or 99999-9999".\n';
	
	// Trim any extraneous whitespace
	field.value = trim(field.value);

	// Validate the pattern
	validatePattern(pattern, msg1, msg2, field, type);	
}

function isConfirmedPassword(field1, field2)
/******************************************************************************/
// DESCRIPTION: 
//		Validates that a string contains some text.  If a bad string is
//		found it will attach a message to the global error string.
//
// VALID PATTERNS: 
//		anything
//  
// PARAMETERS:
//		field1 - The first password field.
//		field2 - The second password field.
//   
// RETURNS:
//		Nothing.
//
{
	// Trim any extraneous whitespace
	field1.value = trim(field1.value);
	field2.value = trim(field2.value);

	// If either of the strings is blank flag an error and exit.
	if((isBlank(field1.value)) || (isBlank(field2.value)))
	{
		errmsg += ' - The password fields cannot be blank.\n'; 
		if(!focusset){field1.focus(); focusset = true;}
		return;
	}

	// If password fields are not identical flag an error and exit.
	if(field1.value != field2.value)
	{
		errmsg += ' - The password fields must be identical.\n'; 
		if(!focusset){field1.focus(); focusset = true;}
		return;
	}	
}

function isValid_RB(frm, btnName)
/******************************************************************************/
// DESCRIPTION: 
//		Validates that a radio button has been checked.  If none oare checked
//		it will attach a message to the global error string.
//
// VALID PATTERNS: 
//		anything
//  
// PARAMETERS:
//		frm - The radiobutton object.
//		btnName - The button name.
//   
// RETURNS:
//		Nothing.
//
{
	var btn = frm[btnName];
	var valid;
	
	if(!btn.length)
	{
		valid = btn.checked	
	}
	else
	{
		for (var i=0; i<btn.length; i++)
		{
			valid = btn[i].checked
			if (valid) {break}
		}
	}
	if(!valid)
	{
		errmsg += ' - You must select one of the radio buttons.\n'; 
		if(!focusset){focusset = true;}
	}
}

function isValid_DD(field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Ensures that a drop down list contains a valid value.  If a  
//		bad value is found it will attach a message to the global error string. 
//
// VALID PATTERNS:
//    All fifty states plus Washington D.C.  See NOTES below. 
//  
// PARAMETERS:
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
//
// NOTES:
//	The drop down list must be populated with a blank option that has a value
// 	of "None".  None is used as the default value if no value is chosen to 
//	allow an error check to occur.  See example HTML below
//
//			<select name="order_type" class="txtMini" id="order_type">
//			<option value="None"></option>
//			<option value="Cash">Cash</option>
//			</select>
//
{	
	// Declare the message.
	var msg1=' - A value must be entered in the dropdown.\n';
	
	// Get the value of the selected drop down list item
	var val = field.options[field.selectedIndex].value;

	// If the string is optional then exit quietly. 
	if(type == 'opt'){return;}

	// If the string is required and it is blank flag an error and exit.
	if((type == 'req') && (val == 'None')) 
	{
		errmsg += msg1; 
		if(!focusset){field.focus(); focusset = true;}
		return;
	}	
}

/////////////////////////////////////
//  FUNCTIONS THAT I ADDED...
//  TO BE COMPLETED AFTER
//  ADD COMMENTS
//  MAKE MY OWN
/////////////////////////////////////

function isValidExpDate(expDate)
{
	// Declare the zip code regular expression.
	var pattern = /^(0[1-9]|1[012])\/\d\d$/;

	// Declare the messages
	var msg1 = ' - An Expiration Date is required.\n';
	var msg2 = ' - Please enter a valid expiration date for your credit card in the form of MM/YY.\n';
	
	// Declare the type
	var type = 'req';
	
	// Trim any extraneous whitespace
	expDate.value = trim(expDate.value);
		 
	// Validate the pattern
	validatePattern(pattern, msg1, msg2, expDate, type);
}

function isValidCreditCardNumber(ccNum, ccType)
{
	var msg1 = ' - A credit card number is required.\n';
	var msg2 = ' - You did not enter a valid credit card number.\n';
	var result = true;
	if (result && (ccNum.length>0))
 	{ 
 		if (!inValidCharSet(ccNum))
		{
 			errmsg += msg2;
			result = false;
		}
	
		if (result)
 			if (!LuhnCheck(ccNum) || !validateCCNum(ccType,ccNum))
			{
  				errmsg += msg2;
				result = false;
			}
	}
	else
	{
		errmsg += msg1;
		result = false;
	}
	
	return result;
}

function allDigits(str)
{
	return inValidCharSet(str,"0123456789");
}

function inValidCharSet(str)
{
	var charset = "0123456789";
	var result = true;
	
	for (var i=0;i<str.length;i++)
		if (charset.indexOf(str.substr(i,1))<0)
		{
			result = false;
			break;
		}
	
	return result;
}

function LuhnCheck(str) 
{
  var result = true;

  var sum = 0; 
  var mul = 1; 
  var strLen = str.length;
  
  for (i = 0; i < strLen; i++) 
  {
    var digit = str.substring(strLen-i-1,strLen-i);
    var tproduct = parseInt(digit ,10)*mul;
    if (tproduct >= 10)
      sum += (tproduct % 10) + 1;
    else
      sum += tproduct;
    if (mul == 1)
      mul++;
    else
      mul--;
  }
  if ((sum % 10) != 0)
    result = false;
        
  return result;
}

function validateCCNum(cardType,cardNum)
{
	var result = false;
	cardType = cardType.toUpperCase();
		
	var cardLen = cardNum.length;
	var firstdig = cardNum.substring(0,1);
	var seconddig = cardNum.substring(1,2);
	var first4digs = cardNum.substring(0,4);

	switch (cardType)
	{
		case "VISA":
			result = ((cardLen == 16) || (cardLen == 13)) && (firstdig == "4");
			break;
		case "AMEX":
			var validNums = "47";
			result = (cardLen == 15) && (firstdig == "3") && (validNums.indexOf(seconddig)>=0);
			break;
		case "MASTERCARD":
			var validNums = "12345";
			result = (cardLen == 16) && (firstdig == "5") && (validNums.indexOf(seconddig)>=0);
			break;
		case "DISCOVER":
			result = (cardLen == 16) && (first4digs == "6011");
			break;
		case "DINERS":
			var validNums = "068";
			result = (cardLen == 14) && (firstdig == "3") && (validNums.indexOf(seconddig)>=0);
			break;
	}
	
	return result;
}


/******************************************************************************/
/******************************************************************************/
// PRIVATE FUNCTIONS: 
// PRIVATE FUNCTIONS: 
/******************************************************************************/
/******************************************************************************/
/******************************************************************************/

function isBlank(str)
/******************************************************************************/
// DESCRIPTION: 
//		Determines if the string passed in is blank. 
//
// PARAMETERS:
//		str - The string to be checked.
//   
// RETURNS:
//		true if the string is blank, false otherwise.
{
	for(var i=0;i<str.length;i++)
	{
		var c = str.charAt(i);
		if((c !=	' ') && (c != '\n') && (c != '\t')) return false;
	}
	return true;
}

function validatePattern(pattern, msg1, msg2, field, type)
/******************************************************************************/
// DESCRIPTION: 
//		Validates that a value matches a valid pattern.  If a bad value is found
//		it will attach a message to the global error string. 
//
// VALID PATTERNS: 
//		See parameters.
//  
// PARAMETERS:
//		pattern - The pattern to validate against.
//		msg1 - Message to add to global error if the field is blank & required.
//		msg2 - Message to add to global error if value is invalid.
//		field - The form field containing the value to be validated.
//		type - A flag indicating if the field is required or optional.
//   
// RETURNS:
//		Nothing.
{
	
	// Trim any extraneous whitespace
	field.value = trim(field.value);

	// If the string is optional and it is blank then exit quietly. 
	if((type == 'opt') && (isBlank(field.value))){return;}

	// If the string is required and it is blank flag an error and exit.
	if((type == 'req') && (isBlank(field.value))) 
	{
		errmsg += msg1; 
		if(!focusset){field.focus(); focusset = true;}
		return;
	}
	
	// Otherwise, if the string does not match the pattern flag an error.
	if (!(pattern.test(field.value)))
	{
		errmsg += msg2; 
		if(!focusset){field.focus(); focusset = true;}
	}
}

/******************************************************************************/
/******************************************************************************/
// UTILITY FUNCTIONS: 
// UTILITY FUNCTIONS: 
/******************************************************************************/
/******************************************************************************/

function ltrim(str)
/******************************************************************************/
// DESCRIPTION: 
//		Removes any leading whitspace.
//
// PARAMETERS:
//		str - The string to remove the whitespace from.
//   
// RETURNS:
//		String.
{
	return str.replace( /^\s*/, "" )
}

function rtrim(str)
/******************************************************************************/
// DESCRIPTION: 
//		Removes any trailing whitspace.
//
// PARAMETERS:
//		str - The string to remove the whitespace from.
//   
// RETURNS:
//		String.
{
	return str.replace( /\s*$/, "" );
}

function trim(str)
/******************************************************************************/
// DESCRIPTION: 
//		Removes any leading and trailing whitspace.
//
// PARAMETERS:
//		str - The string to remove the whitespace from.
//   
// RETURNS:
//		String.
{
	return rtrim(ltrim(str));
}

function stripCharsInBag (str, bag)
/******************************************************************************/
// DESCRIPTION: 
//		Removes all characters which appear in string bag from string s.
//
// PARAMETERS:
//		str - The string to remove the chars from.
//		bag - The invalid chars for the string.
//   
// RETURNS:
//		String.
{   
	var i;
	var returnString = "";
	
	// Search through string's characters one by one. If character is not in bag, append to returnString.
	for (i = 0; i < str.length; i++)
	{   
		// Check that current character isn't whitespace.
		var c = str.charAt(i);
		if (bag.indexOf(c) == -1) returnString += c;
	}
	return returnString;
}

function stripCharsNotInBag (str, bag)
/******************************************************************************/
// DESCRIPTION: 
//		Removes all characters which do NOT appear in string bag from string s.
//
// PARAMETERS:
//		str - The string to remove the chars from.
//		bag - The valid chars for the string.
//   
// RETURNS:
//		String.
{   
	var i;
  var returnString = "";

  // Search through string's characters one by one. If character is in bag, append to returnString.
  for (i = 0; i < str.length; i++)
  {   
		// Check that current character isn't whitespace.
		var c = str.charAt(i);
		if (bag.indexOf(c) != -1) returnString += c;
  }
  return returnString;
}

function stripWhitespace (str)
/******************************************************************************/
// DESCRIPTION: 
// Removes all whitespace characters from s.  Global variable WHITESPACE defines
// the whitespace characters.
//
// PARAMETERS:
//		str - The string from ehich to remove the whitespace.
//   
// RETURNS:
//		String.
{   
	return stripCharsInBag (str, WHITESPACE)
}





