///////////////////////////////////////
// Form Validation javascript
//
// Javascript for validating form data before submitting
// Cobbled together by Kai Mantsch
//


/////////////////////////////////////
// passwords_match()
//
// Verifies that user has entered their password and retyped it the same way

function validate_passwords_match(password, retype_password, alert_text) {

	if ( password.value != retype_password.value ) {
		// What the... hey, they don't match!
		password.style.background = 'Yellow';
		retype_password.style.background = 'Yellow';
		alert( alert_text );
		password.focus();
		retype_password.focus();
		return(false);
	} else {
		// The passwords they entered match
		password.style.background = 'White';
		retype_password.style.background = 'White';
		return(true);
	}

} // end function passwords_match()


/////////////////////////////////////
// ValidateEmail()
//
// Verifies that user has entered basically valid email address

function validate_email(Field, AlertText) {

	with (Field) {

		AtPosition = value.indexOf("@");
		DotPosition = value.lastIndexOf(".");

		if (
			value == "" ||
			AtPosition < 1 || 
			(DotPosition - AtPosition) < 2
		) {
			// What the... hey, that's not a valid email!
	        style.background = 'Yellow';
			alert( AlertText );
	        focus();
			return(false);
		} else {
			// The email address looks ok
	        style.background = 'White';
			return(true);
		}
	}
} // end function ValidateEmail()


/////////////////////////////////////
// ValidatePhone()
//
// Verifies that user has entered basically valid Phone number

function validate_phone(Field, AlertText) {

	with (Field) {

		//strip out acceptable non-numeric characters
		var Stripped = value.replace(/[\(\)\.\-\ ]/g, '');

		if (
			isNaN(parseInt(Stripped)) ||
			Stripped.length != 10
		) {
			// What the... hey, that's not a valid Phone number!
	        style.background = 'Yellow';
			alert( AlertText );
	        focus();
			return(false);
		} else {
			// The Phone number looks ok
	        style.background = 'White';
			return(true);
		}
	}
} // end function ValidatePhone()


/////////////////////////////////////
// ValidateZip()
//
// Verifies that user has entered basically valid Zip number

function validate_zip(Field, AlertText) {

	with (Field) {

		//strip out acceptable non-numeric characters
		var Stripped = value.replace(/[\-\ ]/g, '');
		var DashPosition = value.indexOf("-");

		if (
			isNaN(parseInt(Stripped)) ||
			(Stripped.length != 5 && !(Stripped.length == 9 && DashPosition == 5 ))
		) {
			// What the... hey, that's not a valid Zip number!
	        style.background = 'Yellow';
			alert( AlertText );
	        focus();
			return(false);
		} else {
			// The Zip number looks ok
	        style.background = 'White';
			return(true);
		}
	}
} // end function ValidateZip()


/////////////////////////////////////
// ValidateRequiredField()
//
// Verifies that user has entered valid data for key lines
// on the form.

function validate_required_field(Field, AlertText) {
	with (Field) {
		if (value==null || value=="") {
	        style.background = 'Yellow';
			alert(AlertText);
	        focus();
			return(false);
		} else {
	        style.background = 'White';
			return(true);
		}
	}
} // end function ValidateRequiredField


/////////////////////////////////////
// validate_required_select()
//
// Verifies that user has entered valid data for key lines
// on the form.

function validate_required_select(Field, AlertText) {
	with (Field) {
		if (value==null || value=="0") {
			alert(AlertText);
			return(false);
		} else {
			return(true);
		}
	}
} // end function validate_required_select



/*============================================================================*/
/*
This routine checks the credit card number. The following checks are made:

1. A number has been provided
2. The number is a right length for the card
3. The number has an appropriate prefix for the card
4. The number has a valid modulus 10 number check digit if required

If the validation fails an error is reported.

The structure of credit card formats was gleaned from a variety of sources on 
the web, although the best is probably on Wikepedia ("Credit card number"):

  http://en.wikipedia.org/wiki/Credit_card_number

Parameters:
            CardNumber           number on the card
            CardType             index representing array of card types

Author:     John Gardner
Date:       1st November 2003
Updated:    26th Feb. 2005      Additional cards added by request
Updated:    27th Nov. 2006      Additional cards added from Wikipedia
Updated:    18th Jan. 2008      Additional cards added from Wikipedia

Modifier: Kai Mantsch
Updated:	31st Jul. 2008		Modified to fit coding format for LikeableLawyer.com
*/

function credit_card_error(Field, ErrorIndex) {

	// Error Array
	var ccErrorNo = 0;
	var ccErrors = new Array();
	ccErrors [0] = "Unknown card type";
	ccErrors [1] = "No card number provided";
	ccErrors [2] = "Credit card number is in invalid format";
	ccErrors [3] = "Credit card number is invalid";
	ccErrors [4] = "Credit card number has an inappropriate number of digits";
	
	with (Field) {
		style.background = 'Yellow';
		alert(ccErrors[ErrorIndex]);
		focus();
		return(false);
	}
}

function credit_card_check(CardNumberField, CardTypeField) {

	// Array to hold the permitted card characteristics
	var cards = new Array();
	var CardNumber = CardNumberField.value;
	var CardType = CardTypeField.value;
		
	// Define the cards we support. You may add addtional card types.
	
	//  Name:      As in the selection box of the form - must be same as user's
	//  Length:    List of possible valid lengths of the card number for the card
	//  prefixes:  List of possible prefixes for the card
	//  checkdigit Boolean to say whether there is a check digit
	
	cards [1] = {name: "Visa", 
			   length: "13,16", 
			   prefixes: "4",
			   checkdigit: true};
	cards [2] = {name: "MasterCard", 
			   length: "16", 
			   prefixes: "51,52,53,54,55",
			   checkdigit: true};
	cards [3] = {name: "AmEx", 
			   length: "15", 
			   prefixes: "34,37",
			   checkdigit: true};
				 
	// If card type not found, report an error
	if (CardType == -1 || CardType == 0) {
		return credit_card_error(CardNumberField,0); 
	}
	
	// Ensure that the user has provided a credit card number
	if (CardNumber.length == 0)  {
		return credit_card_error(CardNumberField,1); 
	}
	
	// Now remove any spaces from the credit card number
	CardNumber = CardNumber.replace(/\s/g, "");
	
	// Check that the number is numeric
	var cardNo = CardNumber
	var cardexp = /^[0-9]{13,19}$/;
	if (!cardexp.exec(cardNo))  {
		return credit_card_error(CardNumberField,2); 
	}
	   
	// Now check the modulus 10 check digit - if required
	if (cards[CardType].checkdigit) {

		var checksum = 0;                                  // running checksum total
		var mychar = "";                                   // next char to process
		var j = 1;                                         // takes value of 1 or 2
		
		// Process each digit one by one starting at the right
		var calc;
		for (i = cardNo.length - 1; i >= 0; i--) {
			
			// Extract the next digit and multiply by 1 or 2 on alternative digits.
			calc = Number(cardNo.charAt(i)) * j;
			
			// If the result is in two digits add 1 to the checksum total
			if (calc > 9) {
				checksum = checksum + 1;
				calc = calc - 10;
			}
			
			// Add the units element to the checksum total
			checksum = checksum + calc;
			
			// Switch the value of j
			if (j ==1) {j = 2} else {j = 1};
			
		} // end for loop
		
		// All done - if checksum is divisible by 10, it is a valid modulus 10.
		// If not, report an error.
		if (checksum % 10 != 0)  {
			return credit_card_error(CardNumberField,3); 
		}

	} // end if check for modulous 10 digit
	
	// The following are the card-specific checks we undertake.
	var LengthValid = false;
	var PrefixValid = false; 
	var undefined; 
	
	// We use these for holding the valid lengths and prefixes of a card type
	var prefix = new Array ();
	var lengths = new Array ();
	
	// Load an array with the valid prefixes for this card
	prefix = cards[CardType].prefixes.split(",");
	  
	// Now see if any of them match what we have in the card number
	for (i=0; i<prefix.length; i++) {
		var exp = new RegExp ("^" + prefix[i]);
		if (exp.test (cardNo)) PrefixValid = true;
	}
	  
	// If it isn't a valid prefix there's no point at looking at the length
	if (!PrefixValid) {
		return credit_card_error(CardNumberField,3); 
	}
	
	// See if the length is valid for this card
	lengths = cards[CardType].length.split(",");
	for (j=0; j<lengths.length; j++) {
		if (cardNo.length == lengths[j]) LengthValid = true;
	}
	
	// See if all is OK by seeing if the length was valid. We only check the 
	// length if all else was hunky dory.
	if (!LengthValid) {
		return credit_card_error(CardNumberField,4); 
	};   
	
	// The credit card is in the required format.
	CardNumberField.style.background = 'White';	
	return true;

} // end function CreditCardCheck


