
// <meta http-equiv="content-type" content="text/html; charset=utf-8">

//
// formvalidation.js
//
// Instructions for use:
//
// 1. Set up a form with the attribute 'onsubmit="return validate( this );"'.
// 2. List all required fields in a hidden form element named "required"
//
//    Ex: <input type="hidden" name="required" value="age,name,address">
//
// 3. For each required form field, set up a label with an id set
//    to "label_<fieldname>".
//
//    Ex: <label id="label_age" for="age">age:</label><input type="text" id="age" name="age" tabindex="0" />
//
// 4. Create a warning message with an specific id and mark it hidden
//
//    Ex: <p id="warning" style="visibility:hidden;">Please complete the fields marked in <span style="color:red">red</span> below before sending:</p>
//
// 5. Create a hidden form element with the id of that warning message element
//
//    Ex: <input type="hidden" name="required_warning" value="warning" />
//
// 6. [optional] For validating specific data fields, create a function "validateSpecific",
//    that returns an array of invalid field names or null when everything in the form is valid.
//		
//		function validateSpecific( submitform )
//		{
//			var ageValue = parseInt( submitform.age.value );
//			
//			if ( isNaN( ageValue ) ) return ["age"];
//
//			return null;	// everything valid!
//		}
//
// The form will not be submitted until the validate function (included the user-defined
// "validateSpecific" returns true.
//


var kWarningField = "warning";
var kSelectNoValue = "notselected";
var gMarked = [];  // array of elements marked in red

// 
gDebug = true;   // if this is set, alerts pop up on setup errors

// reset a marked label
function markLabelValid( el )
{
	el.style.color = "black";
	el.style.fontWeight = "normal";
}

// mark a label field invalid
function markLabelInvalid( el )
{
	el.style.color = "red";
	el.style.fontWeight = "bold";
}

// reset all marked label fields
function clearMarked()
{
	// reset the styles
	for ( var i = 0; i < gMarked.length; i++ ) {
		var id = gMarked[i];
		var el = document.getElementById( id );
		
		if ( el ) {
			markLabelValid( el );
		}				
	}
	
	gMarked = new Array();  // just wipe everything out by creating a new array!
}

// mark the label field for a given data field
function markLabelFor( elementName )
{
	var labelId = "label_" + elementName;
	var el = document.getElementById( labelId );
	
	if ( gDebug && !el ) {
		alert( "no label element for \"" + elementName + "\" (should be \"" + labelId + "\")" );
	}
	
	if ( el ) {
		markLabelInvalid( el );
		gMarked[gMarked.length] = labelId;
	}
}

// show the invalid field warning message
function displayWarning( submitform )
{
	var warnField, warningElem;
	
	warnField = submitform.required_warning.value;
	if ( warnField == "" ) warnField = kWarningField;
	
	var warnEl = document.getElementById( warnField );
	
	if ( warnEl ) {
		warnEl.style.visibility = "visible";			
	}
}

// validate a specific item, looking mainly for blank text fields or un-chosen select lists
function validateItem( item )
{
	// radio groups are weird - the form.field element is an *array* of radio buttons!!
	if ( typeof( item.tagName ) == "undefined" && typeof( item.length ) != "undefined" ) {
		var checked = false;
		for ( var i = 0; i < item.length; i++ ) {
			if ( item[i] && item[i].checked ) checked = true;
		}
		return checked;		// if one is checked, field is valid
	}

	// check other items based on their tag (INPUT, SELECT, TEXTAREA...)
	switch ( item.tagName ) {
	
		case "INPUT":
		
			switch ( item.type ) {
				
				case "text":
				case "password":
					if ( item.value == "" ) return false;
					break;
					
				default:
					break;
			}
			break;
			
		case "SELECT":
			if ( item.value == kSelectNoValue ) return false;
			break;
			
		case "TEXTAREA":
			if ( item.value == "" ) return false;
			break;
			
		default:
			return true;
			
	}
	
	return true;
}

// validate specific fields within a form, returning true when valid, false when not (and marking all invalid fields)
function validateFieldList( submitform, fieldlist )
{
	var valid = true;
	
	var requiredList = fieldlist.replace( / /g, "" );		// delete spaces!!
	
	if ( requiredList == "" ) return true; // no required fields ==> valid!
	
	var requiredArr = requiredList.split(",");
	
	for ( var i = 0; i < requiredArr.length; i++ ) {
		var el = submitform[ requiredArr[i] ];
		
		if ( gDebug && !el ) {
			alert( "no form element \"" + requiredArr[i] + "\"" );
		}
		
		if ( el && !validateItem( el ) ) {
			markLabelFor( requiredArr[i] );
			valid = false;
		}

	}
	
	return valid;
}

// validate a form, returning true when valid, false when not (and marking all invalid fields)
function validate( submitform )
{
	var valid = true;
	
	// get rid of all previously marked
	clearMarked();
	
	// iterate over the required fields
	var requiredList = submitform.required.value;
	
	valid = validateFieldList( submitform, requiredList );
	
	// form-specific validation
	if ( valid && typeof( validateSpecific ) != "undefined" ) {
		var invalidFields = validateSpecific( submitform );
		
		if ( invalidFields == null ) {
			valid = true;
		} else {
		
			for ( i = 0; i < invalidFields.length; i++ ) {
				var el = submitform[ invalidFields[i] ];
				
				if ( gDebug && !el ) {
					alert( "no form element \"" + invalidFields[i] + "\"" );
				}
				
				if ( el ) {
					markLabelFor( invalidFields[i] );
				}
			}

			valid = false;
		} 
	}
	
	if ( !valid ) displayWarning( submitform );
				
	return valid;
}

