/**
 * @author Dave Shepard
 * Form validation script. Add the class "formValidate" to any <form> tag and
 * the class "required" to any INPUT, SELECT, or TEXTAREA that is required. The
 * Form tag must have an ID value defined and the individual elements within the
 * form must have IDs defined as well. The IDs of the elements is not important,
 * but it is necessary for like comparison.
 * 
 * Validates against empty fields, email field formatting, and required checkboxes
 * (for terms and conditions and the like). Submit buttons will be disabled 
 * until all fields are valid.
 * 
 * Implementation:
 * <form action="formprocessor.php" method="post" class="formValidate" id="form_id">
 * <input type="text" class="required" />
 * 
 * Submit buttons will be disabled and have the "disabled" class assigned to them
 * when they are disabled. <input type="image" /> buttons will use a naming syntax
 * for the "src" attribute to display a "disabled" image.
 * 
 * <input type="image" /> Image "src" syntax:
 *     "imagename_i.gif" - Enabled (idle) image
 *     "imagename_d.gif" - Disabled image
 *     
 * For the image "src" syntax, the file name must stay the same except for the _i and
 * _d notations at the end of the file name. You may change file types (GIF/JPG/PNG)
 * between states if so desired.
 */

Event.observe(window,"load",function() {
	// Grab all forms to be validated
	$$('form.formValidate').each(function(theForm,ind) {
		// Set checkboxes to blur automatically on click - required for Internet 
		// Explorer compatability
		$$('#'+theForm.identify()+' input[type="checkbox"]').each(function(checks){
			checks.observe('focus', function(){
				this.blur();
			});
		});
		
		// Get all the required elements in the form
		var requiredElems = $$('#'+theForm.identify()+' input.required','#'+theForm.identify()+' textarea.required','#'+theForm.identify()+' select.required');

		// Parse through each required element in the form and assign the in-line
		// form validation check on each field.
		requiredElems.each(function(rE){
			// Make the exception for Internet Explorer based browsers to do the checkbox
			// check on change instead of blur.
			if (rE.type == "checkbox" && Prototype.Browser['IE'] == false) {
				rE.observe('change', function(){
					validateForm(theForm.identify(), requiredElems, rE.identify());
				});
			} else {
				rE.observe('blur', function(){
					validateForm(theForm.identify(), requiredElems, rE.identify());
				});
				// Add a special case to also validate TEXTAREA fields while the user
				// is typing in the field. This is to enable the submit button without
				// requiring a blur() action to happen when a user is typing a comment
				if(rE.nodeName == "TEXTAREA") {
					rE.observe('keyup',function(){
						validateForm(theForm.identify(), requiredElems, rE.identify());
					});
				}
			}
		})

		// Identify the submit button ID for use in the initial validation
		if(theForm.down('input[type="submit"]')) {
			submitBtn = theForm.down('input[type="submit"]').identify();
		} else if(theForm.down('input[type="image"]')) {
			submitBtn = theForm.down('input[type="image"]').identify();
		}
		
		// Probably not necessary, but this will prevent the form from being submitted
		// without validating first. This will interupt the submit of the form to run the
		// validation script first.
		// theForm.writeAttribute("onsubmit","return validateForm('"+theForm.identify()+"',"+requiredElems+",'"+submitBtn+"');");
		$(theForm).observe('submit',function(event){
			if(validateForm(this.identify(),requiredElems,submitBtn) == false){
				event.stop();
			}
		});

		// Run initial form validation on page load. This will disable the submit button,
		// but will not display any error messages in-line on the fields
		validateForm(theForm.identify(),requiredElems,theForm.identify());

	});
});


function validateForm(formID,requiredElems,thisElem) {
	// Identify the submit button element's ID
	if($(formID).down('input[type="submit"]')) {
		submitBtn = $(formID).down('input[type="submit"]').identify();
	} else if($(formID).down('input[type="image"]')) {
		submitBtn = $(formID).down('input[type="image"]').identify();
	}
	
	// Check if this is the initial run (thisElem is the same as formID)
	if($(thisElem) == $(formID)) {
		isInitial = true;
	} else {
		isInitial = false;
	}

	// Check if this is the onsubmit action (thisElem is the submit button/image)
	if($(submitBtn) == $(thisElem)) {
		isSubmit = true;
	} else {
		isSubmit = false;
	}

	// Validate the required fields
	requiredElems.each(function(rE){
		// Check if this is the current field
		if($(thisElem) == rE) {
			sameElem = true;
		} else {
			sameElem = false;
		}

		// Define default values for validation		
		valid = true;
		isEmail = false;

		// Check if this is a checkbox and validate based off of checked boolean
		if (rE.nodeName == "INPUT" && rE.type == "checkbox") {
			if (rE.checked) {
				valid = true;
			}
			else {
				valid = false;
			}
		}
		else {
			// Check if the input field is empty
			if (rE.value.blank() == true) {
				valid = false;
			}
			else {
				// Check if the input field is an email address and validate against proper formatting
				if ((rE.identify().toLowerCase().indexOf("email") != -1 ||
				rE.readAttribute("name").toLowerCase().indexOf("email") != -1 ||
				rE.className.toLowerCase().indexOf("email") != -1) &&
				rE.nodeName == "INPUT") {
					isEmail = true;
					if (!/^\w+([\+\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/.test(rE.value)) {
						valid = false;
					}
				}
			}
		}
		
		// Check to see if the error message should be shown
		if(isInitial == true) {
			// This is the initial run, do not show in-line error messages
			showErr = false;
		} else {
			if(isSubmit == true) {
				// This is the submit check of the form, show all in-line error messages
				showErr = true;
			} else {
				if(sameElem == true) {
					// This is the element the user just came from, show in-line error messages
					showErr = true;
				} else {
					// This is not the element the user just came from, do not show in-line error messages
					showErr = false;
				}
			}
		}
		
		// Check if the field failed validation
		if(valid == false) {
			// Add a class to the invalid field to check for full form validation
			rE.addClassName("invalidFormField");
			// Show errors if allowed to
			if(showErr == true) {
				// If this form is formatted in a list, assign the error class to the input's parent <li>
				if (rE.up()) {
					rE.up().addClassName('error');
				}
				// Create the error message if it does not exist already
				if(document.getElementById(rE.identify()+"_error") == null) {
					var errorMsg = document.createElement("SPAN");
						errorMsg.id = rE.identify()+"_error";
						errorMsg.className = "error";
						rE.parentNode.appendChild(errorMsg);
				}
				// If this is an email address, ask user to format email properly
				if (isEmail == true) {
					$(rE.identify() + "_error").update("Please make sure you enter a valid email (<em>user@domain.com</em>)");
				} else {
					// Check the form field type and provide errors appropriate to the field type
					if (rE.nodeName == "INPUT" || rE.nodeName == "TEXTAREA") {
						if (rE.readAttribute("type") == "checkbox") {
							// Checkbox error message
							$(rE.identify() + "_error").update("Please make sure you have agreed to the above terms");
						}
						else {
							// Text field error message
							$(rE.identify() + "_error").update("Please make sure you enter something for this field");
						}
					}
					if(rE.nodeName == "SELECT") {
						// Drop-down error message
						$(rE.identify() + "_error").update("Please make a choice for this field");
					}
				}
			}
		} else {
			// This field has passed validation, remove all error classes and error messages
			rE.removeClassName("invalidFormField");
			if (rE.up()) {
				rE.up().removeClassName('error');
			}
			if (document.getElementById(rE.identify() + "_error")) {
				$(rE.identify() + "_error").remove();
			}
		}
	}); // End requiredElems.each
	
	// Count the elements with the invalidFormField class in this form and validate against
	// the entire form to disable or enable the submit button.
	if($$('#'+formID+' .invalidFormField').length > 0) {
		$(submitBtn).disabled = true;
		$(submitBtn).addClassName('disabled');
		oldSrc = $(submitBtn).src;
		if(oldSrc.indexOf("_i.") != -1) {
			$(submitBtn).writeAttribute('src',oldSrc.replace("_i.","_d."));
		}
		return false;
	} else {
		$(submitBtn).disabled = false;
		$(submitBtn).removeClassName('disabled');
		oldSrc = $(submitBtn).src;
		$(submitBtn).writeAttribute('src',oldSrc.replace("_d.","_i."));
		return true;
	}
}



