// These functions validate data entered in forms
// 
//
// Some functions have been provided by a validation
// script written by
//
// 18 Feb 97 created Eric Krock
//
// (c) 1997 Netscape Communications Corporation
//
// Other functions and scripting initially done by Andrew Wong and Jeannine // 
// Schumm.
// (c) 2001, 2002, 2003 JMPT Consulting, Inc.
// 
// 12/29/2003 gbf
// modified CheckForm validation
// revised isNumeric to allow '+' and '-' at the beginning of the string
// revised isNumeric to check for multiple '.'
// 12/30/2003
// changed phone and int validation.  
// revised getLabel to handle no labels.

var defaultEmptyOK = true;

//markChange(form)
// set the change field of the form to 'yes'
function markChange(form) {
	var e = form.elements["changed"];
	
	e.value = 'yes';
}


// set the nextAction field of the form
function publishPost(form) {
	var e = form.elements["nextAction"];
	
	e.value = "publish";
	newCheckForm(form);
}


// set the nextAction field of the form
function previewPost(form) {
	var e = form.elements["nextAction"];
	
	e.value = "preview";
	newCheckForm(form);
}


// set the nextAction field of the form
function nextAction(form, strNextAction) {
	var e = form.elements["nextAction"];
	
	e.value = strNextAction;
	newCheckForm(form);
}


// master form validation function
function newCheckForm(form) {
// to add a new function check, include a variable that 
// stores the result of the function check -- like badmusic
// define the function isMusic
// function isMusic should return true and false values
// add the check for badmusic before the form submittal


var msg;
var toolong = "";
var badrequired = "";
var baddate = "";
var badint = "";
var badnumber = "";
var badphone = "";
var badssn = "";
var badmoney = "";
var badlength = "";
var badstrength = "";
var bademail = "";
var badticket = "";


	for(i=0; i<form.length; i++){

		//get sections out of form field name
		var e = form.elements[i];
		//alert(e);
		if (e.name.indexOf("%")!=-1) {

			//break form field name into components
			columnInfo = e.name.split("%");
			//This section may need to be edited to account for
			//different form field name constructions.
			columnname=columnInfo[0];
			required=columnInfo[1];
			pk=columnInfo[2];
			validationFunction=columnInfo[3];
			validationParameter=columnInfo[4];

			//alert(e.name + " validationFunction is " + validationFunction);

	//			if (columnname=="testRadio") {
	//				alert(e.type);
	//			}


			//make sure required fields are not null
			if(required==0) {
				//continue with loop
			} 
			else if(required==1 && e.type=="select-one" && e.selectedIndex==0) {
				badrequired += "\n     " + columnname;
			}
			else if(required==1 && e.type!="select-one" && isEmpty(e.value)) {
				badrequired += "\n     " + columnname;
			}  else if(required==1 && e.type=="radio") {
				//alert(form[e.name].length);

				badrequired += "\n     " + checkRadio(form, i);

				i = i + form[e.name].length;

			} 


			if (validationFunction=="Date") {
				baddate += checkDate(form, i);
				// advance the element increment
				// for the other 2 date fields
				i = i + 2;
			} 

			if (validationFunction=="Money") {
				badmoney += checkMoney(form, i);
			} 

			if (validationFunction=="Number") {
				badnumber += checkNumber(form, i);
				//alert("bad int is " + badint);
			} 


			if (validationFunction=="Integer") {
				badint += checkInteger(form, i);
				//alert("bad int is " + badint);
			} 


			if (validationFunction=="Phone") {
				badphone += checkPhone(form, i);
				//alert("bad int is " + badint);
				// advance the element increment
				// for the other 2 phone fields
				i = i + 2;
			} 

			if (validationFunction=="Strength") {
				badstrength += checkStrength(form, i);
			} 




			if (validationFunction=="Length") {
				badlength += checkLength(form, i, validationParameter);
				//alert("bad length is " + badlength);
			} 


			if (validationFunction=="Email") {
				bademail += checkEmail(form, i, validationParameter);
				//alert("bad email is " + bademail);
			} 



		}
	}

	if (typeof document.getElementById('Tickets'))
	{	
		try {
			if (parseInt(form.Tickets.value) < (parseInt(form.Meat.value) + parseInt(form.Vegetarian.value))) 
			{
				badticket += "Bad"; 
			} else
			{
				//alert(	form.Tickets.value + " " + form.Meat.value + form.Vegetarian.value);
			}
		} catch (err) {
		}
		//alert(	parseInt(form.Tickets.value) + " " +(parseInt(form.Meat.value) + parseInt(form.Vegetarian.value)));
	}
	if (!badrequired && !badlength && !baddate && !badint && !badnumber && !badphone && !badssn && !badmoney && !badstrength && !bademail && !badticket ) {
		form.submit();
		return;
	}

	msg = "Your changes could not be saved because of the following error(s).\n\n";

	if (badrequired) {
		msg+="The following required field(s) are empty:" + badrequired + "\n";
	}

	if (badstrength) {
		msg+="The following strength field(s) are not in the correct range:" + badstrength + "\n";
	}


	if (badlength) {
		msg+="The following field(s) contain too many characters:" + badlength + "\n";
	}

	if (badmoney) {
		msg+="The following money field(s) do not contain valid amounts:" + badmoney + "\n";
	}

	if (baddate) {
		msg+="The following date field(s) do not contain valid dates:" + baddate + "\n";
	}

	if (badint) {
		msg+="The following integer field(s) do not contain valid integers:" + badint + "\n";
	}

	if (badnumber) {
		msg+="The following numeric field(s) do not contain valid numbers:" + badnumber + "\n";
	}

	if (badphone) {
			msg+="The following phone number field(s) do not contain valid phone numbers:" + badphone + "\n";
	}

	if (badssn) {
		msg+="The following Social Security number field(s) do not contain valid Social Security numbers:" + badssn + "\n";
	}

	if (bademail) {
		msg+="The following Email address does not appear to be valid:" + bademail + "\n";
	}

	if (badticket) {
		msg+="The number of people in your party is less than the number of meals requested.\n";
	}


	alert(msg);

}


// get label for field, return columnname if lable not found
function getLabel(form, eIndex) {

	var e = form.elements[eIndex];
	columnInfo = e.name.split("%");
	columnname= columnInfo[0];

	var labelName="";
	
	if (form.labels == null) { return columnname;}
	else {
		var labelArray=form.labels.value.split("%");



		for(j=0; j<labelArray.length; j++) {
			if(labelArray[j]==columnname){
				labelName = labelArray[j+1];
				return labelName;
			}
		}
		if (labelName=="") return columnname;
	}
}


function checkInteger(form, eIndex)
{   	
	var e = form.elements[eIndex];


//	alert("Checking " + getLabel(form, eIndex) + " value is " + e.value);


	if(!(isInteger(e.value)) && !(isSignedInteger(e.value))) {
		return("\n" + getLabel(form, eIndex) );

	} else return("");
}



function checkStrength(form, eIndex)
{   	
	var e = form.elements[eIndex];


//	alert("Checking " + getLabel(form, eIndex) + " value is " + e.value);


	if(!(isInteger(e.value)) && !(isSignedInteger(e.value))) {
		return("\n" + getLabel(form, eIndex) );

	} else if ( (e.value.length>0) && (e.value<0 || e.value>5)) {
		return("\n" + getLabel(form, eIndex) );
	}
	
	else return("");
}


function checkRadio(form, eIndex)
{   	
	var e = form.elements[eIndex];



	for (j=0; j<form[e.name].length; j++) {
		if (form.elements[eIndex + j].checked)
		return("");
	} 
	return("\n" + getLabel(form, eIndex) );
}


function checkLength(form, eIndex, maxLength)
{   	
	var e = form.elements[eIndex];

	if (maxLength=="Blob") return("");
 	else if(parseInt(maxLength) < e.value.length) { 
		return("\n" + getLabel(form, eIndex) );
	} else return("");

 
}


function checkEmail(form, eIndex, maxLength)
{   	
	var e = form.elements[eIndex];


	if (isEmpty(form.elements[eIndex].value)) return("");

	if(parseInt(maxLength) < e.value.length) { 
		return("\n" + getLabel(form, eIndex) );
	} 

	
	var emailPat=/^[a-z0-9]+([_|\-|.][a-z0-9]+)*\@([a-z0-9]+((-*)(.*)[a-z0-9]+)*\.(com|edu|biz|org|gov|int|info|mil|net|arpa|name|museum|coop|aero|[a-z][a-z])|(\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]))$/;
	if (!emailPat.test( (e.value).toLowerCase() ))
  	{
		return("\n" + getLabel(form, eIndex) );
  	}
  	else return("");
}



 


// Check whether field is valid number / 

function checkNumber(form, eIndex)
{   
	if (isEmpty(form.elements[eIndex].value)) return("");

	if (!isNumeric(form.elements[eIndex].value)) {
		return("\n" + getLabel(form, eIndex) );
	} else return("");
}




// Check whether field is valid money / 

function checkMoney(form, eIndex)
{   
	if (isEmpty(form.elements[eIndex].value)) return("");

	if (!isNumeric(form.elements[eIndex].value)) {
		return("\n" + getLabel(form, eIndex) );
	} else return("");
}



// Check whether 3 fields starting with eIndex compose a date / 

function checkDate(form, eIndex)
{   
	//alert(form.elements[eIndex].value + " / " + form.elements[eIndex+1].value + "/ " + form.elements[eIndex+2].value );
	if (isEmpty(form.elements[eIndex].value) &&  isEmpty(form.elements[eIndex +1].value) && isEmpty(form.elements[eIndex+2].value)) return("");
	
	if (!isDate(form.elements[eIndex +2].value, form.elements[eIndex].value, form.elements[eIndex +1].value)) { 			return("\n" + getLabel(form, eIndex) );
	} else return("");
}


// Check whether 3 fields starting with eIndex compose a phone number / 

function checkPhone(form, eIndex)
{   
	if (isEmpty(form.elements[eIndex].value) &&  isEmpty(form.elements[eIndex +1].value) && isEmpty(form.elements[eIndex+2].value)) return("");



	//alert("1 is " + 
	if ( !isNumeric(form.elements[eIndex +2].value) || !isNumeric(form.elements[eIndex].value) || !isNumeric(form.elements[eIndex +1].value) || !(form.elements[eIndex +2].value.length==4) || !(form.elements[eIndex].value.length==3) || !(form.elements[eIndex+ 1].value.length==3)) { 			return("\n" + getLabel(form, eIndex) );
	} else return("");
}




// Check whether string s is empty.

function isEmpty(s)
{   return ((s == null) || (s.length == 0));
}

// beginning of number-validation functions

// Returns true if character c is a digit
// (0 .. 9).

function isDigit (c)
{   return ((c >= "0") && (c <= "9"))
}

// isInteger (STRING s [, BOOLEAN emptyOK])
//
// Returns true if all characters in string s are numbers.
//
// Accepts non-signed integers only. Does not accept floating
// point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// By default, returns defaultEmptyOK if s is empty.
// There is an optional second argument called emptyOK.
// emptyOK is used to override for a single function call
//      the default behavior which is specified globally by
//      defaultEmptyOK.
// If emptyOK is false (or any value other than true), 
//      the function will return false if s is empty.
// If emptyOK is true, the function will return true if s is empty.
//
// EXAMPLE FUNCTION CALL:     RESULT:
// isInteger ("5")            true 
// isInteger ("")             defaultEmptyOK
// isInteger ("-5")           false
// isInteger ("", true)       true
// isInteger ("", false)      false
// isInteger ("5", false)     true

function isInteger(s)

{   var i
    var j=0;

    if (isEmpty(s)) 
       if (isInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isInteger.arguments[1] == true);

    // Search through string's characters one by one
    // until we find a non-numeric 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.
        var c = s.charAt(i);

        if (!isDigit(c)) j = ++j;
    }

    if (j>0)
        return false;
    else
        // All characters are numbers.
        return true;
}

function isNumeric(s)

{   var i
    var j=0;
    var decimalCount=0;

    if (isEmpty(s)) 
       if (isNumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isNumeric.arguments[1] == true);

    // Search through string's characters one by one
    // until we find a non-numeric character or a character
    // that is not a decimal point.
    // When we do, return false; if we don't, return true.
    // '+' or '-' is fine for the first number
    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number.
        var c = s.charAt(i);

        if (!isDigit(c) && c!=".") {
          // 
          if (i==0 && ( c=="-" || c=="+")) {
             //do nothing
          }
          else 
          j = ++j;
        } 
	if (c==".") decimalCount++;
    }

    if (j>0)
        return false;
    else if (decimalCount>1) 
    	return false;
    else
        // All characters are numbers.
        return true;
}



// isSignedInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if all characters are numbers; 
// first character is allowed to be + or - as well.
//
// Does not accept floating point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
//
// EXAMPLE FUNCTION CALL:          RESULT:
// isSignedInteger ("5")           true 
// isSignedInteger ("")            defaultEmptyOK
// isSignedInteger ("-5")          true
// isSignedInteger ("+5")          true
// isSignedInteger ("", false)     false
// isSignedInteger ("", true)      true

function isSignedInteger (s)

{   if (isEmpty(s)) 
       if (isSignedInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedInteger.arguments[1] == true);

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedInteger.arguments.length > 1)
            secondArg = isSignedInteger.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;    
        return (isInteger(s.substring(startPos, s.length), secondArg))
    }
}

// isSignedNumeric (STRING s [, BOOLEAN emptyOK])
// 
// Same as isSignedInteger, except for data types
// that allow decimals.

function isSignedNumeric (s)

{   if (isEmpty(s)) 
       if (isSignedNumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedNumeric.arguments[1] == true);

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedNumeric.arguments.length > 1)
            secondArg = isSignedNumeric.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;    
        return (isNumeric(s.substring(startPos, s.length), secondArg))
    }
}


// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is an integer >= 0.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isNonnegativeInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isNonnegativeInteger.arguments.length > 1)
        secondArg = isNonnegativeInteger.arguments[1];

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a number >= 0

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) >= 0) ) );
}

// isPhone returns true if string is a valid U.S.
// phone number.
//
// Only numbers are allowed.

function isPhone(s) {

    // First, check that there are 10 characters
    // in the string. If not, return false.
    
    if (s.length!=10) {
    	return false;
    }

    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false.
    
    var i;
    var j=0;
    
    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number.
        var c = s.charAt(i);

        if (!isDigit(c)) j = ++j;
    }

    if (j>0) {
        return false;
    }
    else {
        return true;
    }
}

// isSSN returns true if string is a valid U.S.
// Social Security number.
//
// Only numbers are allowed.

function isSSN(s) {

    // First, check that there are 9 characters
    // in the string. If not, return false.
    
    if (s.length!=9) {
    	return false;
    }

    // Search through string's characters one by one
    // until we find a non-numeric character.
    // When we do, return false.
    
    var i;
    var j=0;
    
    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number.
        var c = s.charAt(i);

        if (!isDigit(c)) j = ++j;
    }

    if (j>0) {
        return false;
    }
    else {
        return true;
    }
}

//beginning of date-validation functions

var daysInMonth = new Array(12);
daysInMonth[1] = 31;
daysInMonth[2] = 28;   // must programmatically check this 
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;

// isDate (STRING year, STRING month, STRING day)
//
// isDate returns true if string arguments year, month, and day 
// form a valid date.
// 

function isDate (year, month, day)
{   // catch invalid years (not 4-digit) and invalid months and days.
    //alert(month + "/" + day + "/" + year);
    //alert(" is day " + isDay(day, false));
    if (! (isYear(year, false) && isMonth(month, false) && isDay(day, false))) return false;

    // Explicitly change type to integer to make code work in both
    // JavaScript 1.1 and JavaScript 1.2.
    var intYear = parseInt(year);
    var intMonth = parseInt(month);
    var intDay = parseInt(day);

    // catch invalid days, except for February
    if (intDay > daysInMonth[intMonth]) return false; 

    if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) return false;

    return true;
}

// isYear (STRING s [, BOOLEAN emptyOK])
// 
// isYear returns true if string s is a valid 
// Year number.  Must be 4 digits only.
// 
// For Year 2000 compliance, you are advised
// to use 4-digit year numbers everywhere.
//
// And yes, this function is not Year 10000 compliant, but 
// because I am giving you 8003 years of advance notice,
// I don't feel very guilty about this ...
//
// For B.C. compliance, write your own function. ;->
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isYear (s)
{   if (isEmpty(s)) 
       if (isYear.arguments.length == 1) return defaultEmptyOK;
       else return (isYear.arguments[1] == true);
    if (!isNonnegativeInteger(s)) return false;
    return (s.length == 4);
}



// isMonth (STRING s [, BOOLEAN emptyOK])
// 
// isMonth returns true if string s is a valid 
// month number between 1 and 12.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isMonth (s)
{   if (isEmpty(s)) 
       if (isMonth.arguments.length == 1) return defaultEmptyOK;
       else return (isMonth.arguments[1] == true);
    return isIntegerInRange (s, 1, 12);
}



// isDay (STRING s [, BOOLEAN emptyOK])
// 
// isDay returns true if string s is a valid 
// day number between 1 and 31.
// 
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isDay (s)
{   if (isEmpty(s)) 
       if (isDay.arguments.length == 1) return defaultEmptyOK;
       else return (isDay.arguments[1] == true);   

    return isIntegerInRange (s, 1, 31);
}



// daysInFebruary (INTEGER year)
// 
// Given integer argument year,
// returns number of days in February of that year.

function daysInFebruary (year)
{   // February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}

// isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK])
// 
// isIntegerInRange returns true if string s is an integer 
// within the range of integer arguments a and b, inclusive.
// 
// For explanation of optional argument emptyOK,
// see comments of function isInteger.


function isIntegerInRange (s, a, b)
{   if (isEmpty(s)) 
       if (isIntegerInRange.arguments.length == 1) return defaultEmptyOK;
       else return (isIntegerInRange.arguments[1] == true);

    // Catch non-integer strings to avoid creating a NaN below,
    // which isn't available on JavaScript 1.0 for Windows.
    if (!isInteger(s, false)) return false;

    // Now, explicitly change the type to integer via parseInt
    // so that the comparison code below will work both on 
    // JavaScript 1.2 (which typechecks in equality comparisons)
    // and JavaScript 1.1 and before (which doesn't).
    var num = parseInt (s, 10);
    //alert("day is " + num + " s is " + s);
    return ((num >= a) && (num <= b));
}
