Фильтр пиццы по ингредиентам

У меня есть кнопки, где вы можете выбрать, какие ингредиенты фильтровать

//index.html

<div class="submenu">
    <input type="checkbox" class="filter-item" id="olive" onclick="filter()" />
    <label for="olive">
        <img alt="olive" src="img/png/pizza/olive.png" />
    </label>
    <input type="checkbox" class="filter-item" id="shrimp" onclick="filter()" />
    <label for="shrimp">
        <img alt="shrimp" src="img/png/pizza/shrimp.png" />
    </label>
    <input type="checkbox" class="filter-item" id="mushroom" onclick="filter()" />
    <label for="mushroom">
        <img alt="mushroom" src="img/png/pizza/champion.png" />
    </label>
    <input type="checkbox" class="filter-item" id="pepperoni" onclick="filter()" />
    <label for="pepperoni">
        <img alt="pepperoni" src="img/png/pizza/pepperoni.png" />
    </label>
    <footer id="filter-text">no filter applied</footer>
</div>

И пункты меню (пиццы)

//index.html

<div class="menu-container">
    <img id="olive-pizza" class="menu-item olive" alt="olive" />
    <img id="pepperoni-pizza" class="menu-item pepperoni" alt="pepperoni" />
    <img id="shrimp pizza" class="menu-item shrimp" alt="shrimp" />
    <img class="menu-item mushroom" alt="mushroom" />
    <img class="menu-item olive pepperoni" alt="olive, pepperoni" />
    <img class="menu-item olive shrimp mushroom" alt="olive, shrimp, mushroom" />
</div>

Я хочу отобразить все пиццы, которые включают все выбранные ингредиенты. Например, если в качестве ингредиентов выбраны оливки и креветки, отобразятся только те пиццы, которые по крайней мере относятся к обоим этим классам.

Моя идея состоит в том, чтобы поместить все выбранные ингредиенты в массив itemsToFilter, затем сравнить каждый элемент в этом массиве с классами каждой пиццы, а затем отобразить «оставшиеся» пиццы.

Вот функция:

var itemsToFilter = [];

//HTMLCollections, not arrays
ingredients = document.getElementsByClassName("filter-item"); 
pizzas = document.getElementsByClassName("menu-item");

function filter() {
    for (var i = 0; i < ingredients.length; i++) {
        if (ingredients[i].checked == true) {
            //add checked item to array itemsToFilter
            if (itemsToFilter.includes(ingredients[i].getAttribute("id")) == false) {
                itemsToFilter.push(ingredients[i].getAttribute("id"));
            }
        } else {
            //remove unchecked item from array itemsToFilter
            for (var y = itemsToFilter.length - 1; y >= 0; y--) {
                if (itemsToFilter[y] === ingredients[i].getAttribute("id")) {
                    if (itemsToFilter.includes(ingredients[i].getAttribute("id")) == true) {
                        itemsToFilter.splice(y, 1);
                    }
                }
            }
        }
        //show pizzas with classes that match items in array itemsToFilter
        for (var i = 0; i < pizzas.length; i++) {
            for (y in itemsToFilter) {
                if (pizzas[i].classList.contains(itemsToFilter[y]) == false) {
                    if (pizzas[i].classList.contains("show") == true) {
                        pizzas[i].classList.remove("show");
                    }
                    break;
                } else {
                    pizzas[i].classList.add("show");
                }
            }
        }
    }
}

Это работает до некоторой степени. Он работает только с первым ингредиентом «оливковое», где он правильно добавляет шоу класса, однако он не удаляет класс, когда флажок не установлен. Другие ингредиенты даже не добавляются в массив itemsToFilter.

У кого-нибудь есть подход?


person Community    schedule 16.10.2019    source источник


Ответы (2)


... Я случайно поместил цикл for, который показывает пиццу, внутрь цикла for, который проходит через кнопки ингредиентов. Я переместил его на один шаг, а также переместил часть, которая удаляет класс шоу из пиццы, перед циклом for, который зацикливает массив itemsToFilter, поскольку он не удалил бы класс шоу, если массив был пуст. Спасибо всем любезно.

person Community    schedule 16.10.2019

Я переписал ваш код и внес некоторые изменения:

var itemsToFilter = [];

//HTMLCollections, not arrays
ingredients = document.getElementsByClassName("filter-item"); 
pizzas = document.getElementsByClassName("menu-item");

function filter() {
    // Here you have always only the selected ingredients
    let selectedIngredients = ingredients.filter(ingredient => ingredient.checked === true);

    if(selectedIngredients.length === 0) {
        pizzas.forEach(pizza => {
             pizza.classList.add("show");
        });
    } else {
        pizzas.forEach(pizza => {
            let hasAllIngredients = true;
            selectedIngredients.forEach(ingredient => {
                if(!pizza.classList.includes(ingredient.getAttribute("id"))) {
                    hasAllIngredients = false;
                }
            });

            if(hasAllIngredients) {
                pizza.classList.add("show");
            } else {
                pizza.classList.remove("show");
            }
        });
    }
}
person Simone Boccato    schedule 16.10.2019