jQuery.fn.validates = function(fields){
	// Create HTML for form error
	$('body').append('<div id="formError"><span></span></div>');
	
	// Display error (with position and animation)
	showError = function(field, message){
		// Position form error, append message and display
		var position = field.offset();
		
		// Check for certain input types for extra padding
		if (field.hasClass('calendar')) {
			var padding = 25;
		} else if (field.attr('type') == 'file') {
			var padding = 40;
		} else {
			var padding = 5;
		}
		
		$('#formError').children('span').text(message).end().css({
			left: position.left + field.outerWidth() + padding,
			top: position.top - ($('#formError').outerHeight() / 2) + (field.outerHeight() / 2) 
		}).show();
		
		// Animate error fade away
		window.setTimeout(function(){
			$('#formError').animate({ opacity: 0 }, 1500);
		}, 1300);
	};
	
	// Validate form fields before submit
	$(this).bind('submit', function(){
		$('#formError').stop().css('opacity', 1).hide();
		
		// Iterate through rules and validate each field
		$.each(fields, function(fieldname){
			var field = $('#' + fieldname);

			if (!field.length || typeof validator[this.rule] != 'function') {
				return true;
			}
			
			if (!validator[this.rule](field.val())) {
				showError(field, this.message);
				return false;
			}
		});
		
		// Don't submit form if error is present
		if ($('#formError').is(':visible')) {
			return false;
		}
	});
};

// Validation methods - return true if validation passed
validator = {
	notEmpty: function(value){
		return value.match(/[^ ]/);
	},
	
	numeric: function(value){
		return this.notEmpty(value) && !value.match(/\D/);
	}
};
