jQuery.fn.validate = function(rules,options) {
	var filters = {
		'email' : /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
		'url' : /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
		'ip' : /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
		'postalcode' : /^[ABCEGHJKLMNPRSTVXYabceghjklmnprstvxy]\d[A-Za-z] ?\d[A-Za-z]\d$/,
		'notempty' : /[^ ]/,
		'minlength' : function($field, params) { return $field.val().length >= params[0]; },
		'sameas' : function($field, params) { return $field.val() == jQuery(params[0]).val(); },
		'or' : function($field, params) { return filters['notempty'].test($field.val()) || filters['notempty'].test(jQuery(params[0]).val()); },
		'radio' : function($field, params) {
			var name = $field.attr('name');
			var r = false;
			var $radioButtons = jQuery('input[name=\''+name+'\'][type=\'radio\']');
			$radioButtons.each(function() {
				if(jQuery(this).is(':checked')) {
					r = true;
				}
			});
			return r;
		}
	};
	
	if(typeof(rules) == 'undefined') {
		rules = {};
	}
	
	if(typeof(options) == 'undefined') {
		options = {};
	}

	var $form = jQuery(this);
	
	$form.submit(function(e1) {
		var r = true;
		jQuery.each(rules, function(k, v) {
			var $k = jQuery(k);
			if(typeof(v) == 'string') {
				// regex rule
				if(typeof(filters[v]) == 'function') {
					//alert(k);
					if(v == 'radio') {
						if(!filters[v]($k)) {
							$k.addClass('invalid').removeClass('valid');
							r = false;
						}
						else {
							$k.addClass('valid').removeClass('invalid');
						}
					}
				}
				else {
					if (!filters[v].test($k.val())) {
						$k.addClass('invalid').removeClass('valid');
						r = false;
					}
					else {
						$k.addClass('valid').removeClass('invalid');
					}
				}
			}
			else if(typeof(v) == 'function') {}
			else if(typeof(v) == 'int') {}
			else if(typeof(v) == 'object') {
				var conditionRespected = true;
				var $classon = null;
				var error = null;
				
				if(typeof(v['classon']) != 'undefined') {
					$classon = jQuery(v['classon']);
				}
				
				if(typeof(v['error']) != 'undefined') {
					error = v['error'];
				}
				
				if(typeof(v['condition']) != 'undefined') {
					if(jQuery(v['condition'][0]).is(v['condition'][1])) {
					}
					else {
						conditionRespected = false;
						$k.addClass('valid').removeClass('invalid');
						if($classon != null) {
							$classon.addClass('valid').removeClass('invalid');
						}
					}
				}
				
				if(conditionRespected) {
					if(typeof(v['params']) == 'undefined') {
						// regex
						if (!filters[v['rule']].test($k.val())) {
							$k.addClass('invalid').removeClass('valid');
							$k.parent().children('span.error').replaceWith('');
							if($classon != null) {
								$classon.addClass('invalid').removeClass('valid');
							}
							if(error != null) {
								$k.after('<span class="error">'+error+'</span>');
							}
							r = false;
						}
						else {
							$k.addClass('valid').removeClass('invalid');
							$k.parent().children('span.error').replaceWith('');
							if($classon != null) {
								$classon.addClass('valid').removeClass('invalid');
							}
						}
					}
					else {
						if(!filters[v['rule']]($k, v['params'])) {
							$k.addClass('invalid').removeClass('valid');
							$k.parent().children('span.error').replaceWith('');
							if($classon != null) {
								$classon.addClass('invalid').removeClass('valid');
							}
							if(error != null) {
								$k.after('<span class="error">'+error+'</span>');
							}
							r = false;
						}
						else {
							$k.addClass('valid').removeClass('invalid');
							$k.parent().children('span.error').replaceWith('');
							if($classon != null) {
								$classon.addClass('valid').removeClass('invalid');
							}
						}
					}
				}
			}
		});
		if(r){
			if(typeof(options['submitHandler']) == 'function') {
				options['submitHandler'](this);
				r = false;
			}
		}
		return r;
	});
}

/*
			if(typeof(v) == 'object') {
				jQuery.each(v, function(k1, v1) {
					// code for functions
					var p2;
					switch(k1) {
						case 'minlength':
							p2 = v1;
							break;
						case 'sameas':
							p2 = $(v1).val();
							break;
						case 'or':
							p2 = $(v1).val();
							break;
					}
					
					if(!filters[k1]($k.val(), p2)) {
						$k.addClass('invalid').removeClass('valid');
						r = false;
					}
					else {
						$k.addClass('valid').removeClass('invalid');
					}
				});
			}
			else {
				if(typeof(filters[v]) == 'function') {
					//alert(k);
					if(v == 'radio') {
						if(!filters[v]($k.attr('name'))) {
							$k.addClass('invalid').removeClass('valid');
							r = false;
						}
						else {
							$k.addClass('valid').removeClass('invalid');
						}
					}
				}
				else {
					if (!filters[v].test($k.val())) {
						$k.addClass('invalid').removeClass('valid');
						r = false;
					}
					else {
						$k.addClass('valid').removeClass('invalid');
					}
				}
			}
*/