0

我有一个搜索框,它具有我一直在构建的自动完成功能。我有几个问题。

两件事情:

  • 在自动完成/搜索词列表中上下箭头时,它包括那些被过滤器隐藏的词。如何确保只能遍历可见的列表项?

  • 当我按回车键从列表中选择一项时,下拉菜单仍然存在,因为它与搜索框中的单词匹配。

小提琴

一些代码:

$(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();
        }
    });
});
4

1 回答 1

1

关键是您只显示了 .filter() 调用中的元素,但这些元素仍然存在于同一个列表中。您需要创建另一个隐藏的列表,您将在其中放置隐藏的元素。每次用户更新搜索字段时,您必须检查两个列表中的每个元素:需要可见的将进入可见列表,您不想显示的将进入隐藏列表。

这是一个例子

$("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;
    }                                            
});

您现在每次都有两个列表要检查。现在无法像以前那样缓存 li 的结果,因为它们的数量和位置在不断变化。

在这里,我更改了您的代码以向您展示我的意思,可能存在一些错误,但您应该明白这一点。

于 2012-10-26T14:41:13.823 回答