/*
$RCSfile: validate2.js,v $ $Revision: 1.2 $ in tag $Name:  $
last committed $Date: 2006/02/03 20:31:29 $
=============================================
When        Who   	What
---------------------------------------------
2004-01-28	jsg		added		
=============================================

Notes:

	Validation functions.
	The validateForm() function processes a structure
	like the example included here and validates
	the form accordingly. 
*/

function isBlank( str ) {
     var isValid = false;
     if ( isNull(str) || isUndef(str) || (str+"" == "") ) {
          isValid = true;
	}
     return isValid;
}  // end IsBlank

function isText(str /*, maxlen*/)
{
	var maxlen = 0;
	with (isText) {
		if (arguments.length >= 2) {
			maxlen = new Number(arguments[1]);
		}
	}

//	alert ("maxlen = " + maxlen);
	
	if (maxlen > 0 && str.length > maxlen) {
		return "Only " + maxlen + " characters allowed.";
	}

	var isValid = "";
    if ( isNull(str) || isUndef(str) || (str+"" == "") ) {
		isValid = "Empty entries are not allowed.";
	}
	return isValid;
}
	
function isAllDigits(s)
{
    var maxlen = 0;
	with (isAllDigits) {
		if (arguments.length >= 2) {
			maxlen = new Number(arguments[1]);
		}
	}

//	alert ("maxlen = " + maxlen);
	
	if (maxlen > 0 && s.length > maxlen) {
		return "Only " + maxlen + " characters allowed.";
	}
	
	
	var str = "" + s;
    for (var k = 0; k < str.length; k++) {
		if (! (str.charAt(k) >= "0" && str.charAt(k) <= "9")) {
            return "Only numbers (0 - 9) are allowed.";
        }
    }
    return "";
}



function isAlpha (str /*, maxlen*/) 
{
     // Return immediately if an invalid value was passed in
    if (str+"" == "undefined" || str+"" == "null" || str+"" == "") {
		return "Empty entries are not allowed.";
	}

	var maxlen = 0;
	with (isAlpha) {
		if (arguments.length >= 2) {
			maxlen = new Number(arguments[1]);
		}
	}

	if (maxlen > 0 && str.length > maxlen) {
		return "Only " + maxlen + " letters allowed.";
	}
	
    var isValid = "";
    str += "";
	// convert to a string for performing string comparisons.

    // Loop through string one character at time,  breaking out of for
    // loop when an non Alpha character is found.
	for (i = 0; i < str.length; i++) {
        // Alpha must be between "A"-"Z", or "a"-"z"
        if ( !( ((str.charAt(i) >= "a") && (str.charAt(i) <= "z")) ||
        		((str.charAt(i) >= "A") && (str.charAt(i) <= "Z")) ) )
		{
        	isValid = "Only letters (A - Z) are allowed.";
            break;
        }
   } // end for loop

   return isValid;
}  // end IsAlpha

function isNull( val ) {
     var isValid = false;

     if (val+"" == "null")
          isValid = true;

     return isValid;
}  // end IsNull

function isUndef( val ) {
     var isValid = false;

     if (val+"" == "undefined")
          isValid = true;

     return isValid;
}  // end IsUndef


function isValidTime(str){
	if (str+"" == "undefined" || str+"" == "null" || str+"" == "")
          return "Empty entries are not allowed.";
		  
	var isValid = "";
	
	str += "";
	
	hstr = str.substring(0, str.indexOf(":"));
	mstr = str.substring(str.indexOf(":")+1, str.length);
	
	
	if ((hstr.length == 0) ||
			(mstr.length <= 1) ||
			(str.charAt(str.length-1) != "m"))
		isValid = "Please enter something like '10:00 pm'";
		
	return isValid;	
}	



function isValidMilitaryTime(str){
	if (str+"" == "undefined" || str+"" == "null" || str+"" == "")
          return "Empty entries are not allowed.";
		  
	str += "";
	var errstr = "Please enter time in military format, like '23:30' or '2330'";
	var colonindex = str.indexOf(":");
	
	/* Allows for quick entry, like 1545 or 300 or 1215 */
	if (colonindex == -1){
		if (str.length < 3)	return errstr; //wasn't long enough to be a time
		var tmpnum = str*1;
		if (tmpnum > 2459 || tmpnum < 0) return errstr; // was out of range
		for (i=0; i<str.length; i++) {
			if ((str.charAt(i) < "0") || (str.charAt(i) > "9")) return errstr; //wasn't all digits
	    }
	}
	else{
		hstr = str.substring(0, colonindex);
		mstr = str.substring(colonindex + 1, str.length);
		hnum = hstr * 1;
		mnum = mstr * 1;
		if (hnum > 24 || hnum < 0 || mnum > 59 || mnum < 0) return errstr;
	}
	
	return "";	
}	


function isValidDate(str)
{
	
	var splitters = new Array("-", " ", "/");
	var fourdigityear = false;
	
	for (key in splitters){
		//Split on " " or "-" or "/"
		arr = str.split(splitters[key]);
		//Still good if array has 3 elements
		if (arr.length == 3){
			for (key2 in arr) {
				fourdigityear = (fourdigityear || arr[key2].length == 4);
				//Still good if one of the elements is 4 digits long
				if (fourdigityear){
					//Finally, make sure each of the three elements is all digits
					for (key3 in arr) return isAllDigits(arr[key3]);
				}
			}
		}
	}
	return "A 4-digit year is required. Enter date like '2/30/2001' or '2001-02-30' or even '2001 2 30'."
}		

// Specific validation for date in this format: "mm/dd/yyyy"
function isValidDate2(str) {
	
	var arr = str.split("/");
	var errstr = "Please enter date in the following format: MM/DD/YYYY.  Ex: '2/30/2001'";
	var gooddate = true;

	//Still good if array has 3 elements
	if (arr.length == 3) {
		for (key in arr) {
			// month
			if (key == 0) {
				if (arr[key] < 1 || arr[key] > 12) return(errstr);
				if (isAllDigits(arr[key]) != "") return(errstr);
			}
			// day
			else if (key == 1) {
				if (arr[key] < 1 || arr[key] > 31) return(errstr);
				if (isAllDigits(arr[key]) != "") return(errstr);
			}
			// year
			else if (key == 2) {
				if (arr[key].length != 4) return(errstr);
				if (isAllDigits(arr[key]) != "") return(errstr);
			}
		}
	}

	// bad array
	else {
		return(errstr);
	}

// looks good...
return("");
}
	
// New function that validates the email in the form
function isValidEmail (str /*, maxlen */) {
     // Return immediately if an invalid value was passed in
    if (str+"" == "undefined" || str+"" == "null" || str+"" == "") {
          return "Empty entries are not allowed.";
	}

     var isValid = "";
     str += "";

     namestr = str.substring(0, str.indexOf("@"));
	 // everything before the '@'
     domainstr = str.substring(str.indexOf("@")+1, str.length);
	 // everything after the '@'

	 // Rules: namestr cannot be empty, or that would indicate no
	 // characters before the '@',
     // domainstr must contain a period that is not the first character
	 // (i.e. right after
     // the '@').  The last character must be an alpha.
     if ((namestr.length == 0) ||
               (domainstr.indexOf(".") <= 0) ||
               (domainstr.indexOf("@") != -1))
               //isAlpha(str.charAt(str.length-1)) != "")
	{
//		alert(isAlpha(str.charAt(str.length-1)));
    	isValid = "Please enter a valid email address like 'user@domain.org'.";
	}

     return isValid;
} // end IsValidEmail

function isUSState(str) 
{
	str = str.toUpperCase();
	
  	if ( (str == "AA") || (str == "AE") || (str == "AK") || (str == "AL") || (str == "AR") || (str == "AP") || (str == "AZ") || (str == "CA") || (str == "CO") || (str == "CT") || (str == "DC") || (str == "DE") || (str == "FL") || (str == "GA") || (str == "HI") || (str == "IA") || (str == "ID") || (str == "IL") || (str == "IN") || (str == "KS") || (str == "KY") || (str == "LA") || (str == "MA") || (str == "MD") || (str == "ME") || (str == "MI") || (str == "MN") || (str == "MO") || (str == "MS") || (str == "MT") || (str == "NE") || (str == "NC") || (str == "ND") || (str == "NH") || (str == "NJ") || (str == "NM") || (str == "NV") || (str == "NY") || (str == "OH") || (str == "OK") || (str == "OR") || (str == "PA") || (str == "RI") || (str == "SC") || (str == "SD") || (str == "TN") || (str == "TX") || (str == "UT") || (str == "VA") || (str == "VT") || (str == "WA") || (str == "WI") || (str == "WV") || (str == "WY") )
	{
		return "";
	}
	else {
		return "Please enter a valid 2-letter US state code.";
	}
}

// Functions that validates the phone number in the form
function isPhoneNum(str) 
{
	var errstr = "Please enter a phone number in the format 800-555-1212";

  	if (str.length != 12) { 
  		return errstr;
	}
  	for (i=0; i<str.length; i++) {
    	if ((i == 3) || (i == 7)) {
	      	if (str.charAt(i) != "-") { 
				return errstr;
			}
    	} 
		else {
    	  	if ((str.charAt(i) < "0") || (str.charAt(i) > "9")) { 
				return errstr;
			}
	    }
	}
  	return "";
}

// Functions that validates the phone number in the form in this format: (###) ###-####
function isPhoneNum2(str) {

	var errstr = "Please enter a phone number in the format (800) 555-1212";

  	if (str.length != 14) { 
  		return errstr;
	}
  	for (i=0; i<str.length; i++) {
    	if (i == 0) {
	      	if (str.charAt(i) != "(") { 
				return errstr;
			}
    	} 
    	else if (i == 4) {
	      	if (str.charAt(i) != ")") { 
				return errstr;
			}
    	} 
    	else if (i == 5) {
	      	if (str.charAt(i) != " ") { 
				return errstr;
			}
    	} 
    	else if (i == 9) {
	      	if (str.charAt(i) != "-") { 
				return errstr;
			}
    	} 
		else {
    	  	if ((str.charAt(i) < "0") || (str.charAt(i) > "9")) { 
				return errstr;
			}
	    }
	}
  	return "";
}

function isPhoneNum3(str) {

	var errstr = "Please enter a phone number in one of the following formats: 1234567, 1234567890, 123.1234, 123.123.1234, 123-1234 or 123-123-1234";
	
	if (str.length != 7 && str.length != 10 && str.length != 12 && str.length != 8){
		return errstr;
	} else {
		if (str.length == 7 || str.length == 10){
			return (isAllDigits(str));
		} else if (str.length == 8){
			if (str.charAt(3) != '.' && str.charAt(3) != '-'){
				return errstr;
			} else {
				var newstr = str.substring(0, 3) + str.substring(4, 8);
				return isAllDigits(newstr);
			}
		} else if (str.length == 12){
			if ((str.charAt(3) == '.' && str.charAt(7) == '.') || (str.charAt(3) == '-' && str.charAt(7) == '-')){
				var newstr = str.substring(0, 3) + str.substring(4, 7) + str.substring(8, 12);
				return isAllDigits(newstr);
			} else {
				return errstr;
			}
		}
	}
	
}

function isValidZIPCode(zip)
{
    if (zip.length == 5) {
        return (isAllDigits(zip));
	}
    else if (zip.length == 10)
    {
        return (isAllDigits(zip.substring(0,5)) && (zip.substring(5,6) == "-") && (isAllDigits(zip.substring(6,10))));
	}
	return "Please enter a ZIP code in the format '12345' or '12345-6789'.";
}

function isValidMonth(str)
{
	var errstr;
	if ((errstr = isAllDigits(str)) != "") {
		return errstr;
	}
	var num = new Number(str);
	if (num < 1 || num > 12) {
		return "Please enter a number between 1 and 12.";
	}
	return "";
}

function isValidDay(str)
{
	var errstr;
	if ((errstr = isAllDigits(str)) != "") {
		return errstr;
	}

	var num = new Number(str);
	if (num < 1 || num > 12) {
		return "Please enter a number between 1 and 31.";
	}
	return "";
}

// Verify mod10 status of number.  Last character is modulus character.
function isMod10(instr) {
	var isValid = "";
	var digitstr = new String(instr);
	digitstr = digitstr.replace(/\D/g, '');  // strip all things non-numeric
	var modchar = parseInt(digitstr.substring(digitstr.length-1, digitstr.length)); // get the mod character
	digitstr = digitstr.substring(0, digitstr.length-1); // and the data string without mod character
	var strlen = digitstr.length;
	var currnum = 0;
	var sum = 0;

	dbg("digitstr", digitstr);
	dbg("modchar", modchar);

	for (i = 0; i < strlen; i++) {
		currnum = parseInt(digitstr.charAt(i));
		if (!(i & 1)) {				// double the even ones starting with 0, but i don't quite know why
			currnum += currnum;		// double it 
			if (currnum > 9) {		// check for any carry 
				currnum -= 9;
			}
		}
		sum += currnum;
	}
	sum %= 10;						// mod 10 it
	if (sum > 0) {
		sum = 10 - sum;
	}
	sum = parseInt(sum);			// make sure its an integer
	if (sum != modchar) {
		isValid = "Invalid Order Number";
	}

	return(isValid);
}

function radio_isBlank(radio)
{
	var	isBlank = true;
	for (index = 0; index < radio.length; index++) {
		if (radio[index].checked == true) isBlank = false;
	}
	return isBlank;
}

//tweaked isAllDigits for this one
function isValidHeight(h)
{
    var str = "" + h;
    for (var k = 0; k < str.length; k++) {
		if (! ((str.charAt(k) >= "0" && str.charAt(k) <= "9") || (str.charAt(k) == "-" && str.charAt(k) == "-"))  ) {
            return "Please enter a value like 5-10";
        }
    }
    return "";
}

/*	This prototype defines a validation "object". We make an array of these objects that is 
	specific for a particular form being validated. */
function valobj(fieldname,fieldcapt,inptype,blankfunc,validfunc,maxlen)
{ this.fieldname = fieldname; this.fieldcapt = fieldcapt; this.inptype = inptype; this.blankfunc = blankfunc;  this.validfunc = validfunc; 
this.maxlen = (("undefined" == "" + maxlen || maxlen == null) ? 0 : 0 + maxlen);
//alert("this.maxlen = " + this.maxlen);
}

/*	This code below should go near the form being validated or in a page-specific script file. */
/*	Example:
var valfields = new Array();
var cnt = 0;

valfields[cnt++] = new valobj("Lname", "Last Name", "text", isBlank, isText);
valfields[cnt++] = new valobj("State", "State", "text", isBlank, isUSState);
valfields[cnt++] = new valobj("Zip", "Zip", "text", isBlank, isValidZIPCode);
valfields[cnt++] = new valobj("Telephone", "Telephone", "text", isBlank, isPhoneNum);
valfields[cnt++] = new valobj("Email", "Email", "text", isBlank, isValidEmail);
valfields[cnt++] = new valobj("C1Fname", "First Child First Name", "text", isBlank, isText);
valfields[cnt++] = new valobj("C1Lname", "First Child Last Name", "text", null, isText);
valfields[cnt++] = new valobj("C1Sex", "First Child Sex", "radio", radio_isBlank, null);
valfields[cnt++] = new valobj("C1month", "First Child Birthday Month", "text", isBlank, isValidMonth);
valfields[cnt++] = new valobj("C1day", "First Child Birthday Day", "text", isBlank, isValidDay);
valfields[cnt++] = new valobj("C1year", "First Child Birthday Year", "text", isBlank, isAllDigits);
valfields[cnt++] = new valobj("C2Fname", "Second Child First Name", "text", null, isText);
*/



/*	Here's the granddaddy function that does it all. */
function validateForm(form) 
{
	//alert("In validateForm()... Form name = " + form.name);
	var fieldarray;
	var	local = false;
	
	/*	Allow an alternate field array to be passed in as a second parameter. */
	if (validateForm.arguments.length == 2) {
		fieldarray = validateForm.arguments[1];
		local = true;
	}
	else {
		/*	Use default, global fieldarray. */
		fieldarray = valfields;
	}
	
	//alert("fieldarray.length = " + fieldarray.length);
	
	//var logstr = "";
	var fieldno = 0;
	for (fieldno in fieldarray)
	{
		//alert("fieldno = " + fieldno);
		var fieldname = fieldarray[fieldno].fieldname;
		var fieldcapt = fieldarray[fieldno].fieldcapt;
		var blankfunc = fieldarray[fieldno].blankfunc;
		var validfunc = fieldarray[fieldno].validfunc;
		var inptype = fieldarray[fieldno].inptype;
		var maxlen = fieldarray[fieldno].maxlen;
//		alert("fieldarray[].maxlen = " + maxlen);
		var blank = false;
		
		//logstr += fieldname + "; "
		//alert(fieldname + " - " + fieldcapt);
		
		if (typeof (form[fieldname]) != "object") {
			//alert("Form inputs processed so far: " + logstr);
			alert("Program error: '" + fieldname + "' is not a form input.");
			continue;
		}
		
		/*	First check the blankness of the input. The polarity is such that if the
			function returns true we're blank. If no function is specified then it's ok
			for this input to be blank. But if there's a validfunc we'll still check its
			validity if there's something in it. */
		if (typeof (blankfunc) == "function") {
			if (inptype == "radio") {
				/*	Pass the actual input object */
				blank = blankfunc(form[fieldname]);
				if (blank) {
					alert("Please select an option for '" + fieldcapt + "'.");
					/*	Focus on the first radio in the group. */
					form[fieldname][0].focus();
				}
			} else if (inptype == "checkbox") {
				errstr = blankfunc(form[fieldname]);
				if (errstr != '') blank = true;
				if (blank) {
					alert(errstr);
					form[fieldname].focus();
				}
            } else {
				//alert(fieldname + " = |" + form[fieldname].value + "|");
				blank = blankfunc(form[fieldname].value);
				if (blank) {
					alert("Please enter a value in the '" + fieldcapt + "' box.");
					form[fieldname].focus();
				}
			}
			if (blank) return (false);
		}
		else {
			/*	This might look funny, but if we passed the blank function but
				if we get here we either don't have a blankfunc or we passed it. But
				do a check to make sure the input isn't blank; if it is it will probably
				fail its validation routine, so continue to the next input. */
			if (inptype == "text" && isBlank(form[fieldname].value)) continue;
		}
		
		/*	Now check the validness of the input. Polarity is true == good value. */
		/*	Figure that radio buttons will not need a validate func. */
		var errstr;
		
		if ((typeof (validfunc) == "function") && ((errstr = validfunc(form[fieldname].value,maxlen)) != "")) {
			alert("'" + form[fieldname].value + "' is not a valid value for '" + fieldcapt + "'.\r\n" + errstr);

			form[fieldname].focus();
			return (false);
		}
	}
	

	if (!local) {
		if (typeof(local_validateForm) == "function") {
			return local_validateForm(form);
		}
	}
	
	return true;
}

/*    New function to validate Expiration Dates for credit cards (format: MM/YY)  */
function isValidExpDate(str) {
	var splitter = "/";
	var str_error = "Expiration dates must be in the MM/YY format (ex: 08/05)";
	
	//Split on "/"
	arr = str.split(splitter);
	
	//Still good if array has 2 elements
	if (arr.length == 2){
	        for (key in arr) {
	                if (arr[key].length != 2 || isNaN(arr[key])) {
	                        return str_error;
	                }
	        }
	}
	// Otherwise its an error
	else {
	        return str_error;
	}
	return "";
}

/*	Here's the granddaddy function that does it all. */
function validate_fields(inputs)
{
	var local = false;
	
	var fieldno = 0;
	for (fieldno in inputs)
	{
		var fieldname = inputs[fieldno].fieldname;
		var fieldcapt = inputs[fieldno].fieldcapt;
		var blankfunc = inputs[fieldno].blankfunc;
		var validfunc = inputs[fieldno].validfunc;
		var inptype = inputs[fieldno].inptype;
		var maxlen = inputs[fieldno].maxlen;
		var input = document.getElementById(fieldname)
		var blank = false;

		if (typeof (input) != "object") {
			//alert("Form inputs processed so far: " + logstr);
			alert("Program error: '" + fieldname + "' is not an input.");
			continue;
		}
		
		/*	First check the blankness of the input. The polarity is such that if the
			function returns true we're blank. If no function is specified then it's ok
			for this input to be blank. But if there's a validfunc we'll still check its
			validity if there's something in it. */
		if (typeof (blankfunc) == "function") {
			if (inptype == "radio") {
				/*	Pass the actual input object */
				blank = blankfunc(input);
				if (blank) {
					alert("Please select an option for '" + fieldcapt + "'.");
					/*	Focus on the first radio in the group. */
					input[0].focus();
				}
			} else if (inptype == "checkbox") {
				errstr = blankfunc(input);
				if (errstr != '') blank = true;
				if (blank) {
					alert(errstr);
					input.focus();
				}
            } else {
				//alert(fieldname + " = |" + input.value + "|");
				blank = blankfunc(input.value);
				if (blank) {
					alert("Please enter a value in the '" + fieldcapt + "' box.");
					input.focus();
				}
			}
			if (blank) return (false);
		}
		else {
			/*	This might look funny, but if we passed the blank function but
				if we get here we either don't have a blankfunc or we passed it. But
				do a check to make sure the input isn't blank; if it is it will probably
				fail its validation routine, so continue to the next input. */
			if (inptype == "text" && isBlank(input.value)) continue;
		}
		
		/*	Now check the validness of the input. Polarity is true == good value. */
		/*	Figure that radio buttons will not need a validate func. */
		var errstr;
		
		if ((typeof (validfunc) == "function") && ((errstr = validfunc(input.value,maxlen)) != "")) {
			alert("'" + input.value + "' is not a valid value for '" + fieldcapt + "'.\r\n" + errstr);

			input.focus();
			return (false);
		}
	}
	

	if (!local) {
		if (typeof(local_validateForm) == "function") {
			return local_validateForm(input);
		}
	}
	
	return true;
}
