lmjohns3
lmjohns3

Reputation: 7592

Cannot get focus to return to div after input blurs

http://jsfiddle.net/NsRyr/1/

I am totally stumped on this. Here's what I'm trying to do : I have a div element (call it #keys) that I'm using to handle keypress events.

HTML:

<div id="#keys" tabindex="1">Focus</div>

JS:

$('#keys').keydown(function () {
    $('#log').append('*'); // just note that an event happened
});

This works as expected -- as long as #keys is focused, I can receive keypress events and respond to them. In addition, I can set focus to other div elements and the keypress events will no longer be handled by #keys. I can then re-focus the div (e.g., by clicking on it directly, or by responding to a click event on another DOM element) and keypress events are handled as I expect.

So far, so good. The problem that I've come across is that if I focus an input element and then try to re-focus #keys by setting a blur handler that's activated after tabbing away from the input, the #keys div does not receive focus ! It works fine if I blur away from the input by clicking, but not if I use the keyboard.

$('#input').blur(function () {
    $('#log').append('blur'); // note that a blur happened
    $('#keys').focus();
});

I think the essence of this question is, why doesn't my blur handler on #input seem to work properly when tabbing away from the input (but it does work properly when clicking away) ? Is this just a browser quirk ? (I am using Chrome 30.0.1599.101 on Mac OS.)

This is my first SO question regarding JS, so please let me know what additional detail I can provide to describe the situation.

(Edit : Interestingly, it seems to work fine if I shift-tab away from #input. Still confused what's happening here ; appears to be some sort of tabindex-related issue ?)

Upvotes: 2

Views: 1630

Answers (1)

Evan
Evan

Reputation: 825

I don't have commenting privileges yet, so I'll have to answer, but please mods should change this, because it's basically a duplicate.

Here's the fix to your fiddle: http://jsfiddle.net/NsRyr/3/

The issue (as described in this answer) is that the blur event fires before the change is done, so the focus needs to be sent down the stack to happen after. Adding a timer deals with the issue.

The line I changed was:

setTimeout($('#keys').focus.bind($('#keys')), 0);

That makes it so it'll wait until the new focus event is completed before firing off the handler.

Upvotes: 4

Related Questions