jquery .live('click') vs .click()

JqueryLive

Jquery Problem Overview


I am wondering whether there are any circumstances where it would be better to use .click(function {...}); rather than .live('click', function {...});?

From what I gather the live option seems to be a better option and I am hence using it in almost all circumstances instead of the plain .click(), especially given a lot of my code is loaded asynchronously.

EDIT: Another part to this question. If I'm asynchoronously loading all the javascript in, .click will still pickup all elements already in the dom. Right?

Jquery Solutions


Solution 1 - Jquery

There might be times when you explicitly want to only assign the click handler to objects which already exist, and handle new objects differently. But more commonly, live doesn't always work. It doesn't work with chained jQuery statements such as:

$(this).children().live('click',doSomething);

It needs a selector to work properly because of the way events bubble up the DOM tree.

Edit: Someone just upvoted this, so obviously people are still looking at it. I should point out that live and bind are both deprecated. You can perform both with .on(), which IMO is a much clearer syntax. To replace bind:

$(selector).on('click', function () {
    ...
});

and to replace live:

$(document).on('click', selector, function () {
    ...
});

Instead of using $(document), you can use any jQuery object which contains all the elements you're monitoring the clicks on, but the corresponding element must exist when you call it.

Solution 2 - Jquery

(Note 29/08/2017: live was deprecated many versions ago and removed in v1.9. delegate was deprecated in v3.0. In both cases, use the delegating signature of on instead [also covered below].)


live happens by capturing the event when it's bubbled all the way up the DOM to the document root, and then looking at the source element. click happens by capturing the event on the element itself. So if you're using live, and one of the ancestor elements is hooking the event directly (and preventing it continuing to bubble), you'll never see the event on your element. Whereas normally, the element nearest the event (click or whatever) gets first grab at it, the mix of live and non-live events can change that in subtle ways.

For example:

jQuery(function($) {

  $('span').live('click', function() {
    display("<tt>live</tt> caught a click!");
  });

  $('#catcher').click(function() {
    display("Catcher caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

});

<div>
  <span>Click me</span>
  <span>or me</span>
  <span>or me</span>
  <div>
    <span>I'm two levels in</span>
    <span>so am I</span>
  </div>
  <div id='catcher'>
    <span>I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span>me too</span>
  </div>
</div>
<!-- Using an old version because `live` was removed in v1.9 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>

I'd recommend using delegate over live when you can, so you can more thoroughly control the scope; with delegate, you control the root element that captures the bubbling event (e.g., live is basically delegate using the document root as the root). Also, recommend avoiding (where possible) having delegate or live interacting with non-delegated, non-live event handling.


Here several years later, you wouldn't use either live or delegate; you'd use the delegating signature of on, but the concept is still the same: The event is hooked on the element you call on on, but then fired only when descendants match the selector given after the event name:

jQuery(function($) {

  $(document).on('click', 'span', function() {
    display("<tt>live</tt> caught a click!");
  });

  $('#catcher').click(function() {
    display("Catcher caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

});

<div>
  <span>Click me</span>
  <span>or me</span>
  <span>or me</span>
  <div>
    <span>I'm two levels in</span>
    <span>so am I</span>
  </div>
  <div id='catcher'>
    <span>I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span>me too</span>
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Solution 3 - Jquery

All objects that would be associated with the .click must exist when you set the event.

Example: (in pseudo code) the append can be $("body").append() for example

append('<div id="foo" class="something">...</div>');
$("div.something").click(function(){...});
append('<div id="bar" class="something">...</div>');

Click works for foo but doesn't work for bar

Example2:

append('<div id="foo" class="something">...</div>');
$("div.something").live("click",function(){...});
append('<div id="bar" class="something">...</div>');

click works for both foo and bar

With .live('click'... you can dynamicaly add more objects after you created the event and the clicking event will still work.

Solution 4 - Jquery

"live" is needed when you dynamically generate code. Just look the below example :

$("#div1").find('button').click(function() {
    $('<button />')
     .text('BUTTON')
     .appendTo('#div1')
})
$("#div2").find('button').live("click", function() {
    $('<button />')
     .text('BUTTON')
     .appendTo('#div2')
})

button {
  margin: 5px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id="div1">
  <button>Click</button>
</div>
<div id="div2">
  <button>Live</button>
</div>

without "live" the click-event occurs only when you click the first button, with "live" the click-event occurs also for the dynamically generated buttons

Solution 5 - Jquery

Always use click if you not dynamically add elements.

live works by adding an event listener to the document root and listens for bubbled up events. An alternative is delegate, which works the same, but binds the event handler to the specified element.
This way, the event has not to bubble up the whole DOM and is caught earlier.

Solution 6 - Jquery

.live() is used if elements are being added after the initial page load. Say you have a button which gets added by an AJAX call after the page gets loaded. This new button will not be accessible using .click(), so you'll have to use .live('click')

Solution 7 - Jquery

As 'live' will handle events for future elements that match the current selector, you may choose click as you don't want that to happen - you only want to handle the current selected elements.

Also, I suspect (though have no evidence) that there is a slight efficiency using 'click' over 'live'.

Lee

Solution 8 - Jquery

From what I understand the key difference is that live() keeps an eye open for new DOM elements that match the selector you are working on, whereas click() (or bind('click')) attach the event hook and are finished.

Given that alot of your code is loaded asynchronously, using live() will make your life alot easier. If you don't know exactly the code you are loading but you do know what kind of elements you will be listening to, then using this function makes perfect sense.

In terms of performance gains, one alternative to using live() would be to implement an AJAX callback function to re-bind the event hooks.

var ajaxCallback = function(){
 $('*').unbind('click');
 $('.something').bind('click', someFunction);
 $('.somethingElse').bind('click', someOtherFunction);
}

You will need to keep proper track of your event hooks and make sure this function is rebinding the proper events.

p.s. Ajax methods .get(), .post(), .load() and .ajax() all let you specify a callback function.

Solution 9 - Jquery

If you need simplify code then live is better in the most cases. If you need to get the best performance then delegate will always better than live. bind (click) vs delegate isn't so simple question (if you have a lot of similar items then delegate will be better).

Solution 10 - Jquery

remember that the use of "live" is for "jQuery 1.3" or higher

in version "jQuery 1.4.3" or higher is used "delegate"

and version "jQuery 1.7 +" or higher is used "on"

$( selector ).live( events, data, handler ); // jQuery 1.3+
$( document ).delegate( selector, events, data, handler ); // jQuery 1.4.3+
$( document ).on( events, selector, data, handler ); // jQuery 1.7+

As of jQuery 1.7, the .live() method is deprecated.

check http://api.jquery.com/live/

Regards, Fernando

Solution 11 - Jquery

In addition to T.J. Crowders answer, I have added some more handlers - including the newer .on(...) handler to the snippet so you can see which events are being hidden and which ones not.

What I also found is that .live() is not only deprecated, but was deleted since jQuery 1.9.x. But the other ones, i.e.
.click, .delegate/.undelegate and .on/.off
are still there.

Also note there is more discussion about this topic here on Stackoverflow.

If you need to fix legacy code that is relying on .live, but you require to use a new version of jQuery (> 1.8.3), you can fix it with this snippet:

// fix if legacy code uses .live, but you want to user newer jQuery library
if (!$.fn.live) {
    // in this case .live does not exist, emulate .live by calling .on
    $.fn.live = function(events, handler) {
      $(this).on(events, null, {}, handler);
    };
}

The intention of the snippet below, which is an extension of T.J.'s script, is that you can try out by yourself instantly what happens if you bind multiple handlers - so please run the snippet and click on the texts below:

jQuery(function($) {

  // .live connects function with all spans
  $('span').live('click', function() {
    display("<tt>live</tt> caught a click!");
  });

  // --- catcher1 events ---

  // .click connects function with id='catcher1'
  $('#catcher1').click(function() {
    display("Click Catcher1 caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  // --- catcher2 events ---

  // .click connects function with id='catcher2'
  $('#catcher2').click(function() {
    display("Click Catcher2 caught a click and prevented <tt>live</tt>, <tt>delegate</tt> and <tt>on</tt> from seeing it.");
    return false;
  });

  // .delegate connects function with id='catcher2'
  $(document).delegate('#catcher2', 'click', function() {
    display("Delegate Catcher2 caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  // .on connects function with id='catcher2'
  $(document).on('click', '#catcher2', {}, function() {
    display("On Catcher2 caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  // --- catcher3 events ---

  // .delegate connects function with id='catcher3'
  $(document).delegate('#catcher3', 'click', function() {
    display("Delegate Catcher3 caught a click and <tt>live</tt> and <tt>on</tt> can see it.");
    return false;
  });

  // .on connects function with id='catcher3'
  $(document).on('click', '#catcher3', {}, function() {
    display("On Catcher3 caught a click and and <tt>live</tt> and <tt>delegate</tt> can see it.");
    return false;
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

});

<!-- with JQuery 1.8.3 it still works, but .live was removed since 1.9.0 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>

<style>
span.frame {
    line-height: 170%; border-style: groove;
}
</style>

<div>
  <span class="frame">Click me</span>
  <span class="frame">or me</span>
  <span class="frame">or me</span>
  <div>
    <span class="frame">I'm two levels in</span>
    <span class="frame">so am I</span>
  </div>
  <div id='catcher1'>
    <span class="frame">#1 - I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span class="frame">me too</span>
  </div>
  <div id='catcher2'>
    <span class="frame">#2 - I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span class="frame">me too</span>
  </div>
  <div id='catcher3'>
    <span class="frame">#3 - I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span class="frame">me too</span>
  </div>
</div>

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
QuestionkalpaitchView Question on Stackoverflow
Solution 1 - JqueryNathan MacInnesView Answer on Stackoverflow
Solution 2 - JqueryT.J. CrowderView Answer on Stackoverflow
Solution 3 - JqueryfmsfView Answer on Stackoverflow
Solution 4 - JqueryMr. BlackView Answer on Stackoverflow
Solution 5 - JqueryFelix KlingView Answer on Stackoverflow
Solution 6 - JquerydottyView Answer on Stackoverflow
Solution 7 - JqueryLee AtkinsonView Answer on Stackoverflow
Solution 8 - JqueryJoe GreenView Answer on Stackoverflow
Solution 9 - JqueryoryolView Answer on Stackoverflow
Solution 10 - JqueryFernandoView Answer on Stackoverflow
Solution 11 - JqueryMattView Answer on Stackoverflow