/* 
* jQuery Form Validation (v0.1)
* by Jonathan Chao
* July 16, 2009
*
* NOTE: This script requires jQuery to work. Developed with jQuery v1.3.2
*/

(function($) {
	var validationRules = function() {
		var rules = {
			required: {
			    test: function(val) { return (val) ? true : false; },
			    message: "Required field."
			},
			email: {
			    test: function(val) { return testRegExp(val, /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/); },
			    message: "Invalid e-mail address."
			},
			phone: {
			    test: function(val) { return testRegExp(val, /^((\+\d{1,3}(-| )?\(?\d\)?(-| )?\d{1,5})|(\(?\d{2,6}\)?))(-| )?(\d{3,4})(-| )?(\d{4})(( x| ext)\d{1,5}){0,1}$/); },
			    message: "Invalid phone number."
			},
			pwlength: {
				test: function(val) {
					return testRegExp(val, /^\w{5,}\w$/);
				},
				message: "Must have 6 or more characters."
			},
			pwcapletter: {
				test: function(val) {
					return testRegExp(val, /[A-Z]/);
				},
				message: "Must have 1 or more capital letter."
			},
			pwnumber: {
				test: function(val) {
					return testRegExp(val, /\d/);
				},
				message: "Must have 1 or more number."
			}
		}
		
		var testRegExp = function(val, pattern) {
			return pattern.test(val);
		}
		
		return {
			getRule: function(name) {
				return rules[name];
			}
		}
	}
	
	var Form = function(form) {
	    var fields = [];
	    form.find("input[validation], textarea[validation]").each(function() {
	        fields.push(new Field(this));
	    });
	    this.fields = fields;
	}
	
	Form.prototype = {
	    validate: function() {
	        for (field in this.fields) {
	            this.fields[field].validate();
	        }
	    },
	    isValid: function() {
	        for (field in this.fields) {
	            if (!this.fields[field].valid) {
	                return false;
	            }
	        }
	        return true;
	    }
	}
	
	var Field = function(field) {
	    this.field = $(field);
	    this.valid = false;
	    this.initialize();
	}
	
	Field.prototype = {
	    initialize: function() {
	        var obj             = this,
	            field           = obj.field,
   	            offset          = obj.field.offset().left + obj.field.attr("offsetWidth");
	            errorMessage    = $("<div></div>").addClass("error-wrap").css({ display: "inline", left: offset }).hide();

            obj.field.blur(function() { obj.validate(); });
	        obj.field.after(errorMessage);
   	    },
   	    validate: function() {
   	        var obj             = this,
   	            errorMessage    = obj.field.next(".error-wrap");
   	            types           = obj.field.attr("validation").split(" "),
   	            errors          = [];

   	        for (var type in types) {
   	            var rule = $.validationRules.getRule(types[type]);
   	            if (!rule.test(obj.field.val())) {
   	                errors.push(rule.message);
   	            }
   	        }
   	        
   	        if (errors.length) {
   	            obj.field.after(errorMessage.empty());
   	            for (var error in errors) {
   	                errorMessage.append("<p>" + errors[error] + "</p>");
   	            }
   	            obj.field.parent("div").addClass("error-row");
				var fieldMiddle = obj.field.offset().top + (obj.field.outerHeight() / 2);
				errorMessage.css({ top: fieldMiddle - (errorMessage.outerHeight() / 2) });
   	            this.valid = false;
   	        }
   	        else {
   	            obj.field.parent("div").removeClass("error-row");
   	            this.valid = true;
   	        }
   	        
   	        obj.field.focus(function() { if (errors.length) errorMessage.fadeIn(); });
   	        obj.field.blur(function() { errorMessage.fadeOut(); });
   	    }
	}
	
	$.fn.validate = function() {
	    var form = new Form($(this));
	    $(this).bind("submit", function(e) {
	        form.validate();
	        if (!form.isValid()) {
	            e.preventDefault();
	        }
	    });
	}
	
	$.validationRules = new validationRules();
})(jQuery);