我需要能够使用多个选择框在客户端提交一个长列表。
我已成功使用一个选择框成功完成此操作。
<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>
更改为
如果我然后使用第二个选择框选择Buick [GM]
,<li>
将更改为仅显示
这就是我想要的。但是我发现如果第二个盒子选择本田它会显示
我的问题是如何将两者结合在一起,以便将GM和Honda一起使用?
没有任何过滤器的列表是:
当我们从第一个过滤器中选择GM时,它会显示
因此,如果我们选择'Buick [GM]'形成第二个过滤器,则列表现在显示
这是正确的,但第二个过滤器设置为福特列表将显示
所以过滤器不能一起工作
答案 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');
}
});
答案 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');
}