jQuery使用多个选择框过滤列表

时间:2012-08-24 14:22:23

标签: jquery list filter

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

我已成功使用一个选择框成功完成此操作。

<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>

脚本

 var names = $('#names li').clone();

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

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

这几乎可行,我可以在第一个选择框中选择GM,列表会将<li>更改为

  • 雪佛兰[GM]
  • 别克[GM]

如果我然后使用第二个选择框选择Buick [GM]<li>将更改为仅显示

  • 别克[GM]

这就是我想要的。但是我发现如果第二个盒子选择本田它会显示

  • 思域[本田]
  • 雅阁[本田]

我的问题是如何将两者结合在一起,以便将GM和Honda一起使用?

没有任何过滤器的列表是:

  • 雪佛兰[GM]
  • 别克[GM]
  • 别克[GM]
  • 别克[GM]
  • 思域[本田]
  • 雅阁[本田]
  • 焦点[福特]

当我们从第一个过滤器中选择GM时,它会显示

  • 雪佛兰[GM]
  • 别克[GM]
  • 别克[GM]
  • 别克[GM]

因此,如果我们选择'Buick [GM]'形成第二个过滤器,则列表现在显示

  • 别克[GM]
  • 别克[GM]
  • 别克[GM]

这是正确的,但第二个过滤器设置为福特列表将显示

  • 焦点[福特]

所以过滤器不能一起工作

2 个答案:

答案 0 :(得分:0)

您应该合并两个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 );
    }
});​

这是小提琴:http://jsfiddle.net/EfEYQ/


上述解决方案有效,但我建议你不要乱用DOM。相反,您应该在CSS中使用hidden类,然后只需要在要显示的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');
    }
});​

这是小提琴:http://jsfiddle.net/89qbV/


在评论中进一步澄清后,我认为这可能是您正在寻找的内容:

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');
    }
});​

这是小提琴:http://jsfiddle.net/WfNav/

答案 1 :(得分:0)

我使用你以前的代码接近这个,我不确定'ALL'的行为所以我只有第一个选择元素优先(如果首先是全部,所有都显示)。如果你想要,你可以添加到filterNames()|| val2 ==='ALL'

此外,在您的代码中,我注意到第二个select元素的更改事件在第一个元素更改之前未被挂钩。所以就是这样。

希望这有帮助!

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');
}