Consider this example where I have 2 input fields:
<input id="a" />
<input id="b" style="display: none" />
And consider the following JavaScript, which is an attempt to do this:
Show #b
only when #a
has focus and hide #b
whenever #a
loses focus, except when #a
loses its focus to #b
.
$("#a").focus(function() {
$("#b").show();
});
$("#a, #b").blur(function() {
$("#b").hide();
});
$("#b").focus(function(){
$("#b").show();
});
$("#a").focus(function() {
$("#b").show();
});
$("#a, #b").blur(function() {
$("#b").hide();
});
$("#b").focus(function() {
$("#b").show();
});
#b {
display: none;
}
<input id="a" value=a>
<input id="b" value=b>
<br/>^ focus on the input
The above code is incorrect as $("#b").focus()
would never be triggered because as soon as #a
loses focus, #b
is hidden. This expected behavior is observed in Firefox (Version 24.6.0).
But in Chrome (Version 35.0), the code seems to run incorrectly (or correctly!?).
Clearly, the b.focus
event is still being registered in Chrome.
Why does this event register in Chrome, but not in Firefox?
Update
As pointed out by raina77ow:
b
, blur on a
is fired first, then focus on b
, and b
stays visible.b
is not fired, so b
becomes invisible.b
IS fired, but b
becomes invisible immediately, as blur is fired on b
right after.Here's a fiddle without using jQuery, producing the same behavior.
The blur event fires when an element has lost focus. The main difference between this event and focusout is that focusout bubbles while blur does not. The opposite of blur is focus . This event is not cancelable and does not bubble.
If you want to prevent the blur event from being fired, you have to do so when you are inside the mousedown event, you can do so by invoking the method preventDefault() on the event. Click the checkbox, focus input & then click the button, the textfield never loses focus now.
The main difference between this event and blur is that focusout bubbles while blur does not. The opposite of focusout is focusin .
In browsers, pressing the tab key when a control has focus will move it to the next element in the tab order, causing the current element to lose focus and dispatch a blur event.
As you know, the issue is that different browsers choose to call event handlers in different orders. One solution is to give the other events a chance to fire by setting a timer for 0
milliseconds, and then checking the fields to see which (if any) is focused.
a.onfocus = function() {show(b);};
a.onblur = function() {
setTimeout(function() {
//if neither filed is focused
if(document.activeElement !== b && document.activeElement !== a){
hide(b);
}
}, 0);
};
//same action as for a
b.onblur = a.onblur;
Tested in Chrome, Firefox, Internet Explorer, and Safari. See full working example (edited version of your fiddle) at JSFiddle.net.
You can use an extravarible to check whether b is focused before hiding b. It worked in IE, Chrome & Firefox. I don;t have any other browser. You can check it.
var focusedB = false;
$("#a").focus(function(){
$("#b").show();
});
//if b is focused by pressing tab bar.
$("#a").keydown(function(e){
if(e.which === 9){
focusedB = true;
}
});
$("#b").blur(function(){
$("#b").hide();
});
$("#a").blur(function(){
if(focusedB){
focusedB = false;
}else{
$("#b").hide();
}
});
$( "#b" ).mousedown(function() {
focusedB = true;
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With