34

In the old days, I used to chain calls to live() with great success, e.g.:

$(".something")
    .live("click", function(e) { ... })
    .live("change", function(e) { ... })
    .live("submit", function(e) { ... });

These days, live(), bind() and delegate() have been superseded by the shiny new on().

I've tried simply replacing live() with on() which would seem obvious:

$(".something")
    .on("click", function(e) { ... })
    .on("change", function(e) { ... })
    .on("submit", function(e) { ... });

However, it's almost as obvious that this won't work when you consider how on() works. This from http://api.jquery.com/on/:

"Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on()."

According to the jQuery docs, I need to bind to document and delegate to .something to handle live events. Unfortunately, this means I end up repeating my delegate selector (.document) if I want to replicate what I have above with on():

$(document)
    .on("click", ".something", function(e) { ... })
    .on("change", ".something", function(e) { ... })
    .on("submit", ".something", function(e) { ... });

This works as expected but I'd really love to be able to chain more clearly like I do using live(). Am I missing something?

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
tristanm
  • 3,337
  • 2
  • 27
  • 40

3 Answers3

89

I believe you can do this:

$(document).on({
    "click" : function(e) { ... },
    "change" : function(e) { ... },
    "submit" : function(e) { ... }
}, ".something");

That is, use the "events-map" syntax to specify the events and their handlers, and then specify the selector to use for the delegate-style behaviour.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • 1
    Yes, you sir are the winner. https://github.com/jquery/jquery/blob/1.7.2/src/event.js#L891 – Jake Aug 08 '12 at 02:34
  • 4
    @nnnnnn thank you for being a truly helpful stackoverflow member by actually reading my question and giving a correct answer :) – tristanm Aug 08 '12 at 02:38
  • 1
    Someone who actually read the question thoroughly before answering. An award is in order! – Doug S Nov 20 '12 at 06:39
0

.live() has a bunch of problems. One of them was that it was evaluating the selector ".something" when you ran the code, but then not using the result (e.g. wasteful) and then re-evaluating at runtime when the event occurred (like it needs to in order to work properly).

In addition .live() forced all dynamic events to be on the document object which could really slow event handling down if you had a lot of dynamic event handlers. .on(), on the other hand, lets you pick a static parent that is much closer to the actual object and attach the event handler to that object so different dynamic event handlers can be attached both closer to the source and to different objects which makes their runtime performance much, much better when there are lots of event handlers.

So, you need to just live with the new way that .on() works as it is much more efficient. It should be no big deal to you that you have to do a slight more retyping of the dynamic selector if you use the same form you're using now or, you can pass a map as the first parameter to .on() and handle multiple events in one .on() calls. See the second form of .on() in the jQuery doc for .on() for more info.

Here's a simple explanation of using .on() for dynamic behavior.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • `$(".something", static_parent).live(...)` did let you pick a static parent, right? – Jake Aug 08 '12 at 02:32
  • yes: https://github.com/jquery/jquery/blob/1.6.4/src/event.js#L1016 I understand the inefficiency of evaluating the selector, I'm not saying `live` was better than `on`. – Jake Aug 08 '12 at 02:44
0

As I understand your question you want something as short as live(). Using on() you have to write a bit more, but if .something is being added dynamically then you have another option that also delegates the event.

var $div = $('<div/>', {
  'class': 'something',
   click: function () { ... },
   change: function () { ... }
})

// Already has events attached
// no need to delegate
$div.appendTo('body')
elclanrs
  • 92,861
  • 21
  • 134
  • 171
  • 2
    _"...that also delegates the event"_ - I don't think that's delegating, it's just binding the events directly at the time the element(s) are created. – nnnnnn Aug 08 '12 at 02:38
  • Yup, I guess you're right, in any case it's another way of doing the same thing in certain situations. – elclanrs Aug 08 '12 at 02:43