jQuery on() method on multiple selectors

JavascriptJqueryJquery 1.7

Javascript Problem Overview


Since version 1.7 live is deprecated.

Following example is easy to make compatible with new on method:

$('nav li, #sb-nav li, #help li').live('click', function () {
    // code...
});

Using on:

$('nav, #sb-nav, #help').on('click', 'li', function () {
    // code...
});

How to rewrite following example using on?

 $('#header .fixed-feedback-bn, #sb-sec .feedback-bn').live('click', function () {
     // code...
 });

Javascript Solutions


Solution 1 - Javascript

$(document).on('click', '#header .fixed-feedback-bn, #sb-sec .feedback-bn', function () {
     // code...
 });

.live() is just binding document as listener.

My two cents are that you can almost always find a better listener than document. At bare minimum, almost all pages use a main content wrapper. This eliminates nodes in the header, footer, and sometimes sidebars as listeners.

The best way to use .on as a delegating function is to identify the nearest common ancestor that is expected to never be destroyed or otherwise have events unbound. For example, if you have a form that gets updated and changed by ajax requests, the listener could be the form node itself (if only the contents of the form are updated) or a container element (generally a div) that surrounds the form. If such a div isn't there, you could always add it in, or you could just go up the tree to the next ancestor.

[edited to add:]

In the particular sample code provided, it's hard to say if there's a better listener that would contain both #header and also #sb-sec. But imagining that these things share an ancestor with the id "mainContainer", your more efficient code simply swaps out the listener:

$('#mainContainer').on('click', '#header .fixed-feedback-bn, #sb-sec .feedback-bn', function () {
   // code...
});

Solution 2 - Javascript

If you're trying to use .on() so that you can listen to events on DOM object that may be created after you make the initial .on() call, then the most efficient way to do so is to find an existing parent object that won't come and go and you can bind event listeners to now.

.live() put all listeners on the document object (the master parent) and could get pretty inefficient if you had a lot of listeners.

.on() allows you to specify what that parent object will most efficiently be. So, if you want to put all these event handlers in one statement and these '#header .fixed-feedback-bn, #sb-sec .feedback-bn' don't have a common parent, then you'd have to specify document as that parent like Greg has written.

But, a more efficient way of doing this would be to break this apart according to need. For the elements that have no dynamic need, just bind directly to that element. For example if #header and #sb-sec doesn't come/go and doesn't need dynamic behavior, you can just find directly to it like this:

$('#header, #sb-sec').on('click', function() {
    // code here
});

And, for elements that you need some dynamic behavior, pick an appropriate common parent and hook onto that like this using the common parent as the catch point for the events and the selector as the filter for which sub-elements you want the event to fire for:

$('#feedback').on('click', '.feedback-bn, .fixed-feedback-bn', function() {
    // code here
});

Solution 3 - Javascript

You may want to have a look at the documentation of live(), the switch to on() is documented: http://api.jquery.com/live/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWojciech BednarskiView Question on Stackoverflow
Solution 1 - JavascriptGreg PettitView Answer on Stackoverflow
Solution 2 - Javascriptjfriend00View Answer on Stackoverflow
Solution 3 - JavascriptkarellmView Answer on Stackoverflow