
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;
}

function fieldIsBlank(e)
{
    return !e.value || e.value == "" || isBlank(e.value);
}

function fieldName(field)
{
    return field.longName ? field.longName : field.name;
}

function fieldsMatch(field1, field2, msg, invert)
{
    compare = (field1.value != field2.value);
    if (invert) {
	compare = !compare;
	if (!msg)
	    msg = "The " + fieldName(field1) + " and " + fieldName(field2) +
		" fields should not match";
    }
    if (compare) {
	alert(msg ? msg : "The " + fieldName(field1) + " fields don't match");
	field1.value = "";
	field2.value = "";
	field1.focus();
	field1.select();
	return false;
    }
    return true;
}

function fieldsDiffer(field1, field2, msg)
{
    return fieldsMatch(field1, field2, msg, true);
}

function fieldValidate(f, val, msg)
{
    if ((!val && isBlank(f.value)) || (val && f.value.indexOf(val) == -1)) {
	alert(msg ? msg : "Please enter your " + fieldName(f));
	f.focus();
	f.select();
	return false;
    }
    return true;
}

function fieldLengthIsValid(f, min, max, msg)
{
    if ((min && (f.value.length < min)) || (max && (f.value.length > max))) {
	if (!msg) {
	    msg = "The " + fieldName(f) + " field must contain ";
	    if (min)
		msg += "at least " + min;
	    if (max)
		msg += (min ? " and " : "") + "at most " + max;
	    msg += " characters.\n";
	}
	alert(msg);
	f.focus();
	f.select();
	return false;
    }
    return true;
}

function validateSelect(sel, optStart, selOther, otherField, msg)
{
    var ok = false;
    if (sel.selectedIndex >= optStart && sel.selectedIndex < sel.length) {
	if (selOther && otherField &&
		sel.options[sel.selectedIndex].value == selOther)
	    ok = !isBlank(otherField.value);
	else
	    ok = true;
    }
    if (!ok)
	alert(msg ? msg : "Please select your " + fieldName(sel));
    return ok;
}

function formValidate(form)
{
    var msg;
    var empty_fields = "";
    var errors = "";
    var focusField = null;

    // Loop through the elements of the form, looking for all select, text
    // and textarea elements that don't have an "optional" property defined.
    // For select types, optStart should point to first index in options array
    // that indicates a choice (usually 1); if there is a related "other" field,
    // optOther should contain value that indicates the "other" choice and
    // otherField should point to the linked field.
    //
    // Then, check for fields that are empty and make a list of them.
    // Also, if any of these elements have a "min" or "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 < form.length; i++) {
	var e = form.elements[i];
	if ((e.type == "select-one") && e.optStart) {
	    if (e.otherField)
		e.otherField.optional = true;
	    if (e.selectedIndex >= e.optStart && e.selectedIndex < e.length) {
		if (e.otherField
		  && ((!e.optOther ||
		    	(e.options[e.selectedIndex].value == e.optOther))
		  && isBlank(e.otherField.value)))
		    empty_fields += "\n    --    " + fieldName(e.otherField);
	    } else if (!e.optional)
		empty_fields += "\n    --    " + fieldName(e);
	}
	if ((e.type == "text") || (e.type == "textarea") ||
		(e.type == "password")) {
	    // First, check if the field is empty
	    if (!e.optional && (!e.value || (e.value == "") || isBlank(e.value))) {
		empty_fields += "\n    --    " + fieldName(e);
		if (!focusField)
		    focusField = e;
	    }

	    // Now, check for fields that are supposed to be numeric
	    else if (!isBlank(e.value) && (e.numeric || e.min || e.max)) {
		var v = parseFloat(e.value);
		if (isNaN(v) || (e.min && (v < e.min)) || (e.max && (v > e.max))) {
		    errors += "- The field " + fieldName(e) + " must be a number";
		    if (e.min)
			errors += " that is greater than " + e.min;
		    if (e.max)
			errors += (e.min ? " and" : " that is") +
			    " less than " + e.max;
		    errors += ".\n";
		    if (!focusField)
			focusField = e;
		}
	    }
	}
    }

    // Now, if there were any errors, display the messages and return false
    if (!empty_fields && !errors)
	return true;

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

    if (empty_fields) {
	msg += "- The following required field(s) are unset or empty:"
	    + empty_fields + "\n";
	if (errors)
	    msg += "\n";
    }
    msg += errors;
    alert(msg);
    if (focusField) {
	focusField.focus();
	focusField.select();
    }
    return false;
}
