// This code enhances jQuery validation plug-in 1.5.5 
// (http://bassistance.de/jquery-plugins/jquery-plugin-validation/)
// 
// Its purpuse is to change the validation plug-in so it reacts interactively,
// starting validation on keyup event instead of waiting for the user to leave
// the field first.
// 
(function($) {

// these functions allow to ignore given rules on specific events
$.extend($.fn, {
  allRules: function() {
    var element = this[0];
   var validator = $.data(element.form, 'validator');
   if (validator.settings.rules) {
     rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
   }
   return rules;
  },
  
  setRules: function(argument) {
    if (argument) {
     var element = this[0];
     var validator = $.data(element.form, 'validator');
     validator.settings.rules[element.name] = argument;
    }
    return element;
  }
});

$.extend( $.validator.defaults, {
  messages: {},
  groups: {},
  rules: {},
  errorClass: "error",
  validClass: "valid",
  errorElement: "label",
  focusInvalid: true,
  errorContainer: $( [] ),
  errorLabelContainer: $( [] ),
  onsubmit: true,
  ignore: [],
  ignoreTitle: false,
  onfocusin: function(element) {
    this.lastActive = element;
    
    // show hint on focus
    if ($.validator.focusStatus[element.id] == false) {
      $.validator.focusStatus[element.id] = true;
      var errorElement = $('#' + element.id + "_error");
      if (errorElement.length > 0 && errorElement.is(':hidden'))
        $.validator.showHint(element);
    }
    // /show hint on focus
     
    // hide error label and remove error class on focus if enabled
    if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
      this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
      this.errorsFor(element).removeClass().addClass("error hidden").html("");
    }
  },
  onfocusout: function(element) {  
    // setUnfocusedStyle(element);
    // positionFormElements(); 
    // hide hint on blur
    if ($.validator.focusStatus[element.id] == true) {
      $.validator.focusStatus[element.id] = false;
      $.validator.hideHint(element);
    }
    // /hide hint on blur
    
    if ( !this.checkable(element) ) {
      var ignoreRules = ['required'];
      // array copy
      var originalRules = $.extend(true, {}, $(element).allRules());
      $.each(ignoreRules, function(index, ruleName) {
        $(element).rules('remove', ruleName);
      });
      this.element(element);
      $(element).setRules(originalRules);
    }
  },
  onkeyup: function(element) {    
    var ignoreRules = ['required'];
    // array copy
    var originalRules = $.extend(true, {}, $(element).allRules());
    $.each(ignoreRules, function(index, ruleName) {
      $(element).rules('remove', ruleName);
    });
    this.element(element);
    $(element).setRules(originalRules);
  },
  onclick: function(element) {
     this.element(element);
  }
});

// this allows to show hint only when input field has a focus
$.validator.focusStatus = {};
$.validator.allFields = {};
$.validator.initWithoutNere = $.validator.prototype.init;
$.validator.prototype.init = function() {
  var errorElement;
  var hintElement;
  $.each(this.currentForm.elements, function(index, element) {
    errorElement = $('#' + element.id + "_error");
    hintElement = $('#' + element.id + "_hint");
    if (element.id != "") {
      $.validator.allFields[element.id] = true;
    }
    if (errorElement.length > 0 && hintElement.length > 0 && hintElement.html() != null && hintElement.html().strip() != "") {
      $.validator.focusStatus[element.id] = false;
      $.validator.hideHint(element);
    }
  });
  $.validator.initWithoutNere.apply(this);
};

// hook to the original defaultShowErrors
$.validator.defaultShowErrorsWithoutNere = $.validator.prototype.defaultShowErrors;
$.validator.prototype.defaultShowErrors = function() {
  $.validator.defaultShowErrorsWithoutNere.apply(this);
  $.validator.nereShowErrorsHook(this);
};

$.validator.nereShowErrorsHook = function(originalContext) {
  var errorElement;
  $.each(originalContext.currentForm.elements, function(index, element) {
    errorElement = $('#' + element.id + "_error");
    if (errorElement.length > 0) {
      if (errorElement.is(':hidden')) {
        $.validator.showHint(element);
      }
      else {
        $.validator.hideHint(element);
      }
    } 
  });
}

// hides hint element if present
$.validator.hideHint = function(element) {
  var hintElement = $('#' + element.id + "_hint");
  if (hintElement.length > 0) {
    hintElement.hide();
  }
}

// shows hint element if present and not empty
$.validator.showHint = function(element) {
  var hintElement = $('#' + element.id + "_hint");
  if (hintElement.length > 0 && hintElement.html() != null && hintElement.html().strip() != "" && $.validator.focusStatus[element.id]) {
    hintElement.show();
  }
}

})(jQuery);
 
