Mathias Syversen
Mathias Syversen

Reputation: 51

Show / Hide divs based on search.keypress (filter)

I have a webpage with lots of "cards" I want to filter away some cards as I type into the search field, and when I remove a character, show them again (all when empty).

My problem is that it does not seem to work properly, it is "1 character behind" what I write, it also dont show the cards when I remove characters.

It also wont work when I finally write the whole criteria, it will find 3-4 cards when I am missing some letters.

This is the code I have atm:

$('#search').keypress(function(){
        $( ".champion" ).each(function( index ) {
            if ( $( this ).find('.name-tag').text().toLowerCase().indexOf($('#search').val().toLowerCase(), 0) == -1) {
                $(this).hide();
            } else {
                $(this).show();
            }
        });
    });

I have also tried swapping it around:

$('#search').keypress(function(){
    $( ".champion" ).each(function( index ) {
        if ( $('#search').val().toLowerCase().indexOf($( this ).find('.name-tag').text().toLowerCase()) == -1) {
            $(this).css('opacity', '0.7');
        } else {
            $(this).css('opacity', '1');
        }
    });
});

Upvotes: 3

Views: 2117

Answers (3)

Prateek
Prateek

Reputation: 4500

Since you are using "keypress", it will always give you the value which is "1 character behind". Better use "keyup" event.

I think you are trying to toggle the opacity based on entered search text. If its the same what you are looking for, Check this fiddle :

Live Example

JS Code :

$(function () {

    $("#search").keyup(function(){
        var $target = $("#target"); $target.find("li.champion").css("opacity", "0.7");
        $target.find("li.champion:contains('"+this.value+"')").css("opacity","1");
    });
});

HTML :

<input type="text" id="search" placeholder="type in here" />

<ul id="target">
    <li class="champion">
        <span class="name-tag">abcd</span>
    </li>
    <li class="champion">
        <span class="name-tag">abcd</span>
    </li>
    <li class="champion">
        <span class="name-tag">deds</span>
    </li>
    .....

</ul>

Here is how its done :

  1. Add "onKeyUp" event listener on "search" field

  2. Using jQuery ":contains" selector we are setting the opacity to "1" for the matched element, and for others to "0.7" For more detail about ":contains" selector, Check here.

Hope it helps.

Upvotes: 1

Mathias Syversen
Mathias Syversen

Reputation: 51

thank you for the keyup / keydown and delay tips.

Turned out I had to store the values before doing the test, this is the final code:

$('#search').keydown(function () {     
setTimeout(function () {
            $( ".champion" ).each(function( index ) {
            var nameTag = $( this ).find('.name-tag').text().toLowerCase();
            var searchStr = $('#search').val().toLowerCase();

            if (nameTag.indexOf(searchStr) == -1) {
                $(this).hide();
            } else {
                $(this).show();
            }
        });          
        }, 10);

});

Upvotes: 1

michaeln
michaeln

Reputation: 1052

This can be achieved by delaying the event by about 10ms, the user won't notice a difference, but it'll help you on your side.

I made a fiddle for your problem.

Here's what it basically does:

$(function () {

    var input = $("#entry");
    input.keydown(function () {
        // doesn't matter if you create an anonymous method or a regular method, only the setTimeout is of value

        setTimeout(function () {
            var s = $("#show");
            s.text(input.val());            
        }, 10);

    });
});

Your second problem is based on the keypress event which seems to not capture the backspace key. You're better of with using the keydown event handler as this does capture every key.

Upvotes: 1

Related Questions