There are two elements in play:
$('#myInput') // an input field for search $('#myList') // a list to display search results
I want to hide the list when the input no longer has focus, like so:
$('#myInput').blur(function() { $('#myList').hide(); });
This works great, except when a list item is clicked, because the blur event fires and hides the list before the click is registered. The goal is for the list to stay visible when any part of the list is clicked, even though this will cause the input to blur.
How can I do this? Thanks!
The blur event occurs when an element loses focus. The blur() method triggers the blur event, or attaches a function to run when a blur event occurs. Tip: This method is often used together with the focus() method.
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.
It looks like click event has lower priority than blur, so it is predictible behaviour that blur event fires first.
The blur event fires when focus is lost. By default, a div element cannot have the focus in the first place so it can't be lost. If you set tabindex on a div, then it can gain the focus, but you should almost always be using a more appropriate element (such as a button) when you think about making interactive controls.
You can accomplish this by keeping a global variable, and setTimouts, to wait a delay of 200ms and then check if one of the 2 elements have focus.
var keepFocus = false; function hideList(){ if(!keepFocus){ $('#myList').hide(); } } $('#myInput').blur(function() { keepFocus = false; window.setTimeout(hideList, 200); }).focus(function(){ keepFocus = true; }); $('#myList').blur(function() { keepFocus = false; window.setTimeout(hideList, 200); }).focus(function(){ keepFocus = true; });
I've faced with the exact same problem, so this is how I solved it.
I came up with the fact that blur()
fires earlier than click()
.
So I've tried to change click()
to mousedown()
and found out that mousedown()
fires before blur()
.
And to imitate click()
you'll have to fire mousedown()
and then mouseup()
So in your case I would do something like this:
var click_in_process = false; // global $('#myList').mousedown(function() { click_in_process = true; }); $('#myList').mouseup(function() { click_in_process = false; $('#myInput').focus(); // a code of $('#myList') clicking event }); $('#myInput').blur(function() { if(!click_in_process) { $('#myList').hide(); // a code of what you want to happen after you really left $('#myInput') } });
Demo / example: http://jsfiddle.net/bbrh4/
Hope it helps!
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