(function($) {
	$.fn.legit = function(options) {

		var rules = {
			required:	{ 
				selector: '.required', 	
				rule: function($el) { 
					return ($el.attr('type') != 'checkbox' && $el.val().length > 0) || $el.attr('checked'); 
				} 
			},
			email:		{ selector: '.email', 		rule: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i },
			date:		{ selector: '.date', 		rule: /^[0-3]?[0-9]\/[0123]?[0-9]\/[12][09][0-9][0-9]$/ }
		};

		var settings = {
			'refocus':			true,
			'invalidClass': 	'alert',
			'invalidSelector': 	null,
			'invalidCallback': 	null,
			'validCallback': 	null,
			'smother': 			false
		};

		if(options) {
			$.extend(settings, options);
		}

		return this.each(function() {
			
			var $this = $(this);

			$this.bind('submit', function(e) {

				if(settings.smother) {
					e.preventDefault();
				}
				
				var feedback = '', focus = false, tmpSelector;

				$this.find('input[type="file"], input[type="text"]:enabled, input[type="checkbox"]:enabled, select:enabled, textarea:enabled').each(function() {
					
					var $el = $(this), valid = true;

					for(var i in rules) {

						if($el.is(rules[i].selector)) {
							
							if(i != 'required' && $el.val().length == 0) {
								//the field is empty and only the required rule tests empty fields
								continue;
							}

							if(typeof rules[i].rule.test == 'function') {
								if(!rules[i].rule.test($el.val())) {
									valid = false;
								}
							}
							else if(typeof rules[i].rule == 'function' && !rules[i].rule($el)) {
								valid = false;
							}

						}

					}

					tmpSelector = false;
					if(settings.invalidSelector) {
						tmpSelector = settings.invalidSelector.replace('<<id>>', $el.attr('id')).replace('<<name>>', $el.attr('name'));
					}

					if(!valid) {
						
						if(settings.invalidClass) {
							if(tmpSelector) {
								$(tmpSelector).addClass(settings.invalidClass);
							}
							else {
								$el.addClass(settings.invalidClass);
							}
						}

						feedback += $el.attr('title') + "\n";
						if(!focus) focus = $el;
					}
					else {
						
						if(settings.invalidClass) {
							if(tmpSelector) {
								$(tmpSelector).removeClass(settings.invalidClass);
							}
							else {
								$el.removeClass(settings.invalidClass);
							}
						}
					}

				});

				if(feedback.length > 0) {

					if(settings.refocus) focus.focus();

					if(typeof settings.invalidCallback == 'function') {
						return settings.invalidCallback(feedback);
					}
					else {
						alert(feedback);
						return false;
					}
				}

				if(typeof settings.validCallback == 'function') {
					return settings.validCallback(feedback);
				}
				else {
					return true;
				}
			});
		});
	}
})(jQuery);

