1

I would like to compare a input against li elements but for some reason it's only checking the last li element. You can see this when running the script below everything with "test" works fine but not for "example" or "example 2"

$(document).ready(function() {
    var $input = $('#autocomplete');
    $(document).on('keyup', $input, function() {
        var $val = $input.val().trim(),
            $select = $('.autocomplete-content');

        // Check if the input isn't empty
        if ($val != '') {
            $select.children('li').each(function() {
                var $li = $(this),
                    $html = $li.html(),
                    $text = $li.text().trim();

                // Set input value
                $li.click(function() {
                    $input.val($text);
                });

                // Check if the value has at least 1 match else hide
                if ($text.indexOf($val) !== -1) {
                    // Remove class hide when input changes and finds a match
                    if ($li.hasClass('hide')) {
                        $li.removeClass('hide');
                    }

                    // Unhide "ul.autocomplete-content"
                    if ($select.hasClass('hide')) {
                        $select.removeClass('hide'); // Show options
                    }
                } else {
                    $li.addClass('hide');
                    $select.addClass('hide'); // Hide options
                }
            });
        } else {
            $select.addClass('hide');
        }
    });
});
.hide {
  display: none;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="autocomplete" class="autocomplete">

<ul class="autocomplete-content hide">
  <li><img src="test.jpg"> example</li>
  <li><img src="test.jpg"> example 2</li>
  <li><img src="test.jpg"> test</li>
</ul>

So my question is how can I compare the input against each li element. Thanks in advance.

Update

Something I forgot to mention was that in the li element could be an img thats the reason why I used $li.text()

SuperDJ
  • 7,488
  • 11
  • 40
  • 74
  • 1
    Have you considered [datalists](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist)? – Hatchet Jan 16 '16 at 18:25
  • @Hatchet didn't know that existed but it's not quite what I'm looking for in connection with styling etc. – SuperDJ Jan 16 '16 at 18:29
  • You're adding a new `click` handler on each `keyup` event – Andreas Jan 16 '16 at 18:30
  • @Andreas how is this related on comparing strings as it's only setting the value of the input? – SuperDJ Jan 16 '16 at 18:31
  • 1
    It's not related to your problem but it is an error in your script. `$li.click(function() { $input.val($text) })` adds a new click handler. After the first `keyup` there is one click handler which fills the input, after the second `keyup` there are two click handler which fill the input, after the third `keyup` there are three ... – Andreas Jan 16 '16 at 18:35

3 Answers3

3

Instead of looping through all the li's when anything is entered in the input, you can try to use the pseudo selector :contains. This finds all elements with the text we have provided and if your intention is to find elements which starts with the search string, then you might need to improvise a little. This thread might be helpful.

$(document).ready(function() {
  var $input = $('#autocomplete');
  $(document).on('keyup', $input, function() {
    var $val = $input.val().trim(),
        $select = $('.autocomplete-content');
    // Check if the input isn't empty
    if ($val != '') {
      $select.children('li').addClass('hide')
      $select.children('li').filter(function() { 
       console.log($(this).text().indexOf($val))
       return $(this).text().indexOf($val) !== -1; 
      }).removeClass('hide');
    } else {
      $select.children().addClass('hide');
    }
  });
});
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="autocomplete" class="autocomplete">

<ul class="autocomplete-content">
  <li class="hide"><img src="test.jpg"> example</li>
  <li class="hide"><img src="test.jpg"> example 2</li>
  <li class="hide"><img src="test.jpg"> test</li>
</ul>
Community
  • 1
  • 1
rrk
  • 15,677
  • 4
  • 29
  • 45
  • You really need to explain what you've changed to make this work; as it is to work out the changes we'd need to play spot-the-difference with your code and the OP's, which is unnecessarily tedious. Also, without explanation, it's difficult for anyone to learn anything from this answer. – David Thomas Jan 16 '16 at 18:35
  • @DavidThomas Sorry about that. I am in the process of editing the answer. – rrk Jan 16 '16 at 18:36
  • @SuperDJ let me see. – rrk Jan 16 '16 at 18:54
  • @SuperDJ Please, check the answer now. – rrk Jan 16 '16 at 19:03
1

Need to remove $select.addClass('hide');. It's called when the input does not match test, even when it may match example.

$(document).ready(function() {
    var $input = $('#autocomplete');
    $(document).on('keyup', $input, function() {
        var $val = $input.val().trim(),
            $select = $('.autocomplete-content');

        // Check if the input isn't empty
        if ($val != '') {
            $select.children('li').each(function() {
                var $li = $(this),
                    $html = $li.html(),
                    $text = $li.text().trim();

                // Set input value
                $li.click(function() {
                    $input.val($text);
                });

                // Check if the value has at least 1 match else hide
                if ($text.indexOf($val) !== -1) {
                    // Remove class hide when input changes and finds a match
                    if ($li.hasClass('hide')) {
                        $li.removeClass('hide');
                    }

                    // Unhide "ul.autocomplete-content"
                    if ($select.hasClass('hide')) {
                        $select.removeClass('hide'); // Show options
                    }
                } else {
                    $li.addClass('hide');
                    //$select.addClass('hide'); // Hide options
                }
            });
        } else {
            $select.addClass('hide');
        }
    });
});
.hide {
  display: none;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="autocomplete" class="autocomplete">

<ul class="autocomplete-content hide">
  <li>example</li>
  <li>example 2</li>
  <li>test</li>
</ul>
Fabricator
  • 12,722
  • 2
  • 27
  • 40
1

You have to set class hide to li instead of ul On keyup event of #autocomplete iterate through the lis, which one contains the textbox value remove class hide from that and add class hide which one not contains.

$(document).on('keyup', '#autocomplete', function () {
    var text = $(this).val();

    $('.autocomplete-content li').each(function () {
        if ($(this).text().trim().indexOf(text) > -1) {
           $(this).removeClass('hide');
        } else {
           $(this).addClass('hide');
        }
    });
});
.hide {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" id="autocomplete" class="autocomplete">
<ul class="autocomplete-content">
  <li class="hide"><img src="test.jpg"> example</li>
  <li class="hide"><img src="test.jpg"> example 2</li>
  <li class="hide"><img src="test.jpg"> test</li>
</ul>
Ibrahim Khan
  • 20,616
  • 7
  • 42
  • 55
  • In what way "*may it help*"? What's different, and why? Where was the error in the original code, how did that error cause the code to not work as intended? – David Thomas Jan 16 '16 at 18:38