7

I understand that the "live" function is now deprecated. How can I migrate the following to make use of the new "on"?

$('a.action').live( "click", function (evt) {

        // Do stuff 

}

The scenario is that the a.action is being created on the fly. I've tried this, to no avail:

$('a.action').on( "click", function (evt) {

        // Do stuff 

}
Jonathan Wold
  • 777
  • 1
  • 9
  • 24

2 Answers2

10

If you want the actual .live() - type performance where a.action objects don't have to exist yet when you add the event handler, then you should find a parent DOM object of all a.action elementss that always exists and bind .on() to that like this:

$(parent selector).on('click', 'a.action', function (evt) {
    // Do stuff
});

That parent should be as close to the a.action objects as possible for maximum efficiency. For that reason, it is NOT desirable to bind to document.

In fact, one reason .live() has been deprecated is because it was bound to the document object and could easily lead to performance problems when there were too many events all flowing through the one object (event dispatching performance suffered).

See these other related answers of mine for more info:

jQuery .live() vs .on() method for adding a click event after loading dynamic html

How does jQuery's new on() method compare to the live() method in performance?

Should all jquery events be bound to $(document)?

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I wonder if I'm missing something.. I've copied your code and it works for the initial elements on page, but it's still not working for *new* elements whereas the "live" does. Does it matter *how* the elements are being created? – Jonathan Wold Nov 22 '12 at 01:06
  • +1, also good to mention that some browsers/OS's don't propagate events to `document` level - which is yet another reason it's not desirable to bind handlers to it. – ahren Nov 22 '12 at 01:10
  • @JonathanWold - it does not matter how the elements are created, only that they are in the DOM and that they are descendants of the object that you bound the event handler to. If `.live()` works and the delegated form of `.on()` isn't working, then you probably didn't pick the right common parent element or there's an error in your exact code. – jfriend00 Nov 22 '12 at 01:14
  • @jfriend00 would that hold true (that there may be a bad choice of parent or an error) even if the delegated form of .on() *is* working for the elements already existing? – Jonathan Wold Nov 22 '12 at 01:27
  • @JonathanWold - it depends upon where you add the new elements (they have to be descendants of your parent selector) and whether they correctly match your selector in the `.on()` arguments. We can't diagnose this without seeing your code that adds the new elements, the exact `.on()` code and your HTML. – jfriend00 Nov 22 '12 at 03:20
  • @jfriend00 Thank you for the follow-up - I'm going to go ahead and accept the answer (it makes sense), experiment, and report back if I have any further difficulty. – Jonathan Wold Nov 26 '12 at 21:10
2
$(document).on('click', 'a.action', function (evt) {
    // Do stuff
});
kendaleiv
  • 5,793
  • 3
  • 28
  • 38
  • 2
    careful man, that might get a downvote from someone. Official docs first example is just as OP stated. – Kai Qing Nov 22 '12 at 00:48
  • jfriend said it succinctly by noting that binding a direct parent that always exists is the way to achieve the ajax method, though yours may technically work it is better practice to target closely. – Kai Qing Nov 22 '12 at 00:53
  • Depends on your code, here using `$(document)` is faster than using `$('#container')` it seems: http://jsperf.com/jquery-on-document-vs-id-selector – kendaleiv Nov 22 '12 at 01:03
  • @kendaleiv, that just checks the speed of the binding. It is faster since document is an existing element while `#container` must be located first.. The real issue, though, is that binding to document means that an event will need to bubble all the way to the top element before being handled.. – Gabriele Petrioli Nov 22 '12 at 01:13
  • 1
    In addition to what Gaby said, if you bind a lot of events to `document`, then every time an event occurs and it bubbles up to the `document` object, then that event has to be compared to every single selector that is bound to `document`. Since some selector comparisons are quite slow (depending upon the complexity of the selector), this can get quite slow. Binding as close to the actual object as possible makes a short list of event handlers/selectors to compare to each time rather than a long list. Much, much faster in a bigger page. They didn't get rid of `.live()` for the fun of it. – jfriend00 Nov 22 '12 at 01:17
  • @Gaby aka G. Petrioli: Hmmm, perhaps that isn't a fair/good test. Might be interesting to see just how big of a difference it is using `$(document)` vs a more narrow selector (potentially with different size DOMs too). – kendaleiv Nov 22 '12 at 01:41