按成分过滤比萨饼
Filtering pizzas by ingredients
我有一些按钮,您可以在其中选择要过滤的成分
//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>
我想显示包含所有所选配料的所有比萨饼。例如,如果选择了橄榄和虾成分,则只显示至少具有这两种成分的比萨饼 classes.
我的想法是将所有选定的成分放入一个数组 itemsToFilter
,然后将该数组中的每个项目与每个比萨饼的 classes 进行比较,然后显示 "remaining" 个比萨饼.
函数如下:
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");
}
}
}
}
}
这在一定程度上起作用。它只适用于第一个成分 "olive",它正确地添加了 class 显示,但是当复选框未选中时它不会删除 class。其他成分甚至不会添加到数组 itemsToFilter 中。
有人有办法吗?
...我不小心将显示比萨饼的 for 循环放在循环成分按钮的 for 循环中。我将其移出一步,并将从比萨饼中删除节目 class 的部分移到循环数组 itemsToFilter 的 for 循环之前,因为如果数组为空,它不会删除节目 class。谢谢大家。
我重新编写了您的代码并做了一些更改:
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");
}
});
}
}
我有一些按钮,您可以在其中选择要过滤的成分
//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>
我想显示包含所有所选配料的所有比萨饼。例如,如果选择了橄榄和虾成分,则只显示至少具有这两种成分的比萨饼 classes.
我的想法是将所有选定的成分放入一个数组 itemsToFilter
,然后将该数组中的每个项目与每个比萨饼的 classes 进行比较,然后显示 "remaining" 个比萨饼.
函数如下:
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");
}
}
}
}
}
这在一定程度上起作用。它只适用于第一个成分 "olive",它正确地添加了 class 显示,但是当复选框未选中时它不会删除 class。其他成分甚至不会添加到数组 itemsToFilter 中。
有人有办法吗?
...我不小心将显示比萨饼的 for 循环放在循环成分按钮的 for 循环中。我将其移出一步,并将从比萨饼中删除节目 class 的部分移到循环数组 itemsToFilter 的 for 循环之前,因为如果数组为空,它不会删除节目 class。谢谢大家。
我重新编写了您的代码并做了一些更改:
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");
}
});
}
}