62

When more than one event handler is bound to an element, how is it determined which one is triggered first?

<script> 
$(function(){
    $(".li").find('input').click(function(){alert('li>input');});
    $(".li").click(function(){alert('li');});
    $('input').click(function(){alert('input');});
});
</script>
</head>

<body>
<ul>
<li class="li"><input type="checkbox" /><span>Hello</span></li>
<li class="li"><input type="checkbox" /><span>Hello</span></li>
<li class="li"><input type="checkbox" /><span>Hello</span></li>
</ul>
</body>
user1032531
  • 24,767
  • 68
  • 217
  • 387

3 Answers3

81

I want to point out that the "First come, first serve" rule is not always true, it also depends on how you register a handler:

Handler1 - $(document).on('click', 'a', function....)
Handler2 - $('a').on('click', function....)

This the above example, the Handler 2 is always called before the handler1.

Have a look at this fiddle: http://jsfiddle.net/MFec6/

David Lin
  • 13,168
  • 5
  • 46
  • 46
  • 35
    @Maruccio The reason for this is because of bubbling. `Handler1` in the example above is not _actually_ being attached to the `a` tag. Instead, it is attached to the `document`. Thus, Handler2 is executed, then the event bubbles up until it hits the `document` and then jQuery searches through `document`'s event delegations to check if the element that fired the event matches the selector provided in the second parameter of `on` for `Handler1`. In reality, it *is* true that it is "First come, first serve". Bubbling is a completely different matter entirely. – Swivel Sep 18 '13 at 21:36
  • 2
    +1 Thanks for this answer. I have been banging my head against the wall questioning FCFS - and of course now it makes sense. – Mark Apr 25 '15 at 21:40
  • 2
    @Swivel If there are two or more handlers attached to click event of say #someID then it is essentially FCFS right? – techie_28 May 23 '16 at 09:41
  • 3
    @techie_28 Yes! :) It is all FCFS. There's some great materials on event bubbling [here](http://javascript.info/tutorial/bubbling-and-capturing) that can help you understand the event firing order. It's all FCFS, starting with the event target element's handlers, and then via propagation working its way up the DOM to the root element. – Swivel May 25 '16 at 21:01
  • @Swivel also I have read that if used properly `Handler1` approach is better then the `Handler2`.. like `$('#parentDIV').on('click', 'a', function....)` attaches a single listener on the parent while `Handler2` will attach to each `a`.So we should prefer the `Handler1` approach when we can? – techie_28 May 26 '16 at 05:52
  • 1
    I've just experienced that `$document.on('x', function(){})` is called /after/ `$document.on('x', '...', function(){})`, even if the latter is attached last. –  Nov 25 '16 at 00:32
  • Flash is still a decade ahead of HTML. Not only does Flash support all of this stuff with addEventListener, removeEventListener, stopPropagation, stopImmediatePropagation, it also supports a "priority" parameter so you can set the priority in which listeners will run, which is higher priority first, followed by the attached order. It even supports attaching listeners as weak references. http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener() It's amazing how superior AS3 is to JavaScript (+jQuery, lol). – Triynko Aug 15 '17 at 15:25
  • Something else you should know is that since Handler 1 is attached to `document` and not the `a` element, any new `a` elements created after the event is assigned will still have the handler. In Handler 2, new elements created after the handler is set won't have the event handler. – Gavin Jan 11 '19 at 12:07
  • Bubbling makes so much sense.. :) Thanks for the answer – JayKandari May 20 '20 at 14:04
47

If two event handlers are bound to the exact same object, it would be first come, first serve. The first one attached will execute first.

But, your example looks a bit different. It looks like you also have one event bound to the input object and others to the parent li object. In that case, the one where the event actually originated (presumably the input element in this case) will occur first and then the event will bubble up to the parent objects and they will occur later.

If you want to stop the bubbling up to the parents, you can use jQuery's event.stopPropagation() and the event will not reach the parents and never trigger their event handlers. That would look like this:

$('input').click(function(e) {
    e.stopPropagation();
    alert('input');
});

Per the jQuery documentation for stopPropagation(), it does not stop other event handlers on the same object, only event handlers on parent objects that would normally get the event via bubbling up the parent tree.

You can see the difference here: http://jsfiddle.net/jfriend00/L33aq/

bitifet
  • 3,514
  • 15
  • 37
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Great Answer and Explanation . What happens if the event is forced to capture instead of bubbling up ? – Santhosh Dec 24 '15 at 18:23
  • 1
    @SanKrish - See http://javascript.info/tutorial/bubbling-and-capturing for a full description of how you could use capturing. – jfriend00 Dec 24 '15 at 20:34
4

First come, first serve. The first one bound will be the first one triggered, and so on...

Related: jQuery event handlers always execute in order they were bound - any way around this?

Community
  • 1
  • 1
karim79
  • 339,989
  • 67
  • 413
  • 406