
// This script contains various form validation funtions.

// Where used, fieldLabel contains the display name of the
// field being validated, and is displayed in the error alert.


function validRequired(formField,fieldLabel) {
// Makes sure a variable has something in it besides whitespace.
// Requires: trim()
	var result = true;
	if (trim(formField.value) == "") {
		alert('Please enter a value for the "'+fieldLabel+'" field.');
		formField.focus();
		result = false;
	}
	return result;
}

function validRequiredItem(formField,fieldLabel) {
// Same as validRequired(), except that fieldLabel contains the entire error code.
// Requires: trim()
	var result = true;
	if (trim(formField.value) == "") {
		alert(fieldLabel);
		formField.focus();
		result = false;
	}
	return result;
}

function invalidRequiredValue(formField,fieldLabel) {
// Fails if value matches value given below.
// fieldLabel contains the entire error code.
	var result = true;
	if (trim(formField.value) == "none") {
		alert(fieldLabel);
		formField.focus();
		result = false;
	}
	return result;
}

function validRequiredValue(formField,fieldLabel) {
// Fails if value does NOT match value given below
// fieldLabel contains the entire error code.
	var result = true;
	if (trim(formField.value) != "none") {
		alert(fieldLabel);
		formField.focus();
		result = false;
	}
	return result;
}

function validCheckbox(formField,fieldLabel) {
// Makes sure a checkbox is checked.
// fieldLabel contains the entire error message.
	var result = true;
	if (!formField.checked) {
		alert(fieldLabel);
		formField.focus();
		result = false;
	}
	return result;
}

function validRadio(formField,fieldLabel,valOption) {
// Makes sure a radio button is checked and, optionally, checks
// to see if the correct button is checked. valOption indicates
// the index (starting from zero) of the button that should be
// checked. If valOption is less than zero (-1), this check is skipped
// and the item will validate if any button in the set is checked.
// fieldLabel contains the entire error message.
	var result = false;
	selOption = -1;
	for (i = 0; i < formField.length; i++) {
		if (formField[i].checked) {
			selOption = i;
			result = true;
		}
	}
	if (result && (valOption > -1)) {
		if (selOption != valOption) result = false;
	}
	if (!result) {
		alert(fieldLabel);
		formField[0].focus();
	}
	return result;
}

function validSelect(formField,fieldLabel,index) {
// Make sure something other than the indicated index of a select list
// has been selected. The first (top) index of a select list is zero.
	var result = true;
	if (formField.selectedIndex == index) {
		alert('Please enter a value for the "'+fieldLabel+'" field.');
		formField.focus();
		result = false;
	}
	return result;
}

function validEmail(formField,fieldLabel) {
// Checks for a validly formed email address.
// Requires: isEmail(), trim()
	var result = true;
	if ((formField.value.length < 3) || !isEmail(formField.value)) {
		alert("Please enter a valid email address in the form: yourname@yourdomain.com");
		formField.focus();
		result = false;
	}
	return result;
}

function validNumeral(formField,fieldLabel) {
// Checks to see if a value contains only numerals.
// Requires: isValidChar()
	var result = true;
	if ((trim(formField.value) == "") || !isValidChar(formField.value,"0123456789")) {
		alert('Please enter a numeric value for the "'+fieldLabel+'" field.');
		formField.focus();		
		result = false;
	}
	return result;
}

function validDecimal(formField,fieldLabel) {
// Same as validNumeral(), except allows "." and "-"
// Requires: isValidChar()
	var result = true;
	if ((trim(formField.value) == "") || !isValidChar(formField.value,"0123456789.-")) {
		alert('Please enter a numeric value for the "'+fieldLabel+'" field.\nOnly numbers, "." and "-" are allowed.');
		formField.focus();		
		result = false;
	}
	return result;
}

function validDate(formField,fieldLabel) {
// Checks to see if a valid date was entered in the form MM/DD/YYYY
	var result = true;
	var elems = formField.value.split("/");
	if ((elems.length != 3) ||
		(elems[0].length != 2) || !isAllDigits(elems[0]) || (elems[0] < 1) || (elems[0] > 12) ||
		(elems[1].length != 2) || !isAllDigits(elems[1]) || (elems[1] < 1) || (elems[1] > 31) ||
		(elems[2].length != 4) || !isAllDigits(elems[2]))
		result = false;
	if (result) {
		var test = new Date(elems[2],elems[0]-1,elems[1]);
		if ((elems[2] != test.getFullYear()) || 
			(elems[0] != test.getMonth()+1) || 
			(elems[1] != test.getDate()) ) 
			result = false;
	}
	if (!result) {
		alert('Please enter a date in the format MM/DD/YYYY for the "'+fieldLabel+'" field.');
		formField.focus();		
	}
	return result;
}

function validCC(ccType,ccNumber,ccExpMonth,ccExpYear,server_time) {
// Checks for a valid credit card number, that the number
// is correct for the type of card indicated, and that the expiration
// date is not in the past. If server_time is zero, local time will be used.
// The string "0000111122223333" will validate, so as to allow
// for testing other site functions without entering a live CC number.
// Requires: validRequired(), isAllDigits(), LuhnCheck(), validCCType(), validCCExp(), trim()
	var result = true;
 	var ccNum = ccNumber.value;
	result = validRequired(ccType,"Credit Card Type");
	if (result) result = validRequired(ccNumber,"Credit Card Number");
	if (result) result = validRequired(ccExpMonth,"Credit Card Expiration Month");
	if (result) result = validRequired(ccExpYear,"Credit Card Expiration Year");
	if (result && !isAllDigits(ccNum)) {
		alert('Please enter only numbers (no dashes or spaces) for the Credit Card Number.');
		ccNumber.focus();
		result = false;
	}
	if (result && (ccNum != "0000111122223333") && !LuhnCheck(ccNum)) {
		alert('Please enter a valid Credit Card Number.');
		ccNumber.focus();
		result = false;
	}
	if (result && (ccNum != "0000111122223333") && !validCCType(ccType.value,ccNum)) {
		alert('The Credit Card Number does not match the Credit Card Type indicated.\nPlease enter a valid Credit Card Number and Type.');
		ccNumber.focus();
		result = false;
	}
	if (result && !validCCExp(ccExpMonth,ccExpYear,server_time)) {
		alert('Your credit card has expired. Please enter a valid expiration date.');
		ccExpMonth.focus();
		result = false;
	}
	return result;
}




// Utility Functions -- functions used by the main functions

function isEmail(str) {
// Checks a string to see if it is in the form of an email address.
	var result = false;
	var index1 = str.indexOf("@");
	if (index1 > 0) {
		var index2 = str.indexOf(".",index1);
		if ((index2 > index1+1) && (str.length > index2+1)) result = true;
	}
	return result;
}

function isAllDigits(str) {
// Checks to see if string only contains numeric digits.
// Requires: isValidChar()
	return isValidChar(str,"0123456789");
}

function isValidChar(str,charset) {
// Checks to see if string contains any character not listed in charset.
	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 trim(str) {
// Trim left and right white space from a string
// Requires: ltrim(), rtrim()
	return rtrim(ltrim(str));
}

function ltrim(str) {
// Trim left white space from a string
	while( str.indexOf(' ') == 0 ) {
	  str = str.substring(1)
	}
	return str;
}

function rtrim(str){
// Trim right white space from a string
	while( str.lastIndexOf(' ') == str.length-1 && str.length > 0 ) {
	  str = str.substring(0,str.length-1)
	}
	return str;
}

function LuhnCheck(str) {
// Checks validity of credit card number.
	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 validCCType(cardType,cardNum) {
// Checks that the card type matches the card number.
	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;
}

function validCCExp(monthField,yearField,server_time) {
// Makes sure the month and four digit year given are not in the past.
// The variable server_time is the current time in milliseconds since
// Jan 1, 1970, and should be set by the server to avoid problems with
// the local clock being wrong.
// If server_time is set to zero, local system time will be used instead.
	var result = true;
	var month = monthField.value;
	var year = yearField.value;
	if (server_time == 0) {
		var today = new Date();
	} else {
		var today = new Date(server_time);
	}
	var now_month = today.getMonth() + 1;
	var now_year = today.getFullYear();
	if (year.length == 2) now_year -= 2000;
	if (year < now_year || (year == now_year && month < now_month)) result = false;
	return result;
}

