public
Created — forked from remi/README.markdown

Adds hooks to jQuery.validate's form/element validation methods (via trigger())

  • Download Gist
README.markdown
Markdown

jQuery Validate Hooks

If you're using ASP.NET MVC3, it uses jQuery Validate to do client-side validations. Instead of using jQuery Validate directly, however, it wraps it with its own jQuery plugin called jQuery.Validate.Unobtrusive. jQuery.Validate.Unobtrusive sets up jQuery Validate for you, behind the scenes, so you don't have an opportunity to customize your jQuery Validate settings at all!

We've been running into trouble with this when we've been doing our own custom client-side validations. We need a way to integrate with the build-in ASP.NET MVC3 validation so we can:

  • Find out when our form's client-side validation runs and do something custom, if it fails
  • Find out when a particular element's client-side validation runs and do something custom if it passes or fails

We might extend this to be able to hook into other things, like jQuery Validate's submitHandler (which allows you to override what happens when the form is valid and ready to be submitted).

Installation

<script type="text/javascript" src="jquery.validate.hooks.js"></script>

Usage

$(document).ready(function(){

  // we're assuming that this has already been run (which MVC3 does automatically)
  // $('form').validate();

  // running this overrides some jQuery Validate stuff so we can hook into its validations.
  // triggerElementValidationsOnFormValidation is optional and will fire off all of your 
  // element validations WHEN the form validation runs ... it requires jquery.validate.unobtrusive
  $('form').addTriggersToJqueryValidate().triggerElementValidationsOnFormValidation();

  // You can bind to events that the forms/elements trigger on validation
  $('form').bind('formValidation', function(event, element, result) {
    console.log(['validation ran for form:', element, 'and the result was:', result]);
  });

  // Or you can use the helper functions that we created for binding to these events
  $('form').formValidation(function(element, result) {
    console.log(['validation ran for form:', element, 'and the result was:', result]);
  });

  $('input.something').elementValidation(function(element, result) {
    console.log(['validation ran for element:', element, 'and the result was:', result]);
  });

  $('input#address').elementValidationSuccess(function(element) {
    console.log(['validations just ran for this element and it was valid!', element]);
  });

  $('input#address').elementValidAndInvalid(function(element) {
    console.log(['validations just ran for this element and it was valid!', element]);
  }, function(element){
    console.log(['validations just ran for this element and it was INVALID!', element]);
  });
});
jquery.validate.hooks.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
(function($) {
 
$.fn.addTriggersToJqueryValidate = function() {
// Loop thru the elements that we jQuery validate is attached to
// and return the loop, so jQuery function chaining will work.
return this.each(function(){
var form = $(this);
// Grab this element's validator object (if it has one)
var validator = form.data('validator');
// Only run this code if there's a validator associated with this element
if (! validator)
return;
// Only add these triggers to each element once
if (form.data('jQueryValidateTriggersAdded'))
return;
else
form.data('jQueryValidateTriggersAdded', true);
// Override the function that validates the whole form to trigger a
// formValidation event and either formValidationSuccess or formValidationError
var oldForm = validator.form;
validator.form = function() {
var result = oldForm.apply(this, arguments);
var form = this.currentForm;
$(form).trigger((result == true) ? 'formValidationSuccess' : 'formValidationError', form);
$(form).trigger('formValidation', [form, result]);
return result;
};
// Override the function that validates the whole element to trigger a
// elementValidation event and either elementValidationSuccess or elementValidationError
var oldElement = validator.element;
validator.element = function(element) {
var result = oldElement.apply(this, arguments);
$(element).trigger((result == true) ? 'elementValidationSuccess' : 'elementValidationError', element);
$(element).trigger('elementValidation', [element, result]);
return result;
};
});
};
/* Below here are helper methods for calling .bind() for you */
$.fn.extend({
// Wouldn't it be nice if, when the full form's validation runs, it triggers the
// element* validation events? Well, that's what this does!
//
// NOTE: This is VERY coupled with jquery.validation.unobtrusive and uses its
// element attributes to figure out which fields use validation and
// whether or not they're currently valid.
//
triggerElementValidationsOnFormValidation: function() {
return this.each(function(){
$(this).bind('formValidation', function(e, form, result){
$(form).find('*[data-val=true]').each(function(i, field){
if ($(field).hasClass('input-validation-error')) {
$(field).trigger('elementValidationError', field);
$(field).trigger('elementValidation', [field, false]);
} else {
$(field).trigger('elementValidationSuccess', field);
$(field).trigger('elementValidation', [field, true]);
}
});
});
});
},
formValidation: function(fn) {
return this.each(function(){
$(this).bind('formValidation', function(e, element, result){ fn(element, result); });
});
},
formValidationSuccess: function(fn) {
return this.each(function(){
$(this).bind('formValidationSuccess', function(e, element){ fn(element); });
});
},
formValidationError: function(fn) {
return this.each(function(){
$(this).bind('formValidationError', function(e, element){ fn(element); });
});
},
formValidAndInvalid: function(valid, invalid) {
return this.each(function(){
$(this).bind('formValidationSuccess', function(e, element){ valid(element); });
$(this).bind('formValidationError', function(e, element){ invalid(element); });
});
},
elementValidation: function(fn) {
return this.each(function(){
$(this).bind('elementValidation', function(e, element, result){ fn(element, result); });
});
},
elementValidationSuccess: function(fn) {
return this.each(function(){
$(this).bind('elementValidationSuccess', function(e, element){ fn(element); });
});
},
elementValidationError: function(fn) {
return this.each(function(){
$(this).bind('elementValidationError', function(e, element){ fn(element); });
});
},
elementValidAndInvalid: function(valid, invalid) {
return this.each(function(){
$(this).bind('elementValidationSuccess', function(e, element){ valid(element); });
$(this).bind('elementValidationError', function(e, element){ invalid(element); });
});
}
});
 
})(jQuery);

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.