Доброго времени суток!
Есть фильтр товаров по разным категориям и сам список товаров. Все данные хранятся в data-аттрибутах.
Разметка:
<!-- Чекбоксы -->
<input type="checkbox" data-type="foo" data-foo="foo_item1">
<input type="checkbox" data-type="foo" data-foo="foo_item2">
...
<input type="checkbox" data-type="bar" data-bar="bar_item1">
<input type="checkbox" data-type="bar" data-bar="bar_item2">
<!-- Товары -->
<div class="item" data-foo="foo_item1" data-bar="bar_item1" >
<div class="item" data-foo="foo_item2" data-bar="bar_item2" >
...
В фильтре две категории: "foo" и "bar". Мне нужно чтобы при выборе чекбоксов из обоих типов подсвечивалось только то, что удовлетворяет двум условиям одновременно. Это было несложно:
function getFilteredItems(type) {
// сомнительный момент – сбор выделенных типов (нужен ли он?)
var checkedTypes = $(':checked').map(function(i,ch){
return $(ch).data(type);
});
// сбор узлов для подсветки
var resultItems = $('.item').filter(function(){
// кэшируем текущий элемент чтобы передать в другой метод
var item = $(this);
// Возвращает true если хотя бы один элемент true
return checkedTypes.some(function(typeItem){
// проверка на совпадение data-аттрибута товара с data-аттрибутом чекбокса
return typeItem==item.data(type);
});
});
return resultItems;
}
$('#filter').find(':checkbox').click(function(){
// кэшируем узлы
var items = $('#goods').find('.item');
var checked = $(':checked');
// убрать подсветку со всех товаров
items.removeClass('highlighted');
// Если отмечен хотя бы один чекбокс – фильтровать
if (checked.length>0) {
items
.css({'opacity':'.3'})
.filter(getFilteredItems('foo'))
.filter(getFilteredItems('bar'))
.addClass('highlighted');
}
else { // иначе – ничего не делать
items.css({'opacity':'1'});
}
});
Всё прекрасно работает, если есть хотя бы один чекбокс в двух категориях одновременно. Но если только в одной, то на выходе из фильтра – 0 элементов.
Как сделать так, чтобы при отмеченных чекбоксах только одной категории фильтра отсутствие отмеченных во второй не фильтровало все элементы до нуля?
Я пробовал топорно возвращать результаты фильтра в переменные и сделать условия:
var fooItems = items.filter(getFilteredItems('foo'));
var barItems = items.filter(getFilteredItems('bar'));
if (fooItems.length > 0 && barItems.length > 0) {
// фильтр по двум категориям
} else if (fooItems.length > 0) {
// фильтр только по foo
} else if (barItems.length > 0) {
// фильтр только по bar
}
Но на мой взгляд так писать грубо, неправильно и поддерживать это ужасно неудобно (особенно, в случае добавления бОльшего количества категорий).
Как мне изменить код?
Спасибо!
ps: В некоторых случаях (но далеко не всегда) отмечание чекбокса подвешивается где-то на >400 мс. Меня это очень сильно печалит. Если кто-то даст советы по оптимизации данного кода – буду рад критике!