  (function($){
    $.fn.formValidator = function(options) {
      return this.each(function() {
	    var $this = $(this);
        /*options = $.extend({
            'maxLength': 100,
			'align': 'right',
			'valign': 'bottom',
			'show': 'auto',
			'elCount': 'auto'
		}, options);*/
                
        $this.bind('keydown', function() {
           $elm = $(this) 
          
           typewatch(function () {
                triggerChange($elm);
           }, 500);

            
        });
          
        $this.bind('blur change', function(){
           $elm = $(this)        
           var isValid;
           
           $elm.addClass('form-field-state-loading');
           $elm.removeClass('form-field-state-success');
           $elm.removeClass('form-field-state-error');
           
           isValid = validateForm($elm);
           
           
           if(isValid) {
               $elm.addClass('form-field-state-success');
               $elm.removeClass('form-field-state-error');
           } else {
               $elm.removeClass('form-field-state-success');
               $elm.addClass('form-field-state-error');              
               
               if($elm.data('focus-on-fail')) {
                   window.setTimeout(function(){
                        focus($elm);
                   },10);
               }
               
        }
           
            $elm.removeClass('form-field-state-loading'); 
        });
        
        function validateForm($elm) {
           var valid = true;
           
           if($elm.data('required')) {
               if(!isFilled($elm)) {
                   return false;
               }
           }
           
            
           if($elm.data('min-length')) {
               if(!hasMinLength($elm, $elm.data('min-length'))) {
                   return false;
               }
           }
           
           if($elm.data('min-value')) {
               if(!hasMinValue($elm, $elm.data('min-value'))) {
                   return false;
               }
           }
           
            
           if($elm.data('valid-email')) {
               if(!isValidEmail($elm)) {
                   return false;
               }
           }
           
           if($elm.data('compared-element')) {
               if(!hasSameValue($elm)) {
                   return false;
               }
           }
           
           if($elm.data('custom-valid')) {
              
                if(!$elm.data('custom-valid')()) {
                    return false;
                };
            
            }
           
           return true;
        };
        
    
        
        function isFilled(elm) {
            return elm.val().length > 0;
        };
        
        function hasMinValue(elm, min) {
            return elm.val() >= min;
        };
        
        function hasMinLength(elm, min) {
            return elm.val().length >= min;
        };
        
        function hasSameValue(elm) {
           
            return elm.val() == elm.data('compared-element').val();
        };
        
        function isValidEmail(elm) 
        { 
             var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 
             return elm.val().match(re); 
        };
        
        function focus($elm){
           $elm.focus();
        };
        
        function triggerChange($elm){
           $elm.trigger('change');
        };
        
        var typewatch = (function(){
              var timer = 0;
              return function(callback, ms){
                clearTimeout (timer);
                timer = setTimeout(callback, ms);
              }  
        })();
				
	  });
    };

   

	
  })(jQuery);
  
  
  
    
