The latest version of jQuery, version 1.7.1 at the time of writing, has completely overhauled its event system, giving us just two new methods to replace all existing event methods such as bind(), live() or delegate().
Event handling has been a core part of jQuery for a long time, but over the years the jQuery event landscape has flourished and grown, with successive releases increasing the number of methods for handling events.
The new event methods on() and off() condense these different methods down into a single unified API. Instead of having different methods to handle different behaviours, the new methods simply behave differently depending on how they are called.
Attaching events like bind()
Attaching an event using the on() method in the same way as if we had used the bind() method can be done like this:
$("#button1").on("click", function () {
//do stuff
});
When just two arguments are passed to the on() method the event handler is attached directly to the selected element. In this example the button with an id of button1 will have a click-handler attached to it, which will execution the function passed as the second argument whenever the event is detected. This is equivalent to the now deprecated bind() method. Alternatively, we can attach multiple events by supplying a single argument to on():
$("#button1").on({
click: function () {
//do stuff
},
focus: function () {
//do stuff
}
});
The argument we pass to the method accepts an object where the keys are event names, and the values are anonymous functions that are executed when the events are detected. Again, this is exactly how we could have previously used bind().
Attaching events like delegate()
In its other form, the on() method accepts three arguments:
$("#delegateContainer").on("click", "button", function () {
//do stuff
});
In this form the on() method accepts an extra argument. The first argument is still the name of an event (or a space-separated list of events) to listen for, but the second argument is now a selector to filter by. The third argument is the function to execute when the event (or events) is detected.
What happens is; the container element that is initially selected (“delegateContainer” in the above example) has the event handler attached to it. When the named event is detected jQuery checks to see whether it originated from the element matching the selector passed as the second argument. If it does, the function is executed.
Just like with the delegate() method, we can use any CSS selector, DOM node or jQuery object as the second argument. This is a major step up from the live() method, which was restricted to just CSS selectors. However, the value of $(this) within the event handler changes depending on what you pass as the second argument; if you pass a CSS selector, the $(this) object points to the innermost element that triggered the event (in this example, the button that was clicked). However, if you pass a DOM node or jQuery object, $(this) will point to the container that the event was delegated to. Watch out for this when coding.
Event delegation in this way brings several benefits; firstly, it can allow us to vastly reduce the number of event handlers that are attached to elements – we could have hundreds of buttons within our delegateContainer, but we would still only need to attach a single handler to the container, and any button would trigger it when clicked. Secondly, if we attached new buttons at some point in the future, after we had attached the handler, the new buttons would still trigger the event handler without us having to rebind it.
As well as the arguments we’ve looked at, the on() method can also accept a data object, which will available within the callback function as event.data. This argument should be passed to the method as either the second or third argument depending on whether a CSS selector is also provided, for example either:
$("#button1").on("click", { someKey: "someValue" }, function (e) {
//someValue available via e.data.someKey
});
Or:
$("#button1").on({
click: function (e) {
//someValue available via e.data.someKey
}
}, { someKey: "someValue" });
Or, with event delegation:
$("#delegateContainer").on("click", "button", { someKey: "someValue" }, function (e) {
//someValue available via e.data.someKey
});
Removing events
To remove a bound event handler, we can use the off() method, which is the new replacement for the unbind(), die() and undelegate(). The off() method also takes a varying number of arguments; if a CSS selector was passed to the on() method, the same selector should be passed to off(). To remove the delegated event handler, we could use the following code:
$("#button3").on("click", function () {
$("#delegateContainer").off("click", "button");
});
The off() method is almost identical to the code we used with the on() method from the last example, except that we don’t provide a callback function. If we don’t supply a CSS selector to the on() method, the off() method can be even simpler, with just the name of the event to remove the handler from.
Summary
The old event-handling methods live(), bind() and delegate(), and their opposite unbinding methods, are all now deprecated; they’re still available to use through the core jQuery API of course and will remain there for some time yet, but their use is advised against now that we have on() and off() to take care of all our event handling needs.