11

What is the purpose of the selector in the jQuery on() method?

In what situation is

$("#fish").on("click", ".button", function() {
    // something
});

better than, say,

$("#fish").find(".button").on("click", function() {
    // something
});

?

I've looked on the jQuery documention and found:

If selector is omitted or is null, the event handler is referred to as direct or directly-bound. The handler is called every time an event occurs on the selected elements, whether it occurs directly on the element or bubbles from a descendant (inner) element.

When a selector is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.

Am I correct in saying that the difference is that in my first example, the event is bound to the #fish, but only listens for events bubbling up from the .buttons, whereas in the second example the event is bound to each of the .buttons? If so what are the implications of this? :S

So if the event is bound to the #fish, when you click a .button, is there anyway to know which .button was clicked on? this will refer to the #fish rather than the .button, correct?

Community
  • 1
  • 1
Valuk
  • 1,606
  • 3
  • 17
  • 23
  • 4
    The first example will work for `.button` elements inside `#fish` which exist when the event is bound, or in the future. The second example will only run the function on `.button` elements inside `#fish` when the binding is made. – BenM Jun 20 '13 at 08:55

2 Answers2

13

Example #1 will bind the event for dynamically created buttons, as long as they are a descendant of #fish. Any buttons created after the binding will have the click handler called. You can also bind to $(document) if you don't want select an ancestor element.

Example #2 will only bind to the buttons that are in the DOM at the time of binding. Any dynamically created elements will not receive the handler.

In both examples, this and $(this) will refer to the button that was clicked, not #fish.

Have a look at this jsFiddle for a demo. You'll see in the console that this is referring to the buttons not #fish.

$('#fish').on('click', '.button', function(){
    console.log(this.id);
});
MrCode
  • 63,975
  • 10
  • 90
  • 112
4

Yes, that is correct. When you call the on method with a selector, it creates a delegated event.

$("#fish").on("click", ".button", function() {

does the same as:

$("#fish").delegate(".button", "click", function() {

The event is bound to the #fish element, but it only calls the event handler for clicks on the .button element. This means that the .button element doesn't have to exist when you bind the element, only the #fish element.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • So if the event is bound to the `#fish`, when you click a `.button`, is there anyway to know which `.button` was clicked on? `this` will refer to the `#fish` rather than the `.button`, correct? – Valuk Jun 20 '13 at 09:30
  • @Valuk incorrect, `this` will refer to the button not `#fish`. – MrCode Jun 20 '13 at 09:37
  • @MrCode oh! I would've thought that as the event handler is on the `#fish`, that is what `this` would have referred to. But you're saying that `this` will refer to the element originally clicked on? Is this true for event bubbling as well? – Valuk Jun 20 '13 at 09:42
  • 1
    @Valuk added comment and demo to my answer. Yes `this` will refer to the button, never `#fish`. Event bubbling is a whole new kettle of fish. Event bubbling info http://www.quirksmode.org/js/events_order.html – MrCode Jun 20 '13 at 09:59