34

I'm working on a project with an autocomplete searchbox. Now I have the issue that I want to pass the value from the found autocompleteresults to the input box, but on the same time, I want the autocompletebox to hide when the inputfield is not more focused.

Now I have a conflict going on with both of them since the click on the autocompletebox is seen as focusout and hide the box even before it can pass the value. Any pointers or workarounds for this kind of issue? Here a jsfiddle to make it more clear to you.

http://jsfiddle.net/KeGvM/

Or here

CSS:

#a_c {display:none;}​

JS:

$('#search_field').focusout(function() {
    $('#a_c').hide(); // IF I DELETE THIS IT WORKS
});

$('#search_field').focusin(function() {
    $('#a_c').show();
});

$('#a_c a').click(function() {
    $('#search_field').val('');
    var value = $(this).text();
    var input = $('#search_field');
    input.val(input.val() + value);
    $('#a_c').hide();
    return false;
});​

HTML:

<input autocomplete="off" onkeyup="searchFor(this.value);" name="search" id="search_field" class="bold" type="text" placeholder="Search...">
<div id="a_c"><a href="">hello world</a></div>​
Blazemonger
  • 90,923
  • 26
  • 142
  • 180
Johnny000
  • 2,058
  • 5
  • 30
  • 59

3 Answers3

40

The way I solved this was using the mousedown event instead of click. The mousedown event is always triggered before the focusout event while click is not.

You can try it out in the little demo below. Focus on the field and then click on the button.

const field = document.getElementById('field');
const btn = document.getElementById('btn');

btn.addEventListener('click', () => console.log('Click'));
btn.addEventListener('mousedown', () => console.log('Mouse down'));
field.addEventListener('focusout', () => console.log('Focus out'));
<input id="field">
<button id="btn">Try it</button>

As you can see the output is in the following order:

  1. Mouse down
  2. Focus out
  3. Click

This is the most stable solution without using any workaround hacks like timeouts. It also does not depend on jQuery. The only thing worth noting that mousedown does not wait for the user to release their mouse button, but in terms of user experience that is not really a concern here.

Duncan Lukkenaer
  • 12,050
  • 13
  • 64
  • 97
34

How about using

:hover

I solved same problem using it.

$('className').on('focusout', function(e) {
    if($('.suggestLi' + ':hover').length) {
        return;
    }
    $('.suggestList').empty();
});
Ganesh Yadav
  • 2,607
  • 2
  • 29
  • 52
keiwt
  • 499
  • 5
  • 5
  • 2
    I think this is the best solution. I've used that and it works perfectly. Thanks! – ZanattMan May 26 '15 at 15:07
  • 3
    This is the most elegant solution I've found on the internet. Thanks. – Lei Chen Apr 02 '16 at 00:40
  • Not work if mouse hover suggestList and i will press TAB (like move to next input) (instead click) **[JSFIDDLE](http://jsfiddle.net/KeGvM/61/)** – bsbak Jul 25 '17 at 11:32
32

My solution in the similar situation was using timeout to temporarily hold off the action taken in blur event handler. Like this:

$('#search_field').focusout(function() {
    window.setTimeout(function() { $('#a_c').hide() }, 100);
});
raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • 2
    i had a similar issue like the op, and i decided to use this dirty fix as a solution (last resort and im on a deadline must fix this asap). This puts the events in race condition and its a very very bad practice. i will use this, thanks for this answer, but will downvote. waiting for a better answer. – Sharky Feb 13 '15 at 13:34
  • that was an awesome solution .. +1. I was validating - Is valid Email using txtEmailfield focusout event. if invalid email is typed with cursor focused and immediately click the form clear button. which causes the conflict. now i covered the code with your timeout and not blank condition. Thank you – Pranesh Janarthanan Feb 26 '19 at 15:03
  • @raina77ow, I am facing a different issue for focusout validation code, if the validation is triggered with a popup, click ok button closes the popup button. if swap the window using `Alt+Tab` and swap it back to application window the popup is keep on araising. how to fix this? – Pranesh Janarthanan Feb 27 '19 at 07:02
  • @PraneshJanarthanan Depends. For example, you might want to limit the number of popup displays for a given input (i.e., if nothing has changed since the last time popup has been shown, why show it?) Still, think about the state a user arrives to: if they switch back to that window after a long period of inactivity, do they always remember what exactly should be done? – raina77ow Feb 27 '19 at 08:52
  • @raina77ow, i got your point i need to check the data update before and after validation so that i can skip it? But what i did is.. On validation I added `inputDomElement.focus()`. which triggered looping of popup validation when the window is swapped. Now i removed `focus` and fixed the issue. – Pranesh Janarthanan Mar 01 '19 at 09:43