JavaScript is an event-driven language and events are the heart of pretty much all web applications. You can broadly categorize events as browser events, form events, mouse events, and keyboard events. Even though you might not have realized it, you’ve already written some browser event-based code if you have used the ready() event handler. Functions that are bound to an event are referred to as event handlers:
$(document).ready(function () {
// your logic goes here
});
You used the ready() event handler to make sure all of the DOM elements are loaded, before executing your code. Undoubtedly, one of the most frequent task you will be performing with jQuery, is event handling.
As jQuery has evolved, there have been new ways to add and remove events to elements. Older versions of jQuery used bind(), live() and delegate(). In version 1.7, jQuery introduced the on() method, which replaces the bind(), live() and delegate() methods. However why do we need a new way of attaching event handlers? What was wrong with bind(), live() and delegate()? Let’s understand this with an example. Consider this piece of HTML markup:
Using jQuery bind()
$(function () {
$("#container a").bind("click", function () {
console.log("clicked");
});
});
When you are calling bind() , you are attaching an event handler to every single matched element in the selection, in our case every anchor element in the div ‘container’.
The same code can also be written using click() which is a shorthand way of writing bind().
$("#container a").click(function () {
console.log("clicked");
});
However by using the bind() version, you can assign one handler to multiple events. bind() also supports namespaced events (http://api.jquery.com/on/#event-names)
I am using v 1.6.4 for this example and have set up an example here at http://jsfiddle.net/jquerycookbook/pgywy0ue/.
Open this link in Google Chrome browser, press Ctrl+Shift+J (Cmd+Opt+J in Mac) to bring up the Console window and click on any anchor element inside the container.

As you click on the links, observe the click count increasing in the console every time the anchor element is clicked. However, if there were 100 anchors in the ‘container’ div, the bind() method would attach the event handler to all the 100 anchors! Similarly imagine a large table in which each row has an anchor element, all of them requiring a click handler. Using bind() here could lead to performance issues; if you are attaching an event handler over and over, and especially when dealing with large selections.
Another issue with the bind() method is that since it directly binds the event handlers to individual elements, it cannot bind these handlers to elements that are dynamically created at runtime.
So using the same example, if we were to dynamically add an anchor element to the div ‘container’ and click on it, what would happen? Let’s see this with an example. In the same code, I am using the clone() method to clone the anchor element and add it to the ‘container’ div at runtime.
$("#container a").bind("click", function () {
console.log("clicked");
$(this).clone().appendTo("#container");
});
I have set up an example here http://jsfiddle.net/jquerycookbook/pgywy0ue/1/. Open this link in Google Chrome browser, press Ctrl+Shift+J (Cmd+Opt+J in Mac) to bring up the Console window and click on the top two links to clone them and this is what you will see:

The count of the clicked message in the Console window increases every time you click the anchor. However now try clicking on these dynamically created anchors. You will see that the count does not increase. This is because the anchor does not respond to the click event, as when using bind(); your event handler functions are not associated with any new element that you add to the DOM.
Using unbind() removes event bindings created with bind().
Using jQuery live()
live() was introduced in jQuery 1.3 and its syntax is similar to that of bind(). All you have to do is replace bind() with live() to bind a handler to an event for all current and also future matching elements.
$(function () {
$("#container a").live("click", function () {
console.log("clicked");
});
});
live() implements event delegation. The handler bound to live() is not bound to the anchor element, as it may so appear. Instead live() binds a handler to the root of the DOM. So rather than attaching 100’s of event handlers to all the anchor elements in the ‘container’ div, using live() attaches just one event handler to the root document, along with the associated selector (in our case #container a) and event information.
When we click an anchor element, a click event is generated and passed to the <div>. Since the handler is not bound to the <div>, the event bubbles up to the DOM level and jQuery uses event.target to check if it matches the selector expression; in this case, #container a . It then executes the event with the context of the click source.
To sum it up, the live() method tells the browser to observe all clicks anywhere in the document. If the clicked element matches the #container a selector, then the handler is executed. This means you have one event handler instead of 100’s of them, meaning it's much faster and easier on the browser.
Try clicking on the dynamically generated anchor elements in the same clone example http://jsfiddle.net/jquerycookbook/pgywy0ue/2/, but this time using live() instead of bind() and observe how the count increases in the console, even for the dynamically generated anchors.
live() was introduced as a direct replacement for bind(). It did provide a good replacement where event handlers could work on existing, as well as new DOM elements and you could also avoid performance issues of binding event handlers to a large number of element. However there were some disadvantages to using live():
- The biggest disadvantage with the live() method was that the events had to propagate all the way up to the root document, before your handler functions are executed. In a large DOM tree, this could again lead to performance issues.
- event.StopPropagation was ineffective for stopping event handlers attached lower in the document from bubbling up the DOM tree, as the event had already propagated to the root.
- jQuery used the selector to retrieve elements, which in a large DOM could be time-consuming. It then discarded the selector after registering the event handler on the document, which was again a waste.
- live() was also limited in its chaining support. For example, you could not do $('#container').find('.something').live(..)
- jQuery v1.7 deprecated live() method and v1.9 removed it.
Using die() removes event handlers set with .live()
Using jQuery delegate()
To overcome these bottlenecks in live(); in jQuery 1.4.2 delegate() was introduced. delegate() used live() internally and worked for elements that was dynamically added later. Let us see the syntax:
$('#container').delegate('selector','event',function() {
//respond to the event
});
In our specific case, this would translate to the following:
$("#container").delegate('a', 'click', function () {
console.log("clicked");
$(this).clone().appendTo("#container");
});
delegate() allowed you to specify where the event listener will be located in the document. By doing so, events did not have to travel all the way up to the root document before the handler functions are invoked. Instead it attached the event handler to the div ‘container’ along with the selector and event information. You can see the delegate() function in action over here http://jsfiddle.net/jqueryhowto/hbSKw/3/
In the code above, you start by selecting an element (#container) that contains the elements that you want to add the event to. This is different from what you did while using bind(), where you directly selected the element that you want to add the event to. Next you call the delegate() function and pass the selector, the name of the event and a function that executes when the event is handled.
The main difference between live() and delegate() is that live() did not support DOM traversal, whereas delegate supported binding of events to specific DOM elements.
Using undelegate() removes event bindings created with .delegate()
Using jQuery on()
Now as you can see, there are a large number of methods, all focused on general event binding. In jQuery 1.7, on() method was introduced which is an effort to simplify and merge most event bindings functions into one unified consistent API. If you are interested to see how on() replaces the functionality of all these event methods, open the jQuery 1.7.1 source code (https://github.com/jquery/jquery/blob/1.7/src/event.js#L965) and you will find that bind(), live() and delegate() all point to the on() method.
Let’s see the syntax of on():
$('#container').on('events', 'selector', 'data' ,function() {
//respond to the event
});
Here’s the same example we have been using so far, with on() :
$("#container").on('click', 'a', function () {
console.log("clicked");
$(this).clone().appendTo("#container");
});
http://jsfiddle.net/jquerycookbook/pgywy0ue/4/
Think of on() as a more streamlined way of attaching event handlers. Going forward for all versions of jQuery 1.7 and above, you should use on(). Also note that click() is a shortcut to on().The difference between on() and click() is evident when you use event delegation syntax which is supported only by on(). Another difference is on() supports several events at once like .on('keyup click doubleclick').
Let’s quickly take a recap of the syntax of bind(), live() and delegate() and how your code can be converted to support on():
bind() and on()
// Using bind()
$("#container a").bind("click", function () {});
// Using on()
$("#container a").on("click", function () { });
live() and on()
// Using live()
$("#container a").live("click", function () {});
// Using on()
$("#container").on("click", "a", function () { });
delegate() and on()
// Using delegate()
$("#container").delegate('a', 'click', function () {});
// Using on()
$("#container").on("click", "a", function () { });
Further Reading:
http://api.jquery.com/on/
http://api.jquery.com/category/events/
If you liked this article, take a look at my jQuery book The Absolutely Awesome jQuery Cookbook which contains scores of practical jQuery/jQueryUI recipes you can use in your projects right away.
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn