Do not use jQuery’s live()

Hey, here’s a quick post, because I’m going through some old code and am in the process of refactoring and updating a lot of Javascript. jQuery is a powerful library that is very easy to use. Therein lies the problem: its simplicity makes it an easy target to be misused by developers. One easy way of misusing the library is by using the live() function. Luckily it’s been removed in v1.9, so no further abuse is possible. The live() function is used to listen to incoming events on all items matching the selector, even if they don’t exist at the time. It’s a handy feature to use if you have a lot of dynamic content on your page and don’t want to re-add event listeners every time the content changes.

If you have a list of some sort and would like to add to the list a new item with a listener, you could do the following:

<script type="text/javascript">
  // add a new item with an incremental number
  function addNewItem() {
    $("ul").append("<li><a href=\"#\">Item " + ($("ul li").length+1) + "</a></li>");
  }
  $("ul a").live("click", function(e) {
    e.preventDefault(); // don't follow the link
    alert($(this).html()); // just alert its contents
  });
</script>
<ul>
  <li><a href="#">Item 1</a></li>
  <li><a href="#">Item 2</a></li>
</ul>
<button onclick="return addNewItem();">Add new item</button>

Clickable demo 1: Using live()

And with this all the items added to the list will be heard and do the same as the existing one. The code does this by catching all events on document level and scanning through the sources and doing what you are expecting of it. Catching all events on document level is pretty bad and causes performance issues.

The better way is to set a path yourself and try to make it as small as possible. You can do this by using the same old on() function in jQuery, but you add an extra parameter telling the parent what events to listen to. Here’s how:

<script type="text/javascript">
  // add a new item with an incremental number
  function addNewItem() {
    $("ul").append("<li><a href=\"#\">Item " + ($("ul li").length+1) + "</a></li>");
  }
  $(function() { // depending on your script location (above or below the elements you're targeting), you'll need an onload event as well
    $("ul").on("click", "a", function(e) {
      e.preventDefault(); // don't follow the link
      alert($(this).html()); // just alert its contents
    });
  }
</script>
<ul>
  <li><a href="#">Item 1</a></li>
  <li><a href="#">Item 2</a></li>
</ul>
<button onclick="return addNewItem();">Add new item</button>

Clickable demo 2: Using custom hierarchy

With this you put a click-handler on all ULs in your document, but it only fires if the clicks come from any A-child elements. And just like that, it’s clean and ready for the future!

Note that in this example I added an onload handler as well, because my JavaScript is above my HTML.

2 Thoughts

  1. Hey Rolf, it depends on the level of the element. The element (on which you want to receive the events) has to be there the moment you call the on() function. That’s why in the second piece of code I added jQuery’s onload to make sure the UL is there when I need it. Let me know if this helps. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.