I have two elements:
The accepted answer will work as a quick fix, but by relying on a setTimeout, you assume that the user will only keep clicking down for less than n milliseconds before they release (just picture someone hesitating on a click). To be more sure that the click will go through, you could set a longer timeout, but that means your hide-able element will stay visible that much longer after the blur.
So let's look at the root of the problem.
The click event failing to go through is a result of the events being fired in the following order:
mousedownblurmouseupclickSo by the time the mouseup/click events are ready to fire, the blur listener has been called and the element you had once been hovering over has already disappeared.
Here's a general fix (based on the fact that the mousedown event fires first) that should work:
var searchEl = $('#search');
var listEl = $('#dropdown');
var keepListOpen = false;
searchEl
.on('focus', function() {
listEl.show();
})
.on('blur', function() {
// Hide the list if the blur was triggered by anything other than
// one of the list items
if (!keepListOpen) {
listEl.hide();
}
});
listEl.find('li')
.on('mousedown', function(event) {
// Keep the list open so the onClick handler can fire
keepListOpen = true;
})
.on('click', function(event) {
// Proof that the list item was clicked
alert('clicked option');
});
$(window).on('mouseup', function(event) {
// Return the keepListOpen setting to its default and hide the list
// *NOTE* We could have tied this handler to the list items,
// but it wouldn't have fired if a mousedown happened on a
// list item and then the user dragged the mouse pointer
// out of the area (or out of the window)
if (keepListOpen) {
listEl.hide();
keepListOpen = false;
}
});
// Bind to `window.top` if your page might be displayed in an iframe
// $(window.top).on('mouseup', function(event) {
// if (keepListOpen) {
// listEl.hide();
// keepListOpen = false;
// }
//});