// A utility function that returns true if a string contains only 
// whitespace characters.
function isBlank(s) {
	if((s == null) || (s == '') || (s.length == 0)) { return true; }    for(var i = 0; i < s.length; i++) {
        var c = s.charAt(i);
        if ((c != ' ') && (c != '\n') && (c != '\t')) return false;
    }
    return true;
} // isBlank()

// Removes excess spaces from beginning and end of string
// JavaScript 1.2 compliant code
function trim(val) {
	if((val.replace) && (val != null) && (val.length > 0))
		return val.replace(/^\s*(\b.*\b|)\s*$/, "$1");
		//return val.replace(/<BR>*$/gi, "$+ ");
	else
		return val;
} // trim()


function blnIsCapital(sChar) {
	// Returns true if character is a capital letter
	if(RegExp)
	{
		// Browser is JavaScript 1.2 compliant
		// Use faster implementation
		return (sChar.search(/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/) != -1);
	}
	else	
	{
		// use older javascript implementation
		if(sChar == 'A') { return true; }
		else if (sChar == 'B') { return true; }
		else if (sChar == 'C') { return true; }
		else if (sChar == 'D') { return true; }
		else if (sChar == 'E') { return true; }
		else if (sChar == 'F') { return true; }
		else if (sChar == 'G') { return true; }
		else if (sChar == 'H') { return true; }
		else if (sChar == 'I') { return true; }
		else if (sChar == 'J') { return true; }
		else if (sChar == 'K') { return true; }
		else if (sChar == 'L') { return true; }
		else if (sChar == 'M') { return true; }
		else if (sChar == 'N') { return true; }
		else if (sChar == 'O') { return true; }
		else if (sChar == 'P') { return true; }
		else if (sChar == 'Q') { return true; }
		else if (sChar == 'R') { return true; }
		else if (sChar == 'S') { return true; }
		else if (sChar == 'T') { return true; }
		else if (sChar == 'U') { return true; }
		else if (sChar == 'V') { return true; }
		else if (sChar == 'W') { return true; }
		else if (sChar == 'X') { return true; }
		else if (sChar == 'Y') { return true; }
		else if (sChar == 'Z') { return true; }
		else { return false; }
	}
} // blnIsCapital()

// Returns a user friendly description of the html elment name, s
// returns a newly formatted string which removes control prefix 
// and parses out hungarian (mixed case) notation into distinct words// Be sure to use user friendly HTML Form element names, // e.g. "txtEmailAddress" returns "Email Address"
function strDisplayName(s) {		// s - the form element name
	var sTrunc = '';
	// remove control name prefix
	var sPrefix = s.substring(0,3); 
	
	if(RegExp)
	{
		// Browser is JavaScript 1.2 compliant
		// Use faster implementation
		switch(s.substring(0,3))
		{
			case 'txt':
			case 'lst':
			case 'cbo':
			case 'ddl':
			case 'btn':
			case 'lbl':
			case 'opt':
			case 'grd':
			case 'cmd':			case 'btn':
				sTrunc = s.substring(3);
				break;
			default:
				sTrunc = s;
		}
	}
	else
	{
		// Use earlier & slower Javascript 1.1/1.0 based implementation
		if(sPrefix == 'txt') { sTrunc = s.substring(3);}
		else if(sPrefix == 'lst') { sTrunc = s.substring(3);}
		else if(sPrefix == 'cbo') { sTrunc = s.substring(3);}
		else if(sPrefix == 'ddl') { sTrunc = s.substring(3);}
		else if(sPrefix == 'btn') { sTrunc = s.substring(3);}		else if(sPrefix == 'lbl') { sTrunc = s.substring(3);}
		else if(sPrefix == 'opt') { sTrunc = s.substring(3);}
		else if(sPrefix == 'grd') { sTrunc = s.substring(3);}
		else if(sPrefix == 'cmd') { sTrunc = s.substring(3);}
		else { sTrunc = s;}
	}
	
	// parse hungarian notation to words
	var sEval = '', sNew = '';
	for (var i = 0; i < sTrunc.length; i++)
	{
		sEval  = sTrunc.charAt(i);
		if (blnIsCapital(sEval))
		{ sNew += ' ' + sEval; }
		else
		{	
			if (sEval != '_')
				sNew += sEval;	
			else
				sNew += ' '; // replace underscore with blank space	 
		}
	}
	return sNew;
}  // strDisplayName(s)

// Returns true if form element is a text entry type inputfunction isTextEntryInput(e) {
	// e - form element
	// common code procedure	var sType = e.type;
		sType = sType.toLowerCase();
		if ((sType == 'text') || 
        (sType == 'textarea') || 
        (sType == 'password'))  {
        return true;
    }
    else
		return false;    }  // isTextEntryInput()

// Returns true if the element is to accept only numeric entries
function isNumberInputField(e) {
	if(e == null) 		return false;
	else if((e.isNumber != null) && (e.isNumber == true))
		return true;
	else if(e.min != null)
		return true;
	else if(e.max != null)
		return true;
	else
		return false;		}  // isNumberInputField()
// Returns true if form element is a list selection typefunction isSelectList(e) {
	// e - form element
	var sType = e.type;
		sType = sType.toLowerCase();
	if ((sType == 'select-one') || 
        (sType == 'select-multiple'))  {
        return true;
    }
    else
		return false;    }  // isSelectList()

function setErrorFocus(f) {
	// set focus to the first form element
	// which contains a validation error    for(var i = 0; i < f.length; i++) {
        var e = f.elements[i];
                if(e.isError == true) {
			if(e.focus) {				e.focus();
				break;			}	        
        }    }} // setErrorFocus()

function isValidEmail(strValue) {
	if(isBlank(strValue))
		return true;	// assume it's an optional a field
		
	var iAtSymbolPos = -1; 
	var iDotPos = -1;

	// Check for absolute minimun length (minimum #@#.#)
	if(strValue.length < 5) 
		return false;

	// Check for @ symbol - note indexOf is zero based!
	iAtSymbolPos = strValue.indexOf('@');	

	if(iAtSymbolPos < 1)  
		return false;

	if(iAtSymbolPos > (strValue.length - 3)) 
		return false;
				
	// Check for at least one '.' after @ symbol
	iDotPos = strValue.indexOf('.',iAtSymbolPos + 1);
	
	if(iDotPos < 1 || (iDotPos == (strValue.length - 1)))
		return false;

	// See if email contains "untrimmed" whitespace characters...
	var iWhitespacePos = strValue.indexOf(' ');
	if(iWhitespacePos != -1 && (iWhitespacePos > 0 && iWhitespacePos < strValue.length - 1))
		return false;
		
	if(RegExp.test) {	
		// is js 1.2 compliant
		var reg = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
		return reg.test(strValue);
	}
	else
		return true;
}  // isValidEmail()


function isValidTime(value) {
	if(isBlank(value))
		return false;	// assume it's required a field

   var hasMeridian = false;
   var re = /^\d{1,2}[:]\d{2}([:]\d{2})?( [aApP][mM]?)?$/;
   if (!re.test(value)) { return false; }
   if (value.toLowerCase().indexOf("p") != -1) { hasMeridian = true; }
   if (value.toLowerCase().indexOf("a") != -1) { hasMeridian = true; }
   var values = value.split(':');
   if ( (parseFloat(values[0]) < 0) || (parseFloat(values[0]) > 23) ) { return false; }
   if (hasMeridian) {
      if ( (parseFloat(values[0]) < 1) || (parseFloat(values[0]) > 12) ) { return false; }
   }
   if ( (parseFloat(values[1]) < 0) || (parseFloat(values[1]) > 59) ) { return false; }
   if (values.length > 2) {
      if ( (parseFloat(values[2]) < 0) || (parseFloat(values[2]) > 59) ) { return false; }
   }
   return true;
}  // isValidTime()

function isValidPhoneNumber(phoneNo) { 
	// valid format: (###)###-####
	
	if(isBlank(phoneNo))
		return false;
	
	var phoneRE = /^\(\d\d\d\)\d\d\d-\d\d\d\d$/; 
 
	if(phoneNo.match) {
		// Is javaScript 1.2 compliant
		if (phoneNo.match(phoneRE))  
			return true; 
		else 
			return false; 
	}		
	else
		return true;			
}  // isValidPhoneNumber()


// This is the function that performs form verification. If it is invoked
// from the onSubmit() event handler. The onSubmit() event handler should // return whatever value this function returns.
function isValidForm(f) {	// f - the DOM form object
    var msg;
    var empty_fields = '';
    var errors = '';

    // Loop through the elements of the form, looking for all 
    // text, textarea, and select (select-one, select-multiple) elements that 
    // have the following properties set:
    //		"optional" - if set to false, then an entry is required
    //		"maxLength" - character count max for text input field element    //		"isNumber" - checks to see if it is a numeric value entered    //		"min"	   - checks if numeric field value is below the minimum value specified
    //		"max"	   - checks if numeric field value is above the maximum value specified	//		"isEmailAddress" - for a text input that accepts email addresses
	//		"isPhone"  - for a text input that accepts phone numbers ((###)###-####)	//		"isTime"   - for a text input that accepts time values (hh:mm AM/PM)	//
    // All of these properties are optional. For those elements you are interested in validating    // set the respective property equal to true.
    //     // A list of all errors is displayed in an alert dialog box.  
    // Returns true, if no validation errors occur, otheriwse false is returned.
            
    // For each form element...    for(var i = 0; i < f.length; i++) {
        var e = f.elements[i];
                e.isError = false;                if (isTextEntryInput(e)) {             // Is texbox/password/text-area element
             
            // Required entry check            if((e.optional == false) && isBlank(e.value)) {				empty_fields += '\n          ' + strDisplayName(e.name);				e.isError = true;
				continue;            }            ///// End: Required entry check
                        ///// Not blank - now perform a Character count check
            else if (e.maxLength != null) {				// see if the character count is within the prescribed limit				var eval = e.value;
				if((eval != null) && (eval.length > e.maxLength)) {
					errors += '\n- ' + 
                              strDisplayName(e.name) + 
                              ' must be less than ' + (e.maxLength + 1) + ' characters in length.';
					e.isError = true;                              					continue;
				}             }
			///// End: Character count check						
			///// Valid number check
			if(isNumberInputField(e)) {				var val = parseFloat(e.value);				
				// Is it a number?				if (isNaN(val)) {
					errors += '\n- ' + strDisplayName(e.name) + 
                              ' must be a number';					e.isError = true;                    continue;                              
				}				
				if((e.min != null) && (val < e.min)){					errors += '\n- ' + strDisplayName(e.name) + 
                              ' must be a number that is greater than ' + e.min;
                    e.isError = true;                    continue;          				}								if((e.max != null) && (val > e.max)){					errors += '\n- ' + strDisplayName(e.name) + 
                              ' must be a number that is less than ' + e.max;
                    e.isError = true;                    continue;          				}
							}
			///// End: Valid number check
            
                        ///// Valid email address format check
            if((e.isEmailAddress != null) && (e.isEmailAddress == true)) {
				if(!isValidEmail(e.value)) {					errors += '\n- ' + 
                              strDisplayName(e.name) + 
                              ' is an invalid email address.';					e.isError = true;                    continue;                              
				}            
            }
            ///// End: Valid email address format check
                                    ///// Valid time entry check
            if((e.isTime != null) && (e.isTime == true)) {
				if(!isValidTime(e.value)) {					errors += '\n- ' + 
                              strDisplayName(e.name) + 
                              ' is an invalid time.';					e.isError = true;                    continue;                              
				}            
            }
            ///// End: Valid time entry check
                        ///// Valid phone entry check
            if((e.isPhone != null) && (e.isPhone == true)) {
				if(!isValidPhoneNumber(e.value)) {					errors += '\n- ' + 
                              strDisplayName(e.name) + 
                              ' must be in a (###)###-#### format.';					e.isError = true;                    continue;                              
				}            
            }
            ///// End: Valid phone entry check
                    }  // is texbox/password/text-area element
        
        if (isSelectList(e) && 
             !e.optional && e.length > 0) {
			// Validate entry has been made in list box or combo box
			if (e.selectedIndex == -1 || isBlank(e.options[e.selectedIndex].text))
				empty_fields += '\n          ' + strDisplayName(e.name);				e.isError = true;				continue;
        }        
    }  // for each form element

    // Now, if there were any errors, display the messages, and
    // return false to prevent the form from being submitted. 
    // Otherwise return true.
    if (!empty_fields && !errors) return true;

    msg  = '______________________________________________________\n\n'
    msg += 'The form was not submitted because of the following error(s).\n';
    msg += 'Please correct these error(s) and re-submit.\n';
    msg += '______________________________________________________\n';

    if (empty_fields) {
        msg += '- The following required field(s) are empty:' 
                + empty_fields + '\n';
        //if (errors) msg += '\n';
    }
    msg += errors;
    alert(msg);	setErrorFocus(f);    
    
    return false;
} // isValidForm()