/*
 * jQuery Form Validation plug-in version 2.0
 * Last Update : Sept 1, 2009
 *
 * @requires jQuery v 1.3.+
 * @name	formValidation
 *
 * @License : none
 *
 * Copyright (c) 2007 E-wave web design
 *   http://www.ewave.com.au/
 *
 * Description
 * Form Validation - test fields according to settings, display alerts and prevent form submition untill all restrictions satisfied.
 *
 * required - check that text field is not empty. checkbox/radio checked, and select val is not empty
 * equal - compare value to another fields (must be the same e.g. password)
 * diff - compare value to another fields (must be the diffrent e.g. second email)
 * mask - compre value to mask using reg exp
 *
 *  
 */
(function($) {
  //
  // plugin definition
  $.fn.formValidation = function(options) {
		//
    // iterate each matched element
    return this.each(function() {
			//
			// build main options before element iteration
			var o = $.extend({}, $.fn.formValidation.defaults, options);
			//
			// get extra options from form tag using data attribute
      o = $.extend({}, o, eval("("+$(this).attr('data')+")"));
				
			var form = $(this);
			form.data('active', false);

			form.submit( function () {
				form
				.data('valid', true)	// reset form validation status
				.data('active', true) // start validation test for each tag on change
				.find("input:not([type='submit'],[type='reset'],:button), select, textarea")
				.each(function() { //each tag
					var tag = $(this);
					
					var valid = validate(form, tag) && form.data('valid');
					form.data('valid', valid);
				});	// end each tag
								
//				console.log(o.onValidForm, typeof o.onValidForm == 'function', $.isFunction(o.onValidForm));
			
				if (!form.data('valid') && o.alert)
					alert(o.errAlert);
					
				if (form.data('valid') && $.isFunction(o.onValidForm))
	 				return o.onValidForm.call(this, form);
				
				return form.data('valid');
				
		}); // end form submit

//		remove error indications when click on reset form
			$("[type=reset]").click( function () {
					form.find('*').removeClass(o.errLabelClass).removeClass(o.errTagClass);
					form.find("[id^=err]").remove();														 	
			});
			
			form
			.find("input:not([type='submit'],[type='reset'],:button), select, textarea")
			.each(function() {	//each tag
				
				var tag = $(this);
				//
				// add data attribute to tag
				tag.data('metadata', eval("("+tag.attr('data')+")"));																															
				//
				// bind events to validation
				tag.bind('click change keyup focus blur',function(e){	if ( form.data('active'))	validate(form, tag);	});
				//
				// trigger event from target eq/neq tag to main tag
				if (tag.data('metadata') != undefined && tag.data('metadata').eq != undefined)
					$('#'+tag.data('metadata').eq).keyup(function(){tag.trigger('change')});
				if (tag.data('metadata') != undefined && tag.data('metadata').neq != undefined)
					$('#'+tag.data('metadata').neq).keyup(function(){tag.trigger('change')});
			}); //end each tag

			/************/
    });
  //
	// validate tag input
  function validate(form, obj) {
		//		
		// if no data attribute return (no validation rules defined for this tag)
		if (obj.data('metadata') == undefined) return true;
		
		if (!Required(obj)) {
			highlight(form, obj, false, 'errRequired');
			return false;
		} else if (!Mask(obj)) {
			highlight(form, obj, false, 'errMask');
			return false;
		} else if (!Equal(obj)) {
			highlight(form, obj, false, 'errEq');
			return false;
		} else if (!nEqual(obj)) {
			highlight(form, obj, false, 'errNeq');
			return false;
		} else // tag is valid remove error
			highlight(form, obj, true, '');		
		
		return true; 
	}
  //
	// check required rule
  function Required(obj) {
		
		var id = obj.attr('id');
		//
		//not required
		if (obj.data('metadata').required==undefined || obj.data('metadata').required!='true')
			return true;
		//
		// if required and not empty
		if (obj.val() != '' && !obj.is(':radio') && !obj.is(':checkbox'))
			return true;
		//
		// radio and checkbox
		var name = obj.attr('name');
		//
		// radio and ( at least one is ) checked
		if ($(':radio[name='+name+']:checked').length > 0)
			return true;
		//
		// checkbox and ( at least one is ) checked ()
		if ($(':checkbox[name='+name+']:checked').length > 0)
			return true;
			
		return false;
  }
  //
	// check mask rule
  function Mask(obj) {				
		// if empty
		if (obj.val() == '')	return true;
		//
		//	read mask name from input tag
		oMask = $.fn.formValidation.defaults[obj.data('metadata').mask];
		//
		// if no mask rule
		if (oMask == undefined) return true;
		//
		// test reg exp
		return oMask.test(obj.val());			
	}
  //
	// check equal rule
  function Equal(obj) {
		//
		// compare values
		if (obj.data('metadata').eq != undefined)	return ($('#'+obj.data('metadata').eq).val() == obj.val());
		else	
			return true;
  }
  //
	// check no equal rule
  function nEqual(obj) {
		//
		// compare values
		if (obj.data('metadata').neq != undefined)	return ($('#'+obj.data('metadata').neq).val() != obj.val());
		else
			return true;
  }
  //
	// mark invalid tag
  function highlight(form, obj, valid, type) {
		var name = obj.attr('name');
		obj = form.find('[name='+name+']:first');
		var id = obj.attr('id');
		//
		//if tag input is valid
		if (valid) {
			// remove all err indications
			//
			form.find('[name='+name+']').each(function(){ // radio and cb group handling
				var id = $(this).attr('id');
				$('label[for="'+id+'"]').removeClass($.fn.formValidation.defaults.errLabelClass);
				$(this).removeClass($.fn.formValidation.defaults.errTagClass)
				$("#err_"+id).remove();				
			});
		} else {
			// add err indications
			//
			// if already marked as error skip
			if ($("#err_"+id).length)
				$("#err_"+id).remove();
			//
			// get error msg according to err type
			if ((err = obj.data('metadata')[type]) == undefined) 
				err = $.fn.formValidation.defaults[type];
			//
			// create err label
			var errLbl = '<span class="' + $.fn.formValidation.defaults.errMsgClass + '" id="err_'+id+'">'+err+'</span>';
			// insert err label after (first) tag
			form.find('[name='+name+']:first').after(errLbl);
			//
			// mark single tag and group tags (radio, check box)
			form.find('[name='+name+']').each(function(n){
				var id = $(this).attr('id');
				$('label[for="'+id+'"]').addClass($.fn.formValidation.defaults.errLabelClass);
				$(this).addClass($.fn.formValidation.defaults.errTagClass);
			});
		}
  }
 };	
  //
  // plugin defaults
  //
  $.fn.formValidation.defaults = {
		version				: '2.0',
		//
		// callback
		// onValidForm		: function(f){alert('Form Validation completed successfully!');return true;},
		//
		//reg exp masks
//		email					:	/^([\w.])+\@(([\w])+\.)[a-zA-Z0-9]{2,}/,
		email					: /^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i,
		url						:	/^(http:\/\/)([\w]+\.){1,}[a-zA-Z]{2,4}\b/,
		phone					:	/^\+[0-9]{1,3}\.[0-9]{1,2}\.[0-9]{6,}$/,
		zip						:	/^[0-9]{4,6}$/,
		mobile				:	/^[0-9]+$/,
		numeric				:	/^[0-9]+$/,
		image					:	/[\w]+\.(gif|GIF|jpg|JPG|bmp|BMP|png|PNG|jpeg|JPG)$/,
		media					:	/[\w]+\.(avi|AVI|flv|FLV|mov|MOV|mp3|MP3|wmv|WMV|swf|SWF)$/,
		pdf						:	/[\w]+\.(pdf|PDF)$/,
		//
		//err handling
		errAlert			: "Please fill all required fields!",
		errMsgClass		:	'errorMsg',
		errTagClass		:	'errorTag',
		errLabelClass	:	'errorLabel',
		errRequired		: 'Required!',		
		errMask				: 'Invalid input!',		
		errEq					: 'Invalid Value!',		
		errNeq				: 'Invalid Value!'		
  }
//
// end of closure
//
})(jQuery);