以下是我的所有过滤器的HTML:
<div class="search-filters">
<div class="filter-block">
<label for="employee_type">Employee Type</label>
<select id="employee_type" class="category">
<option value="0">All</option>
<option value="designer">Designer</option>
<option value="manager">Manager</option>
<option value="developer">Developer</option>
<option value="quality-assurance">Quality Assurance</option>
</select>
</div>
<div class="filter-block">
<label for="years_xp">Years Experience</label>
<select id="years_xp" class="category">
<option value="0">Select years Experience</option>
<option value="1">1 year</option>
<option value="2">2 years</option>
<option value="3">3 years</option>
</select>
</div>
</div>
我的结果列表如下:
<ul class="result-set">
<li class="result" data-employee-type="designer" data-xp="3" >John Smith</li>
<li class="result" data-employee-type="manager" data-xp="2" >Billy Joe</li>
<li class="result" data-employee-type="developer" data-xp="5" >John Appleseed</li>
</ul>
所以我要做的是使用数据属性使用jQuery过滤结果,并选择更改下拉列表。现在只有一个或另一个过滤器可以使用下面的jQuery代码。我尝试在Jquery中使用.filter函数,但它仍然只在一个下拉列表更改时才有效。如果我改变它们似乎忽略了一个条件。
我的jQuery:
var category_filters = [];
$('.category').on('change', function() {
category_filters = [];
$('.search-filters select').each(function() {
if ($(this).val() != 0) {
var category = $(this).val();
category_filters[$(this).attr('id')] = category;
}
});
var employee_type = "";
var years_xp = "";
if ('employee_type' in category_filters) {
employee_type = category_filters['employee_type'];
}
if ('years_xp' in category_filters) {
years_xp = category_filters['years_xp'];
}
$(".result-set .result").hide().filter(function() {
if (employee_type != "") {
if ($(this).attr('data-employee-type') == employee_type) {
return true;
}
}
if (years_xp != "") {
if ($(this).attr('data-xp') == years_xp) {
return true;
}
}
}).show();
});
关于我做错的任何想法?我已经坚持了近6个小时了,看了看其他的例子,但它们似乎与我的情况无关。
答案 0 :(得分:2)
好的,所以你想要同时应用两个过滤器,而不是只要一个过滤器匹配就显示一个项目。在你的过滤函数中,一找到匹配就会返回true,这就是问题所在。
我继续并稍微更新了您的代码:
$('.category').on('change', function() {
var category_filters = [];
$('.search-filters select').each(function() {
if ($(this).val() != 0) {
category_filters[$(this).attr('id')] = $(this).val();
}
});
$(".result-set .result").hide().filter(function() {
var show = true;
for (var category in category_filters) {
show = show && $(this).data(category) == category_filters[category];
}
return show;
}).show();
});
演示:https://jsfiddle.net/04v4bqw5/1/
你会注意到我也进行了一些重构。此代码假定过滤器的id
与您要应用过滤器的数据属性的名称完全匹配,因此请务必检查更新的HTML。
javascript的重复次数少得多,您可以根据需要添加更多额外的过滤器和匹配的数据属性,并且无需更改javascript即可使用。
关于过滤功能,让我添加一些注释来解释
// assume we'll want to show the item
var show = true;
// go over each active filter
for (var category in category_filters) {
// check if the filter value matches the data attribute value, and any
// previous filters did not exclude this item yet (show &&)
show = show && $(this).data(category) == category_filters[category];
}
return show;
答案 1 :(得分:1)
您获得此结果的原因是return true;
的行为。可以把它想象成一个中断语句 - 只要在.filter
函数中达到它,就会认为它的工作已经完成,它可以停止处理。要解决这个问题,请使用一些本地布尔值,然后在函数末尾对它们进行评估,以决定是否返回true:
var etMatch = false, xpMatch = false;
if (employee_type != "") {
if ($(this).attr('data-employee-type') == employee_type) {
etMatch = true;
}
}
if (years_xp != "") {
if ($(this).attr('data-xp') == years_xp) {
xpMatch = true;
}
}
if (etMatch && xpMatch) { return true; }
答案 2 :(得分:0)
您应该为每个过滤器使用其功能进行比较:
var compare = {
"employee-type": function(a,b) { return a===b},
"years-xp": function(a,b) { return (1*a)<=(1*b) }
}
$(".result-set .result").show().filter(function() {
var self = this;
return
!Object
.keys(category_filters)
.reduce( function(result, i) {
var filterValue = category_filters[i];
var itemValue = $(self).attr('data-'+i);
return result && compare[ i ]( filterValue, itemValue)
}, true)
}).hide();