Я создаю набор фильтров, и после их выбора соответствующие элементы div должны отображаться на основе ВСЕХ выбранных атрибутов.
Я могу заставить это работать по одному, но моя проблема заключается в том, чтобы заставить их работать вместе. Я чувствую, что, вероятно, есть лучший подход к этому в целом?
Вот мои избранные меню:
<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
к каждому из них и просто использовал value
для элементов <option>
.
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.info('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>
Спасибо! Я знал, что чего-то не хватает. Это работает отлично.
Ваша главная проблема в том, что вам нужна
&&
логика, чтобы убедиться, что каждое условие соответствует