/***************************************************************
  jQuery.validate 1.5.2    2/5/2010
  Author: John Norton - jukebox42@gmail.com
  This version works best with jquery 1.4.1
 ***************************************************************/
(function($){
	$.jvalidateClass = { 
		defaults : {
			useSummary:		false,
			useStyles:		true,
			useTitles:		false,
			summaryStyle:	'validation-summary',
			messageStyle:	'validation-message',
			watermarkStyle:	'validation-watermark',
			summaryId:		'vsummary-',
			messageId:		'vmessage-',
			validationTag:	'ul',
			itemCallback:	function(){return;},
			formCallback:	function(){return;},
			onBlur: true,
			watermark: true,
			attach : 'top'
		},	
		init : function(options) {
			var x = $.extend($.jvalidateClass.defaults, options);
			c = 0;
			return this.each(function(i) {
				$f = $(this);
				var $x = $.extend($f.data, x, $f.data());
				$f.attr('jvalidate', i);
				$f.bind('submit', function(){return $.jvalidateClass.doValidation($(this));});
				if($x.watermark){
					$('input[watermark], textarea[watermark]', $f).each(function() {
						$t = $(this);
						$t.val($t.attr('watermark')).addClass($x.watermarkStyle).bind('focus', function() {
								$o = $(this);
								if($o.val() == $o.attr('watermark')) 
									$o.val('').removeClass($x.watermarkStyle);
							}).bind('blur', function() {
								if($o.val() == '') 
									$o.val($o.attr('watermark')).addClass($x.watermarkStyle);
							});
					});
				}
				if($x.onBlur){
					$.each($('input[validate]:checkbox, input[validate]:radio'), function() {
						$c = $(this);
						n = $c.attr('name');
						v = $c.attr('validate');
						t = $c.attr('title');
						$('input[name="'+$.jvalidateClass.escN(n)+'"]', $f).attr({validate: v, title: t});
					});
					$('input[validate], textarea[validate], select[validate]', $f).bind('blur', function(){return $.jvalidateClass.validateItem($(this));});
				}
			});
		},
		doValidation : function($f){
			r = true;
			n = $f.attr('jvalidate');
			$('#'+$f.data.summaryId+n).remove();
			$.each($('input[validate], textarea[validate], select[validate]', $f), function(){
				vo = $.jvalidateClass.validateItem($(this));
				if(!vo)
					r = false;
			});
			if(r)
				$f.data.formCallback();
			return r;
		},
		validateItem : function($o){
			$f = $o.parents('*[jvalidate]');
			f = $f.attr('jvalidate');
			vo = true;
			$o.removeClass('validation-passed, validation-failed');
			if($f.data.watermark && $o.attr('watermark') && $o.val() == $o.attr('watermark'))
				$o.val('').removeClass($f.data.watermarkStyle);	
			$('#'+$f.data.messageId+f+'-'+$.jvalidateClass.escN($o.attr('name'))).remove();
			var validators = [['empty', function($o){return $o.val()=='';}, 'Please enter some text in this field.'],
							  ['checked', function($o){return !$o.is(':checked');}, 'It is required that you check this check box.'],
							  ['alpha', function($o){return !$o.val().match(/^[a-zA-Z]+$/);}, 'Please use letter only. For example Sketchy.'],
							  ['decimal', function($o){return !$o.val().match(/^[0-9]+$/);}, 'Please use decimal numbers only. For example 42.'],
							  ['number', function($o){return !$o.val().match(/^[-]?([1-9]{1}[0-9]{0,}(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|\.[0-9]{1,2})$/);}, 'Please use numbers only. For example -4.2.'],
							  ['email', function($o){return !$o.val().match(/^\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/);}, 'Please enter a valid email address. For example john@somedomain.com.'],
							  ['phone', function($o){return !$o.val().match(/^[01]?[- .]?\(?(?!\d[1]{2})[2-9]\d{2}\)?[- .]?(?!\d[1]{2})\d{3}[- .]?\d{4}$/);}, 'Please enter a valid US/Canada phone number. For example (603) 555-5555.'],
							  ['postal', function($o){return !$o.val().match(/^\d{5}-\d{4}|\d{5}|[A-Z]\d[A-Z] \d[A-Z]\d$/);}, 'Please enter a valid US/Canada postal code. For example 03102.'],
							  ['date', function($o){return !$o.val().match(/^([0-1][0-9])\/([0-3][0-9])\/(\d{4})$/);}, 'Please enter a valid date. For example 07/03/1987.']];
			l = validators.length;
			if($o.is(':checkbox') && $o.attr('validate') != 'checked' ){ //validate multiple selections on checkbox/radiobutton groups
				a = $o.attr('validate');
				n = a.match(/.*min\[([\d]*)\].*/) ? a.match(/.*min\[([\d]*)\].*/)[1] : 0;
				m = a.match(/.*max\[([\d]*)\].*/) ? a.match(/.*max\[([\d]*)\].*/)[1] : 99999;
				t = $('input[name="'+$.jvalidateClass.escN($o.attr('name'))+'"]:checked', $f).size();
				vo = (t >= n && t <= m) ? vo : false;
				if(!vo)
					$.jvalidateClass.doReport($o, 'You have not met the selection requirements.');
			}else if($o.attr('validate').match(/regex\[([^\s]*)\]/)){ //create your own validator!!! regex[REGEX]
				x = $o.val().match($o.attr('validate').match(/regex\[([^\s]*)\]/)[1]);
				if(x==null){
					$.jvalidateClass.doReport($o, 'Please match the information specified.');
					vo = false;
				}
			}else{
				for(i=0;i<l;i++){
					if($.jvalidateClass.hasValidator($o, validators[i][0])&&validators[i][1]($o)){
						$.jvalidateClass.doReport($o, validators[i][2]);
						vo = false;
					}
				}
			}
			if($f.data.useStyles)
				$o.addClass((vo ? 'validation-passed' : 'validation-failed'));
			if(vo)
				$f.data.itemCallback;
			if($f.data.watermark && $o.attr('watermark') && $o.val() == '')
				$o.val($o.attr('watermark')).addClass($f.data.watermarkStyle);
			return vo;
		},
		doReport : function($o, m){
			$f = $o.parents('*[jvalidate]');
			if($o.is(':checkbox') || $o.is(':radio')){
				$c = $('input[name="'+$.jvalidateClass.escN($o.attr('name'))+'"]', $f);
				switch($f.data.attach){
					case 'top': case 'custom': $o = $c.first(); break;
					case 'bottom': $o = $c.last(); break;
					default: $o = $c.first(); break;
				}
			}
			if(!$f.data.useSummary)
				$.jvalidateClass.writeMessage($o, m, $f);
			else{
				$.jvalidateClass.writeSummary($o, m, $f);
			}
		},
		writeMessage : function($o, m){	
			o = '<'+$f.data.validationTag+' class="'+$f.data.messageStyle+'" id="'+$f.data.messageId+$f.attr('jvalidate')+'-'+$o.attr('name')+'">'+($f.data.validationTag=='ul' ? '<li>' : '')+($f.data.useTitles==true&&$o.attr('title') ? $o.attr('title') : m)+($f.data.validationTag=='ul' ? '</li>' : '')+'</'+$f.data.validationTag+'>';
			switch($f.data.attach){
				case 'top': return $o.before(o); break;
				case 'bottom': return $o.after(o); break;
				case 'custom': return $o.attr('attach') ? $($o.attr('attach')).first().prepend(o) : $o.before(o); break;
				default: return $($f.data.attach).first().prepend(o); break;
			}
		},
		writeSummary : function($o, m){
			f = $f.data.summaryId+$f.attr('jvalidate');
			if($('#'+f).size() < 1) { //if summary dosnt exist
				s = '<'+$f.data.validationTag+' class="'+$f.data.summaryStyle+'" id="'+f+'"></'+$f.data.validationTag+'>';
				switch($f.data.attach){
					case 'top': $f.prepend(s); break;
					case 'bottom': $f.append(s); break;
					case 'custom': $f.attr('attach') ? $($f.attr('attach')).first().prepend(s) : $f.prepend(s); break;
					default: $($f.data.attach).first().prepend(s); break;
				}
			}
			return $('#'+f).append('<'+($f.data.validationTag=='ul' ? 'li' : $f.data.validationTag)+' id="'+$f.data.messageId+$f.attr('jvalidate')+'-'+$o.attr('name')+'">'+($f.data.useTitles==true&&$o.attr('title') ? $o.attr('title') : m)+'</'+($f.data.validationTag=='ul' ? 'li' : $f.data.validationTag)+'>');
		},
		hasValidator : function($o, s){
			s = ' '+s+' ';
			v = ' '+$o.attr('validate')+' ';
			return (v.match(s) == null) ? false : v.match(s);
		},
		escN : function(n){
			a = new Array('#', ';', '&', ',', '.', '+', '*', '~', '\'', ':', '"', '!', '^', '$', '[', ']', '(', ')', '=', '>', '|', '/');
			l = a.length;
			for(i=0;i<l;i++){
				n = n.replace(a[i], '\\'+a[i]);
			}
			return n;
		}
	}
	$.fn.jvalidate = $.jvalidateClass.init;
})(jQuery);