Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Focus and blur jQuery events not bubbling

With the following html structure:

<div>
<form><span><input></span></form>
</div>
<p>

and the following jquery code:

$('form').on("focus", function(event) {
    $("p").append("focus no delegation<br>");
})

Why doesn't the focus event ever reach my event handler? Binding the event with a selector parameter works fine:

$('form').on("focus", "input", function(event) {
    $("p").append("focus delegation<br>");
})

Event the next snippet works so the focus event does in fact bubble...

$('form').on("focus", "span", function(event) {
    $("p").append("focus delegation<br>");
})

Both forms work with click and change events:

$('form').on("click", function(event) {
    $("p").append("click no delegation<br>");
})
$('form').on("click", "input", function(event) {
    $("p").append("click delegation<br>");
})

The only note I found about the focus event's bubbling is relative to older jQuery versions which I don't use. See it in action here

edit 1

Well this is confusing... According to jQuery's focus doc:

The focus event does not bubble in Internet Explorer. Therefore, scripts that rely on event delegation with the focus event will not work consistently across browsers. As of version 1.4.2, however, jQuery works around this limitation by mapping focus to the focusin event in its event delegation methods, .live() and .delegate().

And according to jQuery's focusin doc:

The focusin event is sent to an element when it, or any element inside of it, gains focus. This is distinct from the focus event in that it supports detecting the focus event on parent elements (in other words, it supports event bubbling).

Is it too late for me or does one contradict the other?

like image 395
bernie Avatar asked Mar 06 '12 04:03

bernie


People also ask

Do focus events bubble?

The focus event fires when an element has received focus. The event does not bubble, but the related focusin event that follows does bubble. The opposite of focus is the blur event, which fires when the element has lost focus. The focus event is not cancelable.

Which function supports event bubbling in jQuery?

Event bubbling on( 'click', function( event ) { event. preventDefault(); console. log( this ); }); It binds a click handler to all elements in a document (something you should never do in real code), as well as to the document and window .

What is the difference between Blur and Focusout?

The focusout event fires when an element has lost focus, after the blur event. The two events differ in that focusout bubbles, while blur does not. The opposite of focusout is the focusin event, which fires when the element has received focus.

What is the difference between focus and Focusin events in jQuery?

The focusin event fires when an element has received focus, after the focus event. The two events differ in that focusin bubbles, while focus does not. The opposite of focusin is the focusout event, which fires when the element has lost focus.


2 Answers

As Ohgodwhy pointed out, using focusin instead of focus does work.

However, I can't understand how the following code can work if the "focus" event does not bubble:

$('form').on("focus", "span", function(event) {
    $("p").append("focus delegation<br>");
})

If a span child of the form receives the "focus" event, it means that the event bubbled from the input to the span. Even this works!

$('div').on("focus", "form", function(event) {
    $("p").append("focus delegation<br>");
})

So... using "focusin" does fix the problem, but I'm not fully satisfied by this workaround. If anybody has a better answer, I'll happily accept it.

like image 137
bernie Avatar answered Sep 29 '22 10:09

bernie


Yes, it appears the jQuery docs are misleading. I believe the documentation on focus neglected to mention that this was for the elements that aren't involved in user input (@Ohgodwhy listed them above in your question's comments).

I imagine it has something to do with the browser's need to trap the cursor in the input element that has focus, so that it can accept input from the keyboard. In other words, if jQuery allowed it to bubble, then you would never be given the chance to type in the input field.

Either way you'll never get a form to accept a focus event unless you first put a tabindex on it: http://jsfiddle.net/qxLqP/ but if an input based field gets focus first, it will never bubble. By default, the form element doesn't have a tabindex, and you can't set focus to something that doesn't have a tabindex.

I'd just accept @Ohgodwhy's solution of using focusin and then go let the jQuery team know about their confusing documentation.

like image 37
Josh Avatar answered Sep 29 '22 12:09

Josh