Reputation: 7592
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
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