Где находятся чекбоксы и фильтруемые элементы, какой класс обеспечивает сокрытие элементов:
const checkboxContainer = document.querySelector('.options');
const itemsContainer = document.querySelector('.box');
const hiddenClass = 'hidden';
Собираем селектор на основе состояний чекбоксов (выставлен - класс должен присутствовать, не выставлен - помещаем класс внутрь
:not
):
function getCheckedSelector(container) {
const [ not, has ] = Array.prototype.reduce.call(
container.querySelectorAll('input'),
(acc, n) => (acc[+n.checked].push(`.${n.value}`), acc),
[ [], [] ]
);
return has.join('') + (not.length ? `:not(${not.join(',')})` : '');
}
Затем проверяем фильтруемые элементы на соответствие селектору:
checkboxContainer.addEventListener('change', function() {
const selector = getCheckedSelector(this);
for (const n of itemsContainer.children) {
n.classList.toggle(hiddenClass, !n.matches(selector));
}
});
Или сначала прячем всё, а потом показываем что надо:
const toggleHidden = (selector, state) => itemsContainer
.querySelectorAll(selector)
.forEach(n => n.classList.toggle(hiddenClass, state));
checkboxContainer.addEventListener('change', e => {
toggleHidden(':scope > *', true);
toggleHidden(getCheckedSelector(e.currentTarget), false);
});
ИЛИ
При обработке элемента перебираем чекбоксы и проверяем, что их состояния соответствуют наличию классов у данного элемента:
const checkboxes = [...checkboxContainer.querySelectorAll('input')];
const onChange = function() {
this.forEach(({ classList: cl }) => {
cl.toggle(hiddenClass, checkboxes.some(n => n.checked !== cl.contains(n.value)));
});
}.bind([...itemsContainer.children]);
checkboxes.forEach(n => n.addEventListener('change', onChange));