0
<div id="tours">
  <h1>Guided Tours</h1>
  <ul>
    <li class="usa tour" data-discount="299">
      <h2>New York, New York</h2>
      <span class="details">$1,899 for 7 nights</span>
      <button class="book">Book Now</button>
    </li>
    <li class="europe tour" data-discount="176">
      <h2>Paris, France</h2>
      <span class="details">$2,299 for 7 nights</span>
      <button class="book">Book Now</button>
    </li>
    <li class="asia tour" data-discount="349">
      <h2>Tokyo, Japan</h2>
      <span class="details">$3,799 for 7 nights</span>
      <button class="book">Book Now</button>
    </li>
  </ul>
</div>

The above is HTML code and below is the DOM manipulation part.

$(document).ready(function(){
  $("li.tour button.book").on("click", function(){
    var tour = $(this).closest(".tour");
    var discount = tour.data("discount");
    var message = $("<span>Call 1-555-jquery-air for a $" + discount + "</span>");
    tour.append(message);
    $(this).remove();
  });
});

The above code works fine. But it seems the right way to do the approach is below and they call it as event delegation

$(document).ready(function(){
  $("li.tour").on("click", "button", function(){
    var tour = $(this).closest(".tour");
    var discount = tour.data("discount");
    var message = $("<span>Call 1-555-jquery-air for a $" + discount + "</span>");
    tour.append(message);
    $(this).remove();
  });
});
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Kevin
  • 23,174
  • 26
  • 81
  • 111

2 Answers2

2

Your second solution will have better performance if you have a ton of <button>s because jQuery will look for bubbled events on $("li.tour"), instead of attaching event handlers to every <button>, as the docs say: "another advantage of delegated events is their potential for much lower overhead when many elements must be monitored. On a data table with 1,000 rows in its tbody, this example attaches a handler to 1,000 elements"

"Note that for a small amount of elements, and especially with complicated selectors, the filtering that takes place in a delegated event handler can in many cases be slower than just attaching four seperate event handlers" - adeneo

This fiddle here helps explain the difference.

TL;DR

If you have a ton of elements to select, use a delegated event handler.

If you have a complicated selector and not a lot of elements to select, use a regular event handler.

Otherwise, its not a big deal which one you use.

Community
  • 1
  • 1
dezman
  • 18,087
  • 10
  • 53
  • 91
  • @Itay Aside from what exactly watching consists of inside of jQuery, I am sure that is how it works. – dezman Sep 07 '13 at 17:26
  • 1
    I'm pretty sure there isn't any mechanism that `see if more elements have been added to the DOM`. It just captures the clicks on the parent and check if the target is one of the selectors. – Itay Sep 07 '13 at 17:29
  • " If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next... Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time." - http://api.jquery.com/on/ – dezman Sep 07 '13 at 17:33
  • That sounds exactly like what I said. – Itay Sep 07 '13 at 17:34
  • I know what delegated events are and what they do. I'm just saying the mechanism for implementing this is not how you've written above. – Itay Sep 07 '13 at 17:39
  • 1
    I see now, and actually the OP was correct, because delegated events have lower overhead. My bad. – dezman Sep 07 '13 at 17:41
  • 1
    Event delegation takes advantage of *event bubbling* in JavaScript. There is no *watching* involved. – Matt Sep 07 '13 at 17:41
  • @Matt, right, I was wrong about this, :( but I have updated my answer to be accurate now, I believe. – dezman Sep 07 '13 at 17:46
  • Note that for a small amount of elements, and especially with complicated selectors, the filtering that takes place in a delegated event handler can in many cases be slower than just attaching four seperate event handlers. – adeneo Sep 07 '13 at 17:48
2

As others have pointed out, neither solution is too-distinguishable from the other as it stands, as both will attach an event handler to 3 elements (whether it be a li.tour or a button.book).

To really take advantage of event bubbling, what you'll want to do is;

$(document).ready(function(){
  $("ul").on("click", "button.book", function(){
    var tour = $(this).closest(".tour");
    var discount = tour.data("discount");
    var message = $("<span>Call 1-555-jquery-air for a $" + discount + "</span>");
    tour.append(message);
    $(this).remove();
  });
});

... this way, only 1 event handler is bound to the ul. Event bubbling will mean click's on the button are eventually fired on the ul, which is how jQuery knows a click event has happened.

The advantage here is that you:

  • Aren't looping over 3 elements (only 1).
  • Your DOM has only 1 event handler bound, rather than 3

... obviously this will be a negligible (almost non-existent) benefit for now, but will grow as the amount of elements involved increases.

A small disadvantage is that any click on a descendant of a ul will also bubble to the ul, leaving jQuery to decide (hence a small performance hit) whether to invoke the click handler or not.

Community
  • 1
  • 1
Matt
  • 74,352
  • 26
  • 153
  • 180
  • And in that one event handler, everytime someone clicks the parent UL or a descendant of that UL, the event handler has to check if that click originated from an element matching the second selector. – adeneo Sep 07 '13 at 17:50
  • @adeneo: Hehe, great minds think alike. I was just considering whether it was worth including that ;). – Matt Sep 07 '13 at 17:50
  • Still a good answer, I'll upvote! In my opinion using event delegation for performance in jQuery makes such a small difference that unless it's really **a lot** of elements, or if it's **a lot** easier to write just one event handler (and with jQuery's selector engine it rarely is) it's not worth it. – adeneo Sep 07 '13 at 17:55
  • @adeneo: I agree that the performance benefits are almost negligible (I tried to stress that in my answer :P). Personally, I prefer to delegate to a single element rather than attaching to multiple as it makes me sleep easier... but as you said, it basically boils down to personal preference :). – Matt Sep 07 '13 at 17:57