【问题标题】:jQuery filter a list using multiple select boxesjQuery使用多个选择框过滤列表
【发布时间】:2012-08-20 03:02:07
【问题描述】:

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

我已经使用一个选择框成功地做到了这一点。

<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,列表会将&lt;li&gt; 更改为

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

如果我随后使用第二个选择框选择 Buick [GM]&lt;li&gt; 将变为仅显示

  • 别克 [GM]

这是我想要的。但是我发现如果第二个框选择 Honda,它将显示

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

我的问题是如何将两者链接在一起,以便同时使用通用和本田?

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

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

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

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

所以如果我们从第二个过滤器中选择“别克 [GM]”,列表现在会显示

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

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

  • 专注 [福特]

所以过滤器没有协同工作​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

【问题讨论】:

  • 我真的不明白你在做什么。能详细解释一下吗?

标签: jquery list filter


【解决方案1】:

您应该将两个 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 类,然后只需在您要显示的 lis 上切换该类:

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/


在 cmets 进一步澄清后,我认为这可能是您正在寻找的:

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/

【讨论】:

  • 太好了,我应该真正发布小提琴而不是所有代码。但是,您的解决方案让我在选择 GM 后仍然选择本田。
  • @JasonBruce - 这不是你想要的吗?
  • 不,我应该只能进一步过滤结果,即在选择 GM 并且在 GM 之后选择本田之后,列表不应更新。只有在选择了新列表中显示的选项时,它才会更新
  • @JasonBruce - 我不确定我是否完全理解你,但我在答案中添加了一些代码。希望对你有帮助。
  • 就是这样,谢谢!很抱歉没有正确地解释我自己
【解决方案2】:

我使用您之前的代码解决了这个问题,但我不确定 'ALL's 的行为,所以我只有第一个选择元素优先(如果第一个是全部,则显示全部)。如果你愿意,你可以添加到 filterNames() || val2 === '全部'

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

希望这会有所帮助!

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

【讨论】:

    猜你喜欢
    • 2019-10-07
    • 2012-11-09
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2019-10-08
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    相关资源
    最近更新 更多