jQuery: Prevent focus loss of input when clicking on specific element

I have an input that contains a custom drop down menu. When you click on a menu item it should set the value of the input to the text of the item. I also want the menu to hide when the input loses focus. This has created a problem, where clicking a menu item makes the input lose focus and hide the menu before the click event for the menu item can be run. How do I fix this?

$(document).on('click', '#inputMenu li', function (e) {
    $('#input').val($(this).text());
    $('#inputMenu').removeClass('active');
    e.preventDefault();
    return false
});
  
$('#input').on('focusout',function(e) {
    $('#inputMenu').removeClass('active');
});
 
$('#input').on('input',function(e) {
    $('#inputMenu').addClass('active');
});
#inputMenu {
  display: none;
}

#inputMenu.active {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input" type="text" placeholder="type something">
<ul id="inputMenu">
  <li>Click me to set text 1</li>
  <li>Click me to set text 2</li>
  <li>Click me to set text 3</li>
  <li>Click me to set text 4</li>
</ul>

Upvotes: 6

Views: 4610

Answers (2)

Ahmad Maleki
Ahmad Maleki

Reputation: 1493

This problem is caused by the order of events. There is a trick you can use, replace click event with mousedown which is fired before focusout.

$(document).on('mousedown', '#inputMenu li', function (e) {
    $('#input').val($(this).text());
    $('#inputMenu').removeClass('active');
    e.preventDefault();
    return false
});
  
$('#input').on('focusout',function(e) {
    $('#inputMenu').removeClass('active');
});
 
$('#input').on('input',function(e) {
    $('#inputMenu').addClass('active');
});
#inputMenu {
  display: none;
}

#inputMenu.active {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="input" type="text" placeholder="type something">
<ul id="inputMenu">
  <li>Click me to set text 1</li>
  <li>Click me to set text 2</li>
  <li>Click me to set text 3</li>
  <li>Click me to set text 4</li>
</ul>

Credits:

This answer was originally posted here

Upvotes: 11

Haris
Haris

Reputation: 1

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.js"></script>
</head>
<body>
    <ul id="inputMenu">
        <li>test 1</li>
        <li>test 2</li>
        <li>test 3</li>
        <li>test 4</li>
        <li>test 5</li>
    </ul>
    <input type="text" name="name" id="input">
    <script type="text/javascript">
        $(document).on('click', '#inputMenu li', function (e) {
            $('#input').val($(this).text()).focus();
        });
        $('#input').on('focusout',function(e) {
            let curElem = this;
            $('#inputMenu li:visible').each(function(){
                if($(curElem).val() == $(this).text())
                    $(this).hide()
            });
        });
    </script>
</body>
</html>

Upvotes: 0

Related Questions