显示与多个选定数据属性匹配的元素
Show elements matching multiple selected data attributes
我正在创建一组过滤器,一旦它们被 selected,相应的 div 应该基于被 selected 的所有属性显示。
我可以让它一次工作一个,但我的问题是试图让它们一起工作。我觉得一般来说可能有更好的方法?
这是我的 select 菜单:
<div class="filters">
<select class="filter-location">
<option value="" disabled="" selected="">Location</option>
<option data-location="Remote">Remote – United States</option>
<option data-location="Portland, OR">Portland, OR</option>
<option data-location="Seattle, WA">Seattle, WA</option>
</select>
<select class="filter-team">
<option value="" disabled="" selected="">Team</option>
<option data-team="Sales">Sales</option>
<option data-team="Support">Support</option>
<option data-team="Management">Management</option>
</select>
<select class="filter-type">
<option value="" disabled="" selected="">Type</option>
<option data-type="Full-Time">Full-Time</option>
<option data-type="Contract">Contract</option>
</select>
</div>
这是我的 HTML 标记的简化版本:
<div class="job" data-team="Sales" data-location="Remote" data-type="Full-Time">
<p>Job Content Here</p>
</div>
<div class="job" data-team="Management" data-location="Portland, OR" data-type="Contract">
<p>Job Content Here</p>
</div>
<div class="job" data-team="Sales" data-location="Seattle, WA" data-type="Full-Time">
<p>Job Content Here</p>
</div>
这是我的jQuery,一次显示一个过滤器:
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.filters select').on('change', function() {
var location_value = $(':selected', this).data('location');
var team_value = $(':selected', this).data('team');
var type_value = $(':selected', this).data('type');
$('.job').hide();
$(".job").each(function( index ) {
if ($(this).data('location') == location_value) {
$(this).show();
}
if ($(this).data('team') == team_value) {
$(this).show();
}
if ($(this).data('work_type') == type_value) {
$(this).show();
}
});
});
});
</script>
以下为每个 <select>
创建一个过滤器对象数组,其值如下所示:
[
{
"filter": "location",
"value": "Remote"
},
{
"filter": "team",
"value": "Sales"
}
]
然后它使用 Array#every() 来确保每个过滤器都与职位的 data-
属性相匹配,以确定是否显示它。
请注意,我使 <select>
元素更加通用,并为每个元素添加了一个 data-filter
属性,并且只在 <option>
元素上使用了 value
const $sels = $('.filters select'),
$jobs = $('.job')
$sels.change(function(){
const filters = $sels.filter(function(){
return !!this.value
}).map(function(){
return {filter: $(this).data('filter'), value : this.value}
}).get();
//console.log('Filters', filters)
// hide all jobs then filter the ones to show
const $filterJobs = $jobs.hide().filter(function(){
const data = $(this).data()
return filters.every(function(obj){
return data[obj.filter] === obj.value
});
}).show();
// toggle "no-match" depending on length of filter jobs collection
$('#no-match').toggle( !$filterJobs.length )
});
.job, #no-match {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filters">
<select data-filter="location">
<option value="">Location</option>
<option value="Remote">Remote – United States</option>
<option value="Portland, OR">Portland, OR</option>
<option value="Seattle, WA">Seattle, WA</option>
</select>
<select data-filter="team">
<option value="">Team</option>
<option value="Sales">Sales</option>
<option value="Support">Support</option>
<option value="Management">Management</option>
</select>
<select data-filter="type">
<option value="">Type</option>
<option value="Full-Time">Full-Time</option>
<option value="Contract">Contract</option>
</select>
</div>
<div id="no-match">
<h3>No Match</h3>
</div>
<div class="job" data-team="Sales" data-location="Remote" data-type="Full-Time">
<p>Sales Remote Full Time</p>
</div>
<div class="job" data-team="Management" data-location="Portland, OR" data-type="Contract">
<p>Management Portland Contract</p>
</div>
<div class="job" data-team="Sales" data-location="Seattle, WA" data-type="Full-Time">
<p>Sales Seattle Full Time</p>
</div>
我正在创建一组过滤器,一旦它们被 selected,相应的 div 应该基于被 selected 的所有属性显示。
我可以让它一次工作一个,但我的问题是试图让它们一起工作。我觉得一般来说可能有更好的方法?
这是我的 select 菜单:
<div class="filters">
<select class="filter-location">
<option value="" disabled="" selected="">Location</option>
<option data-location="Remote">Remote – United States</option>
<option data-location="Portland, OR">Portland, OR</option>
<option data-location="Seattle, WA">Seattle, WA</option>
</select>
<select class="filter-team">
<option value="" disabled="" selected="">Team</option>
<option data-team="Sales">Sales</option>
<option data-team="Support">Support</option>
<option data-team="Management">Management</option>
</select>
<select class="filter-type">
<option value="" disabled="" selected="">Type</option>
<option data-type="Full-Time">Full-Time</option>
<option data-type="Contract">Contract</option>
</select>
</div>
这是我的 HTML 标记的简化版本:
<div class="job" data-team="Sales" data-location="Remote" data-type="Full-Time">
<p>Job Content Here</p>
</div>
<div class="job" data-team="Management" data-location="Portland, OR" data-type="Contract">
<p>Job Content Here</p>
</div>
<div class="job" data-team="Sales" data-location="Seattle, WA" data-type="Full-Time">
<p>Job Content Here</p>
</div>
这是我的jQuery,一次显示一个过滤器:
<script type="text/javascript">
jQuery(document).ready(function($) {
$('.filters select').on('change', function() {
var location_value = $(':selected', this).data('location');
var team_value = $(':selected', this).data('team');
var type_value = $(':selected', this).data('type');
$('.job').hide();
$(".job").each(function( index ) {
if ($(this).data('location') == location_value) {
$(this).show();
}
if ($(this).data('team') == team_value) {
$(this).show();
}
if ($(this).data('work_type') == type_value) {
$(this).show();
}
});
});
});
</script>
以下为每个 <select>
创建一个过滤器对象数组,其值如下所示:
[
{
"filter": "location",
"value": "Remote"
},
{
"filter": "team",
"value": "Sales"
}
]
然后它使用 Array#every() 来确保每个过滤器都与职位的 data-
属性相匹配,以确定是否显示它。
请注意,我使 <select>
元素更加通用,并为每个元素添加了一个 data-filter
属性,并且只在 <option>
元素上使用了 value
const $sels = $('.filters select'),
$jobs = $('.job')
$sels.change(function(){
const filters = $sels.filter(function(){
return !!this.value
}).map(function(){
return {filter: $(this).data('filter'), value : this.value}
}).get();
//console.log('Filters', filters)
// hide all jobs then filter the ones to show
const $filterJobs = $jobs.hide().filter(function(){
const data = $(this).data()
return filters.every(function(obj){
return data[obj.filter] === obj.value
});
}).show();
// toggle "no-match" depending on length of filter jobs collection
$('#no-match').toggle( !$filterJobs.length )
});
.job, #no-match {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filters">
<select data-filter="location">
<option value="">Location</option>
<option value="Remote">Remote – United States</option>
<option value="Portland, OR">Portland, OR</option>
<option value="Seattle, WA">Seattle, WA</option>
</select>
<select data-filter="team">
<option value="">Team</option>
<option value="Sales">Sales</option>
<option value="Support">Support</option>
<option value="Management">Management</option>
</select>
<select data-filter="type">
<option value="">Type</option>
<option value="Full-Time">Full-Time</option>
<option value="Contract">Contract</option>
</select>
</div>
<div id="no-match">
<h3>No Match</h3>
</div>
<div class="job" data-team="Sales" data-location="Remote" data-type="Full-Time">
<p>Sales Remote Full Time</p>
</div>
<div class="job" data-team="Management" data-location="Portland, OR" data-type="Contract">
<p>Management Portland Contract</p>
</div>
<div class="job" data-team="Sales" data-location="Seattle, WA" data-type="Full-Time">
<p>Sales Seattle Full Time</p>
</div>