Click here to Skip to main content
Click here to Skip to main content

How can we adopt our application to use Jquery Validation Plugin

, 11 Jun 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
This Articles gives reader an idea on how Jquery Validation plugin works internally and also how can we extend the validation rules from our local application
This is an old version of the currently published article.

Introduction

I was going through the Jquery validation plugin code (Jquery.validate.js), and found it is very interesting and useful, I thought it would be beneficial if I share my findings here to people who are looking to have an understanding on how Jquery validation framework works.  This article contains internals of how Jquery validation plugin works, also contains how we can extend default rules to provide our own validation methods. 

Background

I was a bit of curious about how Jquery magically validates the input controls just after applying simple class rules like "required email, required url"  etc to the class attribute. So I spent couple of hours to understand how Jqquery.validate.js is written by experts. 

Using the code 

Download JqueryValidation.zip - 58.33 KB

To explain how jquery validation works, I took a simple html page, and added few controls on it, also applied few (existing) rules to see how the validation work. code below shows the validation.html code.

  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <script src="jquery-1.4.1.js"></script>
  <script type="text/javascript" src="jquery.validate.js"></script>
<style type="text/css">
* { font-family: Verdana; font-size: 96%; }
label { width: 10em; float: left; }
label.error { float: none; color: red; padding-left: .5em; vertical-align: top; }
p { clear: both; }
.submit { margin-left: 12em; }
em { font-weight: bold; padding-right: 1em; vertical-align: top; }
.class1 {color:red}
</style>
  <script>
      $.extend($.validator, { cool: function () { } });
      $(document).ready(function () {
          $("#commentForm").validate();
          $.validator.addMethod("PinCode", function () { }, "PIN code is not in valid format");
          

      });
  </script>
  
</head>
<body>
  

 <form class="cmxform" id="commentForm" method="get" action="">
 <fieldset>
   <legend>A simple comment form with submit validation and default messages</legend>
   <p>
     <label for="cname">Name</label>
     <em>*</em><input id="cname" name="name" size="25" class="class1 required"  minlength="2" />
   </p>
   <p>
     <label for="cemail">E-Mail</label>
     <em>*</em><input id="cemail" name="email" size="25"  class="required email" />
   </p>
   <p>
     <label for="curl">URL</label>
     <em>  </em><input id="curl" name="url" size="25"  class="required url" value="" />
   </p>
   <p>
     <label for="ccomment">Your comment</label>
     <em>*</em><textarea id="ccomment" name="comment" cols="22"  class="required"></textarea>
   </p>
   <p>
     <input class="submit" type="submit" value="Submit"/>
   </p>
 </fieldset>
 </form>
</body>
</html> 


   

How it works: In the above html file, classes applied required, required email, required url, etc, these minimal changes on input elements should be good enough to make them part of Jquery validation plugin framework.   

Heart of the Jquery validation framework is Jquery validator ($.validator), which contains all the necessary default settings to handle element's validation work. Jquery validator comes with the default settings when the we can call  validate() method on the form, validate() method takes options as input parameter and return validator. We can always send our own options which will extend the Jquery default validation settings. Below are the default settings with which validator comes with initially.

here are the default settings of the validtor. 

		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		validClass: "valid",
		errorElement: "label",
		focusInvalid: true,
		errorContainer: $( [] ),
		errorLabelContainer: $( [] ),
		onsubmit: true,
		ignore: [],
		ignoreTitle: false,
		onfocusin: function(element) {
			this.lastActive = element;
				
			// 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).hide();
			}
		},
		onfocusout: function(element) {
			if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
				this.element(element);
			}
		},
		onkeyup: function(element) {
			if ( element.name in this.submitted || element == this.lastElement ) {
				this.element(element);
			}
		},
		onclick: function(element) {
			// click on selects, radiobuttons and checkboxes
			if ( element.name in this.submitted )
				this.element(element);
			// or option elements, check parent select in that case
			else if (element.parentNode.name in this.submitted)
				this.element(element.parentNode)
		},
		highlight: function( element, errorClass, validClass ) {
			$(element).addClass(errorClass).removeClass(validClass);
		},
		unhighlight: function( element, errorClass, validClass ) {
			$(element).removeClass(errorClass).addClass(validClass);
		}


we can override any of these settings on our local page, for example take the event onfocusout i want to perform different logic other than what framework provides, then in our local page we can do some thing like below.
$.validator.defaults.onfocusout = function(element)
				{
  					//your custom code,
				},
Label will be used to display error messages, with 'error' has it's class, we can override this class in our application and provide, our own custom style, somewhat similar to what we have done in the above sample
label { width: 10em; float: left; }
label.error { float: none; color: red; padding-left: .5em; vertical-align: top; }

How rules are applied and validation takes place. 

 Jquery validator has rules object ($.validator.settings.rules), A rule in Jquery associates an element to validation method , and a method defines validation process how an element needs to be  validated. In Framework Rules are categorized at 4 levels,

  • class level 
  • Attribute level 
  • Meta Rules
  • static rules
For eg, Here are some of the classRuleSettings defined in the framwork.
classRuleSettings: {
		required: {required: true},
		email: {email: true},
		url: {url: true},
		date: {date: true},
		dateISO: {dateISO: true},
		dateDE: {dateDE: true},
		number: {number: true},
		numberDE: {numberDE: true},
		digits: {digits: true},
		creditcard: {creditcard: true}
	},

Rules preparation for an element, 

To get the rules applied on an element, Jquery first gets the value of class attribute for eg consider in our sample email element,  

1. is having the "required email" as class value, 

2. it splits the value returned by the class attribute using delimeter ' ', in our case we get two values required, email

3. For each value (required,email), it gets the mapping from classRuleSettings and prepares the validation rule for the element, here the validation rule is {required:true,email:true}. For each value in the rule like required, email etc framework has got methods defined in the $.validator.Methods, a list of methods describes how an element needs to be validated based on the rules assigned to it. Here are the some of framework validator methods, MinLength, MaxLength, rangelength, min, max, range, url, date, dateISO, number, digits, creditcard etc  

4. After class level rules are created, it iterates through other attributes of the input element (like minlengh, maxlength) etc and prepares similar kind of rule object like above {required:true, minlength=2} , and combines both the rules. It works in the similar way for meta, static rules also. 

5. once the rules preparation is done, it goes through the validation Methods ($.validator.Methods) list and calls the appropriate method based on the rule association. In the above case three validation methods will be called, required, email, minlength, (<input name="cname" id="cname" class="required email" minlength=2 />) here is how code for methods look like in the validation framework.  

$.validator.Methods{

  required: function(value, element, param) {
			// check if dependency is met
			if ( !this.depend(param, element) )
				return "dependency-mismatch";
			switch( element.nodeName.toLowerCase() ) {
			case 'select':
				// could be an array for select-multiple or a string, both are fine this way
				var val = $(element).val();
				return val && val.length > 0;
			case 'input':
				if ( this.checkable(element) )
					return this.getLength(value, element) > 0;
			default:
				return $.trim(value).length > 0;
			}
		},
  email: function(value, element) {
			// contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
			return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
		},
	
}

What if the framework provided validation methods are not sufficient: 

how do we add our own validation mechanism/method?, well, framework provides a method called, $.validator.addMethod(name, method, Message) which adds a new validation method to Methods list. Here name is the name of the validation method, method is the validation process, and Message  is validation failure message.  In the above given sample, I have added PINCode validation method,which is not part of the framework. For simplicity method(Pin code) always returns false, to kick the validation, and the validation message will be displayed. 

 Framework has default message settings, for each kind of validation failure, for eg below when required validation failes it displays "This field is required". 

messages: {
		required: "This field is required.",
		remote: "Please fix this field.",
		email: "Please enter a valid email address.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date (ISO).",
		number: "Please enter a valid number.",
		digits: "Please enter only digits.",
		creditcard: "Please enter a valid credit card number.",
		equalTo: "Please enter the same value again.",
		accept: "Please enter a value with a valid extension.",
		maxlength: $.validator.format("Please enter no more than {0} characters."),
		minlength: $.validator.format("Please enter at least {0} characters."),
		rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
		range: $.validator.format("Please enter a value between {0} and {1}."),
		max: $.validator.format("Please enter a value less than or equal to {0}."),
		min: $.validator.format("Please enter a value greater than or equal to {0}.")
	},

if we want to display our own custom messages then,  here is how we can override every message in our local web application. $.validator.messages.required ="My Custom message";  

When we click on the submit button, below code picks up

		this.submit( function( event ) {
				if ( validator.settings.debug )
					// prevent form submit to be able to see console output
					event.preventDefault();
					
				function handle() {
					if ( validator.settings.submitHandler ) {
						if (validator.submitButton) {
							// insert a hidden input as a replacement for the missing submit button
							var hidden = $("<input type="hidden" />").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
						}
						validator.settings.submitHandler.call( validator, validator.currentForm );
						if (validator.submitButton) {
							// and clean up afterwards; thanks to no-block-scope, hidden can be referenced
							hidden.remove();
						}
						return false;
					}
					return true;
				}
					
				// prevent submit for invalid forms or custom submit handlers
				if ( validator.cancelSubmit ) {
					validator.cancelSubmit = false;
					return handle();
				}
				if ( validator.form() ) {
					if ( validator.pendingRequest ) {
						validator.formSubmitted = true;
						return false;
					}
					return handle();
				} else {
					validator.focusInvalid();
					return false;
				}
			}

in the above code, validator.form(), does the form validation element by element and accumulates the errorList, and finally $.validator.ShowErrors() method will display the errors on the page. 

 How do we do conditional validation: Remember while calling framework validate() (which returns the validator), we can pass in options as input parameter. Here I have written a dependency function handler to do conditinal required check. Here I am applying condition validation on Url, which says, Url is required only when the value in email is empty (ofcourse it doesn't make sense to have this kind of dependency, but to demo the options input parameter i did so.)

$("#commentForm").validate(
          {
              rules:
          {
              url:
          {
              required: function () {
                  
                  return $("#cemail").val().length === 0;
              }
          }
          }
          }

          );
now in the above code Url is required only when email is empty, internally jquery uses extend()  to extend our own custom provided rules with the default settings of the validator. Below is the code settings are extended with our default options sent as input parameters.
$.validator = function( options, form ) {
	this.settings = $.extend( {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};

Points of Interest 

  1. Jquery validation framework hides the lot of complex logic, and gives the user flexibility to specify rules in a simple manner. 
  2. It is highly extensible, we can override existing or add Rules/validation methods.
  3. We can have individual teams write their own validation methods and hook them into existing framework, that is how we can separate the concerns also.    
  4. Error messages can be customized local to page.  

Disclaimer

This article uses a sample, which is not for direct production deployment. This is to give the reader an idea on how Jquery works and how we can use it in our local web application, it is individual responsibility to follow the necessary best practices while implementing the Model Binding.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

RamuSangabathula
Architect
India India
I have around 9 years of experience in Microsoft technologies, .Net 2.0,3.5, Asp.net MVC developed small to medium scale products using Silverlight 2.0, Asp.net Ajax technologie and Javascript frameworks.

Comments and Discussions


Discussions posted for the Published version of this article. Posting a message here will take you to the publicly available article in order to continue your conversation in public.
 
GeneralNice explanation, but i have some question here... Pinmemberkeonglah15-Jun-11 0:47 
GeneralMy vote of 5 PinmemberMonjurul Habib14-Jun-11 12:09 
GeneralMy vote of 5 PinmemberViral Upadhyay14-Jun-11 10:44 
GeneralMy 4! PinmemberRakeshMeena11-Jun-11 20:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 11 Jun 2011
Article Copyright 2011 by RamuSangabathula
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid