/////////////////////////////////////////////////////////////////////////
// form_validate_utilities.js
//
// This Javascript file contains utility functions that help validate 
// operator-entered form fields or strings from them.
//
/////////////////////////////////////////////////////////////////////////


var field_required = true   // Actually, a constant, but IE doesn't support const
var field_optional = false  // Actually, a constant, but IE doesn't support const

/////////////////////////////////////////////////////////////////////////

function valueof_dollar_field( field )
{
	return Number(field.value.replace( /[ $]/g, "" ));
}

/////////////////////////////////////////////////////////////////////////

function radiobutton_value( field ) {
	var the_value = "";
	for ( var i = 0; i < field.length; i++ )
		if ( field[i].checked ) {
			the_value = field[i].value;
			break;
		}
	return the_value;
}



/////////////////////////////////////////////////////////////////////////

function validate_radiobutton_field( field, message, is_required ) {

	for ( var i = 0; i < field.length; i++ ) {
		if ( field[i].checked ) {
			return true;
		}
	}		

	// Ignore is_required -- a radiobutton group *must* have a button checked.
	field[0].focus();
	alert( message );
	return false;

}

/////////////////////////////////////////////////////////////////////////

function trim( the_string ) {
	// trim() strips the leading and trailing blanks from the_string,
	// corrects multiple spaces internally, and returns the result.

	var string_length, return_string
	var leading_blanks  = /^ +/
	var trailing_blanks = / +$/
	var multiple_blanks = / +/g

	return_string = the_string
	
	// Strip the leading blanks from return_string.
	return_string = return_string.replace( leading_blanks, "" )

	// Strip the trailing blanks from return_string.
	return_string = return_string.replace( trailing_blanks, "" )

	// Replace all multiple blanks with singles.
	return_string = return_string.replace( multiple_blanks, " " )

	return return_string
}

/////////////////////////////////////////////////////////////////////////

function string_contains_valid_chars( the_string, valid_chars ) {
	// Returns true if the_string contains only characters in valid_chars, false otherwise.

	// Regular expression:  any char not in the string valid_chars.
	var invalid_chars_regexp = new RegExp( "[^" + valid_chars + "]" );
	
	return !invalid_chars_regexp.test( the_string );
}

/////////////////////////////////////////////////////////////////////////

var digits = "0123456789"

function is_valid_digit_string( the_string ) {
	// Returns true if the_string contains only decimal digits, false otherwise.
	
	return string_contains_valid_chars( the_string, digits )
}

/////////////////////////////////////////////////////////////////////////

function validate_generic_field( field, message, is_required ) {
	field.value = trim( field.value )
	
	// If the field is required, it must be non-empty.
	if ( is_required  &&  field.value.length == 0 ) {
		field.focus();
		alert( message );
		return false;
	}
	return true;
}


/////////////////////////////////////////////////////////////////////////

function validate_name_field( field, message, is_required ) {
	
	var reg_exp = /\W[a-z]/; // Find a non-letter followed by a lowercase letter.
	var index;
	
	var old_string = " " + field.value;
	var new_string = "";
	while ( index = old_string.search( reg_exp ), index != -1 ) {
		new_string += old_string.substr( 0, index ) + old_string.substr( index, 2 ).toUpperCase();
		old_string = old_string.substr( index + 2, 10000 );
	}
	new_string += old_string;
	
	// Lowercase the words 'And' and 'Or'.
	new_string = new_string.replace( / and /gi, ' and ' );
	new_string = new_string.replace( / or /gi, ' or ' );
		
	field.value = trim( new_string );
	
	// If the field is required, it must be non-empty.
	if ( is_required  && ( field.value.length == 0 || field.value == "Not Applicable" ) ) {
		field.focus();
		alert( message );
		return false;
	}
	return true;
}

/////////////////////////////////////////////////////////////////////////

// Some Iowa city names start with certain words that are often abbreviated.
// Find all the variants and replace them with the official forms.
var ft_regexp = /^(Ft |Ft. |Fort )/i;
var mt_regexp = /^(Mt |Mt. |Mount )/i;
var st_regexp = /^(St |St. |Saint )/i;
var ft_replace = "Fort "
var mt_replace = "Mount "
var st_replace = "St. "

// No Iowa city or school name contains a comma.
// Delete the comma and everything after it.
var comma_regexp = / *,.*$/;

// No Iowa city name ends in ' Iowa' or ' IA'.
// Strip it.
var iowa_regexp = /( Iowa| IA)$/i;

function validate_city_field( field, message, is_required ) {

	var new_string

	// First remove any decimal digits.
	field.value = field.value.replace( /[0-9]+/g, "" );
	
	// Next remove extra spaces and Title Case each word.
	validate_name_field( field, message, field_optional )

	// Next strip any comma and everything following.
	new_string = field.value;
	new_string = new_string.replace( comma_regexp, "" );
	
	// Next replace the bad starting words with the good ones.
	new_string = new_string.replace( ft_regexp, ft_replace )
	new_string = new_string.replace( mt_regexp, mt_replace )
	new_string = new_string.replace( st_regexp, st_replace )

	// Next remove any trailing 'Iowa' or 'IA'.
	new_string = new_string.replace( iowa_regexp, "" );
		
	field.value = new_string;
	
	// If the field is required, it must be non-empty.
	if ( is_required  &&  field.value.length == 0 ) {
		field.focus();
		alert( message );
		return false;
	}
	return true;
}

/////////////////////////////////////////////////////////////////////////
function validate_school_field( field, message ) {

	// Strip any comma and everything following.
	field.value = field.value.replace( comma_regexp, "" );

	return validate_name_field( field, message, field_required )
}

/////////////////////////////////////////////////////////////////////////

var iowa_zipcode_regexp = /^(50|51|52)/

function validate_zipcode_field( field, 
                                 message, 
                                 is_required, 
                                 must_be_in_iowa ) {

	is_valid = false
	field.value = trim( field.value )
	if ( must_be_in_iowa == null ) {
		must_be_in_iowa = false;
	}

	// If the field is required or non-empty, validate it.
	// I.e., it's valid if it's not required and is empty.
	if ( !is_required  &&  field.value.length == 0 ) 
		return true

	if ( field.value.length == 5 ) {
		// Expected format:  #####
		is_valid = is_valid_digit_string( field.value )
	}
	else if ( field.value.length == 10 ) {
		// Expected format:  #####-####
		is_valid =    is_valid_digit_string( field.value.substr( 0, 5 ) )
		           && ( field.value.charAt( 5 ) == '-' )
		           && is_valid_digit_string( field.value.substr( 6, 4 ) )
	}
	if ( !is_valid ) {
		field.focus();
		alert( message + "\nFormats: ##### or #####-####"  );
	}
	else if ( must_be_in_iowa && !iowa_zipcode_regexp.test( field.value ) )  {
		field.focus();
		alert( field.value + " is not an Iowa zip code." );
		is_valid = false;
	}

	return is_valid
}

/////////////////////////////////////////////////////////////////////////

var phone_spacers = /[ ().-]/g;
var default_eisef_area_code = "319";
var iowa_area_codes_regexp = /^\((319|515|563|641|712)\)/;

function validate_phone_number_field( field, 
                                      message, 
                                      is_required,
                                      must_be_in_iowa ) {

	if ( must_be_in_iowa == null ) {
		must_be_in_iowa = false;
	}

	// If the field is required or non-empty, validate it.
	// I.e., if it's not required, it must be empty or valid.
	if ( !is_required  &&  field.value.length == 0 ) 
		return true

	// First, copy the field string, remove the spacer characters,
	// and check that only decimal digits are left.
	
	var the_copy = field.value.replace( phone_spacers, "" )
	var good_field = is_valid_digit_string( the_copy )

	if ( good_field ) {
		if ( the_copy.length == 7 )
			// No area code -- prepend the default.
			the_copy = default_eisef_area_code + the_copy;
		else if ( the_copy.length == 10 )
			{ } // Phone number with area code.
		else // Wrong length for a US phone number.
			good_field = false;
	}

	if ( good_field ) {
		// Move the_copy back to the field, nicely formatting it: (###) ###-####
		field.value = "(" + the_copy.substr(0,3) + ") "
		              + the_copy.substr(3,3) + "-" + the_copy.substr(6,4);

		if ( must_be_in_iowa && !iowa_area_codes_regexp.test( field.value ) ) {
			field.focus();
			alert( field.value + " is not an Iowa phone number." );
			return false;
		}
	}
	else {
		field.focus();
		alert( message + "\nFormats: ###-#### or (###) ###-####" );
		return false;
	}
	return true;
}

/////////////////////////////////////////////////////////////////////////

var bad_email_chars = " ()<>,;:\\[]\"@"

function is_valid_email_half( the_string ) {
	// Returns true if the_string looks like a reasonable e-mail 
	// local address or domain, false otherwise.
	
	// First, the_string mustn't be null.
	if ( the_string.length < 1)
		return false
	
	// Second, see if the_string contains any bad_email_chars
	for ( i = 0; i < the_string.length; i++ ) {
		if ( bad_email_chars.indexOf( the_string.charAt( i ) ) != -1 )
			return  false
	}
	
	// Next ensure that period is not the first or last character.
	if ( the_string.charAt( 0 ) == '.'
	     || the_string.charAt( the_string.length - 1 ) == '.' )
		return false

	return true	
}


/////////////////////////////////////////////////////////////////////////

function validate_email_address_field( field, message, is_required ) {

	field.value = trim( field.value )
	
	// If the field is required or non-empty, validate it.
	// I.e., if it's not required, it must be empty or valid.
	if ( is_required  ||  field.value.length > 0 ) {
		split_address = field.value.split( '@' )
		if ( split_address.length != 2
		     || !is_valid_email_half( split_address[0] )
		     || !is_valid_email_half( split_address[1] ) ) {
			field.focus();
			alert( message );
			return false;
		}
	}
	return true;
}


/////////////////////////////////////////////////////////////////////////

function validate_url_field( field, message, is_required ) {
	// Returns true if the_string looks like a reasonable URL, false otherwise.

	var leading_http = /^http:/

	field.value = trim( field.value )
	
	// If the field is required or non-empty, validate it.
	// I.e., if it's not required, it must be empty or valid.
	if ( is_required  ||  field.value.length > 0 ) {
		
		// Strip a leading 'http://' from the URL for testing.
		string_to_test = field.value.replace( leading_http, "" );
		if ( !is_valid_email_half( string_to_test ) ) {
			field.focus();
			alert( message );
			return false;
		}
	}
	return true;
}


/////////////////////////////////////////////////////////////////////////

function validate_integer_field( field, message, is_required ) {

	field.value = trim( field.value );
	if ( field.value.length < 1  ||  field.value < 0 ) {
		field.focus();
		alert( message );
		return false;
	}
	
	field.value = Number(field.value);

	return true;
}


/////////////////////////////////////////////////////////////////////////

function validate_dollar_field( field, message, is_required ) {

	field.value = field.value.replace( /[ $]/g, "" );
	if ( field.value.length < 1  ||  !is_valid_digit_string( field.value ) )  {
		field.focus();
		alert( message );
		return false;
	}

	field.value = "$" + Number(field.value);

	return true;
}


/////////////////////////////////////////////////////////////////////////

function validate_select_field( field, no_selection_index, message, is_required ) {

	if ( field.selectedIndex == no_selection_index  &&  is_required ) {
		field.focus();
		alert( message );
		return false;
	}

	return true;
}

