Jon
Jon

Reputation: 3184

Arrowing through a list using jQuery

I have a search box which has an auto-complete feature that I've been building. I'm having a couple issues.

Two things:

FIDDLE

Some code:

$(document).ready(function() {
    $("#dropdown").hide();
    $("input").keyup(function() {
        if (this.value.length) {
            var that = this;
            $("#dropdown li").hide().filter(function() {
                return $(this).html().toLowerCase().indexOf(that.value.toLowerCase()) !== -1;
            }).show();
            $("#dropdown").show();
        }
        else {
            $("#dropdown").hide();
        }
    });

    $('li').click(function() {
        $('#search').val($(this).text());
        $("#dropdown").hide();
    });

    var li = $('li');
    var liSelected;

    $('input').keydown(function(e) {
        if(e.which === 40) {
            if(liSelected) {
                liSelected.removeClass('selected');
                next = liSelected.next();
                if(next.length > 0) {
                    liSelected = next.addClass('selected');
                    $('#search').val(liSelected.text());
                }
                else {
                    liSelected = li.eq(0).addClass('selected');
                }
            }
            else {
                liSelected = li.eq(0).addClass('selected');
            }
        }
        else if(e.which === 38) {
            if(liSelected) {
                liSelected.removeClass('selected');
                next = liSelected.prev();

                if(next.length > 0) {
                    liSelected = next.addClass('selected');
                }
                else {
                    liSelected = li.last().addClass('selected');
                }
            }
            else {
                liSelected = li.last().addClass('selected');
            }
        }
        else if(e.which === 13) {
            $('#search').val(liSelected.text());
            $("#dropdown").hide()
            $('#search').blur();
        }
    });
});

Upvotes: 0

Views: 104

Answers (1)

Jose Faeti
Jose Faeti

Reputation: 12294

The point is you are showing only elements out of a .filter() call, but the elements are still present in the same list. You need to create another list, hidden, where you will put the hidden elements. Each time the user update the search field, you have to check each element in both lists: the one who needs to be visible will go in the visible list, the ones you don't want to show will go in the hidden list.

Here's an example

$("input").keyup(function(e) {
    if (this.value.length) {
        var that = this;
        $("#dropdown li").each(function() {

            if ( $(this).html().toLowerCase().indexOf(that.value.toLowerCase()) == -1 )
                $(this).appendTo($hidden);
        });
        $('#hidden li').each(function() {
            if ( $(this).html().toLowerCase().indexOf(that.value.toLowerCase()) !== -1 )
                $(this).appendTo('#list');
        });
        $("#dropdown").show();
    }
    else {
        $("#dropdown").hide();
    }
    if ( e.which !== 40 && e.which !== 38 )
    {
        $('#dropdown li,#hidden li').each( function() {
            $(this).removeClass( 'selected' );
        });
        liSelected = null;
    }                                            
});

You now have two lists to check every time. Caching the results of the li's is not possible now like you were doing before, as their number and position is constantly changing.

Here I changed your code to show you what I mean, there may be some bugs but you should get the point.

Upvotes: 1

Related Questions