// A utility function used internally that returns true if a string contains only whitespace characters.
function isBlank(s){
	for ( var i = 0; i < s.length; i++ ) {
		var c = s.charAt( i );
		if (( c != ' ' ) && ( c != '\n' ) && ( c != '\t' )) return false;
	}
	return true;
} // END isBlank function

// This internal function takes an element as the input parameter and returns its alias if there is any.
// If not, the actual element name is returned.
function displayName(e){
	// Check if the alias is null
	if ( ( e.alias == null ) || ( e.alias == "" ) || isBlank( e.alias ) ) {
		return e.name;
	} else {
		return e.alias;
	}
}

// External function that checks if any radio or checkbox choice is selected
function isSelected( f, name ) { 
	// Retrieve number of elements in array of radio or checkboxes
	var numElem = eval( 'f.' + name + '.length' );
	// Loop through boxes to see if they are checked
	for ( index = 0; index < numElem; index++ ) {
		if ( eval( 'f.' + name + '[index].checked' ) ) {
			// Return true if at least one box is checked
			return true
		}
	}
	// Return false if no box is checked
	return false;
}

// Set all checkbox/radio elements with the same name as being optional
function setAsOptional( f, name ) { 
	// Retrieve number of elements with the same name (checkboxes, radios)
	var numElem = eval( 'f.' + name + '.length' );
	// Loop through elements
	for ( index = 0; index < numElem; index++ ) {
		// Retrieve element
		var e = eval( 'f.' + name + '[index]' );
		// Set each element as being optional
		e.optional = true;
	}
}

// This is the main function that performs verification. It will be invoked from JavaScript on the form.
// Prior to calling this function, parameters can be set for each field to determine how it should be handled
// Options are : 	alias 		( name to be used in error message box )
//				eg.	this.document.forms[0].FirstName.alias = "First Name";
//	 	optional 	( the item is not required )
//				eg.	this.document.forms[0].FirstName.optional = true;
//		minlen		( the minimum number of characters for an entry )
//				eg.	this.document.forms[0].Description.minlen = 3;
//		maxlen		( the maximum number of characters for an entry )
//				eg.	this.document.forms[0].Description.maxlen = 80;
//
//		numeric		( the value should be numeric )
//				eg.	this.document.forms[0].Age.numeric = true;
//		 min		( the minimum value for the numeric field )
//				eg.	this.document.forms[0].Year.min = 1990;
//		 max		( the maximum value for the numeric field )
//				eg.	this.document.forms[0].Year.max = 2050;
//		relative		( the minimum or maximum value is relative to another field and not absolute)
//				eg.	this.document.forms[0].MaxAgeRequired.relative = "MinAgeRequired";
//
//		date		( the value should equate to a date )
//				eg.	this.document.forms[0].StartingWeek.date = true;
//		 day		( the date value should equate to a specific day of the week )
//				eg.	this.document.forms[0].StartingWeek.day = 1;       ( 0 = Sun, 1 = Mon, 2 = Tue, etc.)
//		priorTo		( the date value should be prior to a given date )
//				eg.	this.document.forms[0].StartingWeek.priorTo = "01/01/99"
//		laterThan	( the date value should be later than a given date )
//				eg.	this.document.forms[0].StartingWeek.laterThan = "01/01/98"
//
//		unique		( the field value should be unique and not found in the existing list)
//				eg.	this.document.forms[0].IDNumber.unique = "100&101&102&103";  ( existing IDs )
//		separator	( the separator used separate each value in the unique string )
//				eg.	this.document.forms[0].IDNumber.separator = "&";   ( "*" will not work )
//		caseCheck	( the unique value is case sensitive )
//				eg.	this.document.forms[0].IDNumber.caseCheck = true;
//
// ---	File Uploads         ---	File upload controls have unique names generated by Domino.
//				In order to check a file upload control create a text box with the name "_fileUpload"
//				add  "type = hidden " to the HTML attribute of the text box.
//				Make sure that the field has a default value so that it will not fail validation if the 
//				the _fileUpload 	is not optional. If the file passes validation then the value of the
//				_fileUpload field will be set to "Yes".
//				In your JavaScript on the page set the validation values for the upload control to the 
//				_fileUpload object.
//		optional 	( the file upload is not required )
//				eg.	this.document.forms[0]._fileUpload.optional = true;
//                              fileTypes	( the acceptable file extentions for an upload control separated by commas)
//				eg.	this.document.forms[0]._fileUpload.fileTypes = ".gif,.jpg,.htm,.html"  
// ---		Notes 	        ----
//				1) All Notes Keyword fields must use aliases in order for the HTML field to have a 'value'
//				eg.	Yes|Yes and/or No|N in a keyword selection list.

// " f " is the form object which is passed in from the invoking JavaScript on the form.
function verify( f ) {
	var msg;
	var empty_fields = "";
	var errors = "";
	var lastElementName = "";
	var currElementDisplayName = "";
	var lastElementDisplayName = "";
	var lastElementType = "";
	var valueChecked = false;

	// Loop through the elements of the elements of the form, looking for all text and textarea elements that 
	// don't have an "optional" property defined. Then, check for fields that are empty and make a list of 
	// them. Also, if any of these elements have a "min" or a "max" property defined, then verify that they are
	// numbers and that they are in the right range. Put together error messages for fields that are wrong.
	for ( var i = 0; i < f.length; i++) {
		var e = f.elements[ i ];
		// Retrieve the display name for the current element
		currElementDisplayName = displayName( e );
	                //alert ( e.name + " - Type : " + e.type );
		
		if ( (( e.type == "text" ) || ( e.type == "textarea") || ( e.type == "password")) && ( ! e.optional || e.value != "") ) {
			// check if the field is empty
			if ((( e.value == null ) || ( e.value == "" ) || isBlank( e.value )) && !e.optional ) {
				empty_fields += "\n                " + currElementDisplayName;
				continue;
			}
			// check for field length
			if ( e.maxlen != null ) {
				if ( e.value.length > e.maxlen )
					errors += "- The field "+currElementDisplayName+" can have no more than "+e.maxlen+" chars\n";
			}
			if ( e.minlen != null ) {
				if ( e.value.length < e.minlen )
					errors += "- The field "+currElementDisplayName+" can have no less than "+e.minlen+" chars\n";
			}
			// check for fields that should have a unique value
			// the e.unique value is a string of all existing values for the item
			// if the current value is found in the string then the item is a duplicate
			if ( e.unique != null ) {
				var sep = e.separator;			
				if ( sep == null ) 
					sep = ";";          // default separator to semicolon
				var valToCheck = e.value;
				var s = sep + e.unique + sep;
				if ( !e.checkCase ){		// convert to uppercase if not case sensitive		
					s = s.toUpperCase( );
					valToCheck = valToCheck.toUpperCase( );
				}
						
				if ( s.search( sep + valToCheck + sep ) != -1 )
					errors += "- The field " + currElementDisplayName + " must contain a unique value\n";
			}
			// check for fields that should be numeric
			if ( e.numeric || ( e.min != null ) || ( e.max != null )) {
				var v = Number(e.value);
				if ( isNaN( v ) || (( e.min != null ) && ( v < e.min )) || (( e.max != null ) && ( v > e.max ))) {
					errors += "- The field " + currElementDisplayName + " must be a number";
					if ( e.min != null && !e.relative)
						errors += " that is greater than " + e.min;
					if ( e.max != null && e.min != null  && e.relative == null )                             						errors += " and less than " + e.max;
					else if ( e.max != null && e.relative == null)
						errors += " that is less than " + e.max;
					else if ( e.min != null && e.relative != null )
						errors += " that is greater than the " + e.relative;
					else if ( e.max != null && e.relative != null )
						errors += " that is less than the " + e.relative;
					errors += "\n";
				}  // end "if isNaN( v )"
			}  // end "if e.numeric"
			if ( e.date ) {			// begin if date					
				var d = Date.parse( e.value );
								
				if ( d.toString( ) == "NaN" ){      // begin if valid date
					errors += "- The field " + currElementDisplayName + " must be a valid date\n";
				} else {
					var dat = new Date( d );	
					//dat_entered = e.value.replace('0','');	
					dat_entered = e.value;					 
					dat_array = dat_entered.split('/');	
					
					for (x = 0; x < dat_array.length; x++){
						if ( dat_array[x].charAt(0) == '0' )
							dat_array[x] = dat_array[x].charAt(1)
					}		
						
					if ( dat_array[0] < 1 || dat_array[0] > 12 )
						errors += "- The month value in " + currElementDisplayName + " is invalid\n";
						
					if ( dat.getDate() != dat_array[1])
						errors += "- The day value in " + currElementDisplayName + " is invalid\n";						
					
					if (  e.day != null ) {	// begin if day
						//alert( e.day );				
						var dayOfTheWeek = "Sunday";
						if ( e.day == 1 )
							dayOfTheWeek = "Monday";
						else if ( e.day == 2 )
							dayOfTheWeek = "Tuesday";
						else if ( e.day == 3 )
							dayOfTheWeek = "Wednesday";
						else if ( e.day == 4 )
							dayOfTheWeek = "Thursday";
						else if ( e.day == 5 )
							dayOfTheWeek = "Friday";
						else if ( e.day == 6 )
							dayOfTheWeek = "Saturday";
						
						if( dat.getDay( ) != e.day ){
							errors += "- The field " + currElementDisplayName + " must be a valid date";	
							errors += " which represents a " + dayOfTheWeek + "\n";
						}
					}      // end if day
					if ( e.priorTo != null ) {      // begin prior to
						var priorToDate = new Date( e.priorTo );

						if ( dat.getTime() > priorToDate.getTime() ) {   // check prior to
							errors += "- The date " + currElementDisplayName + " must be ";	
							errors += "prior to " + e.priorTo + "\n";
						}  // end check prior to
					}
					if ( e.laterThan != null ){				
						var laterThanDate = new Date( e.laterThan );

						if ( dat.getTime() < laterThanDate.getTime() ) {   // check later than
							errors += "- The date " + currElementDisplayName + " must be ";	
							errors += "later than " + e.laterThan + "\n";
						}  // end check later than
					}
				}   // end if valid date
			}    // end if date
		}  // end "if e.type == text"

		if (( e.type == "file") && ( !f._fileUpload.optional || e.value != "")) {	// begin "if e.type == "file"
			// check if the field is empty
			if ((( e.value == null ) || ( e.value == "" ) || isBlank( e.value )) && !f._fileUpload.optional ) {
				empty_fields += "\n                File Upload";
				continue;
			} else {
				//check for valid file type
				if ( f._fileUpload.fileTypes != null ){ 
					var fileTypes = "," + f._fileUpload.fileTypes;					
					var uploadFileType = e.value;
					var pos = uploadFileType.lastIndexOf(".");
					uploadFileType = uploadFileType.substring( pos, uploadFileType.length);
					uploadFileType = uploadFileType.toUpperCase( );

					var temp = "";
					var found = false;
					pos = fileTypes.indexOf(",");
					while ( pos > -1&& !found ) {
						temp = fileTypes.substring(0,pos);
						fileTypes = fileTypes.substring(pos + 1, fileTypes.length);
						fileTypes = fileTypes.toUpperCase( );
						if ( temp == uploadFileType )
							found = true;
						
						pos = fileTypes.indexOf(",");				
					}  //end while
					// last file type or only one file type given
					if ( !found ){	// begin "if not found"
						if ( fileTypes != uploadFileType ){					
							errors += "- The File Uploaded must be ";	
							errors += "of type " + f._fileUpload.fileTypes + "\n";
							found = true;
						}
					}	// end "if not found"
					if ( found ) 
						f._fileUpload.value = "Yes";

				} else {
					f._fileUpload.value = "Yes";
				} // end check for valid file types
			}  // end else "if e.type == "file"
		}
		if ( ( ( e.type == "select-one" ) || ( e.type == "select-multiple" ) ) && !e.optional ) {
			if ( e.selectedIndex == -1 ) 
				empty_fields += "\n                " + currElementDisplayName;
			else if ( e.options[e.selectedIndex].value == "" || isBlank(e.options[e.selectedIndex].value) )
				empty_fields += "\n                " + currElementDisplayName;
		} // end "if e.type == select-one"

		if (( lastElementType == "radio" || lastElementType == "checkbox") && lastElementName != e.name ) {
//alert( e.name + " - " + lastElementName );
			 if ( ! valueChecked )
				empty_fields += "\n                " + lastElementDisplayName;
			valueChecked = false;		
		}
		if ( ( e.type == "radio" ) || ( e.type == "checkbox") ) {
			if ( e.checked || e.optional ){
				valueChecked = true;
			}
		} // end "if e.type == radio"

		lastElementName = e.name;
		lastElementDisplayName = currElementDisplayName;
		lastElementType = e.type;
	}  // end " for i " loop

	// 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 ) {
		// auto submit the form unless the "noSubmit" option is set.
		if ( f.noSubmit == null ){
			window.document.forms[0].submit();
			return true;
		}
		else
			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\n";

	if ( empty_fields ) {
		msg += "-  The following required field(s) are empty:" + empty_fields + "\n";
		if ( errors ) msg += "\n";
	}

	msg += errors;
	alert ( msg );
	return false;
} // END verify function