michaelp0730
1/19/2015 - 6:30 PM

John Resig - Form Validation

// A function for validating all fields within a form.
// The form argument should be a reference to a form element
// The load argument should be a boolean referring to the fact that
// the validation function is being run on page load, versus dynamically

function validateForm(form, load) {

	var valid = true;

	// Go through all the field elements in the form
	// form.elements is an array of all fields in a form
	for (var i = 0; i < form.elements.length; i++) {

		// Hide any error messages, if they're being shown
		hideErrors(form.elements[i]);

		// Check to see if the field contains valid contents, or not
		if(! validateField(form.elements[i], load)) {
			valid = false;
		}
	}

	// Return false if a field does not have valid contents
	// true if all fields are valid
	return valid;
}

// Validate a single field's contents
function validateField(elem, load) {

	var errors [];

	// Go through all the possible validations techniques
	for (var name in errMsg) {
		// See if the field has the class specified by the error type
		var re = new RegExp("(^|\\s)" + name + "(\\s|$)");

		// Check to see if  the element has the class and that it passes the validation test
		if (re.test(elem.className) && !errMsg[name].test(elem, load)) {
			// If it fails the validation, add the error message to the list
			errors.push(errMsg[name].msg);
		}
	}

	// Show the error messages, if they exist
	if (errors.length) {
		showErrors(elem, errors);
	}

	// Return false if the field fails any of the validation routines
	return errors.length > 0;
}

// Hide any validation error messages that are currently shown
function hideErrors(elem) {
	// Find the next element after the current field
	var next = elem.nextSibling;

	// If the next element is a ul and has a class of errors
	if (next && next.nodeName == "UL" && next.className == "errors") {
		// Remove it (which is our means of 'hiding')
		elem.parentNode.removeChild(next);
	}
}

// Show a set of errors messages for a specific field within a form
function showErrors(elem, errors) {
	// Find the next element after the field
	var next = elem.nextSibling;

	// If the field isn't one of our special error-holders.
	if (next && (next.nodeName != "UL" || next.className != "errors")) {
		// We need to make one instead
		next = document.createElement("ul");
		next.className = "errors";

		// and then insert into the correct place in the DOM
		elem.parentNode.insertBefore(next, elem.nextSibling);
	}

	// Now that we have a reference to the error holder UL
	// we then loop through all the error messages
	for (var i = 0; i < errors.length; i++) {
		// create a new li wrapper for each
		var li = document.createElement("li");
		li.innerHTML = errors[i];

		// and insert it into the DOM
		next.appendChild(li);
	}
}

// Waiting Until a Form Is Submitted to Run the Form Validation Function
function watchForm(form) {
	// Watch the form for submission
	addEvent(form, 'submit', function() {
		// make sure that the form's contents validate correctly
		return validateForm(form);
	});
}

// Find the first form on the page
var form = document.getElementsByTagName("form")[0];

// and watch for when its submitted, to validate it
watchForm(form);


// Watching Fields for a Change Before Running Any Field Validation Functions
function watchFields(form) {
	// Go through all the field elements in the form
	for(var i = 0; i < form.elements.length; i++) {
		// attach a 'change' event handler (which watches for a user
        // to lose focus of an input element)
		addEvent(form.elements[i], 'change', function() {
			// Once the focus has been lost, re-validate the field
			return validateField(this);
		});
	}
}

// Locate the first form on the page
var form = document.getElementsByTagName("form")[0];

// Watch all the fields in the form for changes
watchFields(form);


// Performing Form Validation Upon Page Load
addEvent(window, "load", function() {
	// Find all the forms on the page
	var forms = document.getElementsByTagName("form");

	// Go through all the forms on the page
	for (var i = 0; i < forms.length; i++) {
		// Validate each of the forms, being sure to set the 'load' argument to
        // true, which stops certain, unnecessary, errors from appearing
        validateForm( forms[i], true );
	}
});