<!--

/*
** Bluewire Media Pty Ltd
** Project Leader: Sarah Hyne
** Developer: Jake Pospischil
** FormValidation class & initialization script
** Instantiates FormValidation instances automatically on DomReady
*/

// instantiate validators on DomReady
window.addEvent("domready", function() {
	
	FormValidation.MakeValidations();
	
});

// formValidation class definition
var FormValidation = new Class({
	
	// formValidation parameters
	Implements: Options,
	options: {
		form: null
	},
	
	// formValidation constructor
	initialize: function(options) {
		this.setOptions(options);
		
		// find children with validation rules
		this.validatedChildren = new Array();
		FormValidation.FORM_ELEMENTS.each(function(elementType) {
			
			// get children of the form with validation instructions
			var formControls = options.form.getElements(elementType).filter(function(formControl) {
				var controlRel = formControl.getAttribute("rel");
				
				// test for validation rel tag and valid instructions
				var validated = (controlRel && controlRel.match(/^validate\[.+?\]$/i));
				
				// if instructions are found, set individual validation rules for the element and find element's label text
				if (validated) {
					
					formControl.rules = controlRel.replace(/^validate\[(.+?)\]$/i, "$1").split(",");
					formControl.controlName = (formControl.title)? formControl.title: FormValidation.UNKNOWN_FIELD;
					
				}
				
				return validated;
				
			});
			
			this.validatedChildren.extend(formControls);
			
		}.bind(this));
		
		// add onsubmit check listener to form
		options.form.addEvent("submit", function(event) {
			
			var errorList = new Element(FormValidation.ADVICE_WRAPPER_OUTER);
			this.validatedChildren.each(function(validatedChild) {
				
				validatedChild.rules.each(function(rule) {
					
					// add error text if rule conditions are not met
					if (FormValidation.RULES[rule] && !FormValidation.RULES[rule](validatedChild.value)) {
						new Element(FormValidation.ADVICE_WRAPPER_INNER).set("text", FormValidation.ADVICE[rule].replace(/^(.*?)\*(.*?)$/, "$1" + validatedChild.controlName + "$2")).inject(errorList);
					}
					
				});
				
			});
			
			// dispatch error event with details of any errors and stop submission
			var errorsPresent = errorList.getChildren().length > 0;
			if (errorsPresent) {
				options.form.fireEvent("invalidate", errorList);
				event.stop();
			}
			
		}.bind(this));
		
	}
	
});

// formValidation static creation method
FormValidation.MakeValidations = function() {
	
	// validation advice panel to display errors
	var advicePane = $(FormValidation.ADVICE_PANE_ID);
	var adviceContainer = $(FormValidation.ADVICE_CONTAINER_ID);
	if (adviceContainer) {
		var adviceFade = new Fx.Tween(adviceContainer, {
			property: "opacity",
			unit: "",
			link: "cancel",
			duration: FormValidation.ADVICE_FADE_DURATION,
			transition: Fx.Transitions.Quad.easeOut
		});
		adviceContainer.addEvent("click", function() {
			adviceFade.start(0).chain(function() {
				adviceContainer.setStyle("display", "none");				   
			});
		});
	}
	
	var forms = $(document.body).getElements("form");
	forms.each(function(form) {
		
		var validation = new FormValidation({
			form: form
		});
		
		// invalidation event listener to handle errors
		form.addEvent("invalidate", function(errors) {
			
			advicePane.empty();
			errors.inject(advicePane);
			adviceContainer.setStyle("display", "block");
			adviceFade.set(0);
			adviceFade.start(1);
			
		});
		
	});
	
}

// formValidation configuration
FormValidation.ADVICE_CONTAINER_ID = "validationErrors";
FormValidation.ADVICE_PANE_ID = "validationAdvice";
FormValidation.ADVICE_WRAPPER_OUTER = "ul";
FormValidation.ADVICE_WRAPPER_INNER = "li";
FormValidation.UNKNOWN_FIELD = "[unknown field]";
FormValidation.ADVICE_FADE_DURATION = 400;

// formValidation constant definitions (not used)
FormValidation.FORM_ELEMENTS = new Array("input", "select", "textarea");
FormValidation.VALIDATE_REL = "validate";
FormValidation.TYPE_REQUIRED = "required";
FormValidation.TYPE_NOWHITE = "nowhite";
FormValidation.TYPE_ALPHA = "alpha";
FormValidation.TYPE_NUMERIC = "numeric";
FormValidation.TYPE_ALPHANUMERIC = "alphanumeric";
FormValidation.TYPE_EMAIL = "email";
FormValidation.TYPE_PHONE = "phone";

// validation checks
FormValidation.RULES = {
	required: function(value) {
		return value.match(/.+/) != null;
	},
	nowhite: function(value) {
		return value.match(/^\S*$/) != null;
	},
	alpha: function(value) {
		return value.match(/^[a-zA-Z\s\-']*$/) != null;
	},
	numeric: function(value) {
		return value.match(/^[0-9\s]*$/) != null;
	},
	alphanumeric: function(value) {
		return value.match(/^[a-zA-Z0-9\s\-']*$/) != null;
	},
	email: function(value) {
		return value.match(/^([a-zA-Z0-9_!#\$%\*\/\?\|\^\{\}`~&'\+=\-\.]+@[a-zA-Z0-9\-]+(\.[a-zA-Z0-9\-]+){1,2})?$/) != null;
	},
	phone: function(value) {
		return value.match(/^((\d{2}\W?)?\d{4}\W?\d{4})?$/) != null;
	},
	mobile: function(value) {
		return value.match(/^(\d{4}\W?\d{3}\W?\d{3})?$/) != null;
	},
	postcode: function(value) {
		return value.match(/^(\d{4})?$/) != null;
	}
};

// validation error messages
FormValidation.ADVICE = {
	required: "The field '*' is required.",
	nowhite: "The field '*' may not contain spaces.",
	alpha: "The field '*' may contain only letters.",
	numeric: "The field '*' may contain only numbers.",
	alphanumeric: "The field '*' may contain only letters and numbers.",
	email: "The field '*' must be a valid email address.",
	phone: "The field '*' must be a valid Australian phone number.",
	mobile: "The field '*' must be a valid Australian mobile phone number.",
	postcode: "The field '*' must be a valid Australian postal code."
};

//-->