jQuery使用多个选择框筛选列表

jQuery使用多个选择框筛选列表,jquery,list,filter,Jquery,List,Filter,我需要能够在客户端使用多个选择框归档一个长列表 我使用一个选择框成功地完成了这项工作 <select id="company"> <option selected="true" >ALL</option> <option>GM</option> <option>Honda</option> <option>Ford</option> </select> <

我需要能够在客户端使用多个选择框归档一个长列表

我使用一个选择框成功地完成了这项工作

<select id="company">
  <option selected="true" >ALL</option>
  <option>GM</option>
  <option>Honda</option>
  <option>Ford</option>
</select>

<select id="company2">
  <option selected="true" >ALL</option>
  <option>Buick [GM]</option>
  <option>Honda</option>
  <option>Ford</option>
</select>

<ul id="names" multiple="multiple" size="8">
  <li>Chevy [GM]</li>
  <li>Buick [GM]</li>
  <li>Civic [Honda]</li>
  <li>Accord [Honda]</li>
  <li>Focus [Ford]</li>
</ul>
这几乎起作用了,我可以在第一个选择框中选择GM,列表将
  • 更改为

    • 雪佛兰[通用]
    • 别克[通用]
    然后,如果我使用第二个选择框选择别克[GM],则
  • 将变为仅显示

    • 别克[通用]
    这就是我想要的。然而,我发现如果第二个框选择本田,它将显示

    • 思域[本田]
    • 雅阁[本田]
    我的问题是,我如何将这两者联系在一起,使其同时使用通用汽车和本田

    不带任何过滤器的列表为:

    • 雪佛兰[通用]
    • 别克[通用]
    • 别克[通用]
    • 别克[通用]
    • 思域[本田]
    • 雅阁[本田]
    • 福克斯[福特]
    ​当我们从第一个过滤器中选择GM时,它会显示

    • 雪佛兰[通用]
    • 别克[通用]
    • 别克[通用]
    • 别克[通用]
    因此,如果我们从第二个过滤器中选择“别克[GM]”,列表现在显示出来

    • 别克[通用]
    • 别克[通用]
    • 别克[通用]
    这是正确的,但是第二个过滤器设置为Ford,列表将显示

    • 福克斯[福特]

    所以过滤器不能一起工作​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

    您应该为两个
    select
    元素组合事件处理程序:

    var $names = $('#names'),
        $namesAll = $names.find('li'),
        $company1 = $('#company'),
        $company2 = $('#company2');
    
    $company1.add( $company2 ).change(function() {
    
        var val1 = $company1.val(),
            val2 = $company2.val();
    
        $names.empty();
    
        if ( val1 == 'ALL' && val2 == 'ALL' ) {
            $names.append( $namesAll );
        }
        else {
            $namesAll.filter(function(i, el) {
                var $el = $(el);
                return ~$el.text().indexOf( val1 ) || ~$el.text().indexOf( val2 );
            }).appendTo( $names );
        }
    });​
    
    这是小提琴:


    上面的解决方案是有效的,但我建议您不要对DOM太过麻烦。相反,您应该在CSS中有一个
    隐藏的
    类,然后在要显示的
    li
    上切换该类:

    var  $names = $('#names li'),
         $company1 = $('#company'),
         $company2 = $('#company2');
    
    $company1.add( $company2 ).change(function() {
    
        var val1 = $company1.val(),
            val2 = $company2.val();
    
        if ( val1 == 'ALL' && val2 == 'ALL' ) {
            $names.removeClass('hidden');
        }
        else {
            $names.addClass('hidden').filter(function(i, el) {
                var $el = $(el);
                return ~$el.text().indexOf( val1 ) || ~$el.text().indexOf( val2 );
            }).removeClass('hidden');
        }
    });​
    
    这是小提琴:


    在评论中进一步澄清后,我认为这可能是您想要的:

    var  $names = $('#names li'),
         $company1 = $('#company'),
         $company2 = $('#company2');
    
    $company1.add( $company2 ).change(function() {
    
        var val1 = $company1.val(),
            val2 = $company2.val();
    
        if ( val1 == 'ALL' && val2 == 'ALL' ) {
            $names.removeClass('hidden');
        }
        else {
            $names.addClass('hidden').filter(function(i, el) {
    
                var $el = $(el),
                    include = true;
    
                if ( val1 != 'ALL' && !~$el.text().indexOf( val1 ) ) include = false;
                if ( val2 != 'ALL' && !~$el.text().indexOf( val2 ) ) include = false;
    
                return include;
    
            }).removeClass('hidden');
        }
    });​
    

    问题是:

    我是使用您以前的代码来解决这个问题的,但我不确定'ALL'的行为,所以我只有第一个select元素优先(如果first是ALL,则显示ALL)。如果需要,只需添加到filterNames()| | val2=='ALL'

    另外,在您的代码中,我注意到第二个select元素上的change事件在第一个元素更改之前不会挂接。就是这样

    希望这有帮助

    var names = $('#names li').clone();
    
    $('#company').change(function() {
        var val = $(this).val();
        var val2 = $('#company2').val();
        filterNames(val, val2);
    });
    
    $('#company2').change(function() {
        var val = $('#company').val();
        var val2 = $(this).val();
        filterNames(val, val2);
    });
    
    function filterNames(val, val2) {
        $('#names').empty();
        names.filter(function(idx, el) {
            return val === 'ALL' || $(el).text().indexOf( val ) >= 0 || $(el).text().indexOf( val2 ) >= 0;
        }).appendTo('#names');
    }
    

    我真的不明白你在追求什么。你能更详细地解释一下吗?那太好了,我真的应该把所有的代码都贴出来。然而,你的解决方案让我在选择通用汽车后仍然选择本田。@JasonBruce-这不是你想要的吗?不,我应该只能进一步过滤结果,即在选择通用汽车后,本田在选择通用汽车后,列表不应更新。仅当新列表中显示的选项为selected@JasonBruce-我不确定我是否完全理解你,但我在答案中添加了一些代码。希望对你有帮助,就这样谢谢你!对不起,没有正确地解释我自己
    var names = $('#names li').clone();
    
    $('#company').change(function() {
        var val = $(this).val();
        var val2 = $('#company2').val();
        filterNames(val, val2);
    });
    
    $('#company2').change(function() {
        var val = $('#company').val();
        var val2 = $(this).val();
        filterNames(val, val2);
    });
    
    function filterNames(val, val2) {
        $('#names').empty();
        names.filter(function(idx, el) {
            return val === 'ALL' || $(el).text().indexOf( val ) >= 0 || $(el).text().indexOf( val2 ) >= 0;
        }).appendTo('#names');
    }