Вопрос или проблема
У меня есть вопрос о том, как показать несколько категорий на странице, нажав на несколько кнопок. Кодпен:
https://codepen.io/alena-chuyankova/pen/YzmWYKZ
- По умолчанию все страницы активны;
- Когда я нажимаю и снимаю нажатие с определенных кнопок, карточки с одинаковыми категориями должны появляться и скрываться (пока работает только для одной категории);
- Когда у меня есть несколько кнопок, они должны показывать и скрывать карточки с соответствующими категориями. Например, если пользователь хочет увидеть продукты с карточками лосося и креветок, должны показать карточки, которые содержат лосося и креветок. Если какая-то кнопка активна, она должна показывать все, что содержит текст этой кнопки, если это имеет смысл.
Большое спасибо!
let products = {
data: [
{
productName: "Fantasy",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Лосось, Креветки",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-diego-pontes-901015-2323391.jpg",
},
{
productName: "Spring",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Овощи",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-pixabay-357756.jpg",
},
{
productName: "Rainbow",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Лосось, Туна, Унаги",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-freestockpro-3147493.jpg",
},
{
productName: "Unique",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Лосось, Туна, Унаги, Креветки",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-photo-248444.webp",
},
{
productName: "Perfection",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Лосось",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-isabella-mendes-107313-858501.jpg",
},
{
productName: "Style",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Лосось, Туна, Унаги, Креветки",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-rajesh-tp-749235-2098143.jpg",
},
{
productName: "Dreamy",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Лосось",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-viniciusbenedit-3620705.jpg",
},
{
productName: "Spicy",
heart: "./icons/heart.svg",
heartCount: 2547,
category: "Креветки",
content:
"Lorem ipsum dolor sit amet, eu mei posse possim atomorum, vix cu fabellas assueverit. Vel ad option partiendo maiestatis, nec affert appetere te, his.",
picture: "./images/pexels-catscoming-699544.jpg",
},
],
};
for (let i of products.data) {
let card = document.createElement("div");
card.classList.add("card", "i.category");
//изображение
let imgContainer = document.createElement("div");
imgContainer.classList.add("image-container");
let image = document.createElement("img");
image.classList.add("product-img");
image.setAttribute("src", i.picture);
imgContainer.appendChild(image);
card.appendChild(imgContainer);
document.getElementById("products").appendChild(card);
card.setAttribute("title", i.category);
image.addEventListener("error", () => {
image.style.display = "none"; // Скрыть поврежденное изображение
image.parentNode.style.backgroundColor = "#d9d9d9"; // Установить цвет фона
});
//содержимое
let content = document.createElement("div");
content.classList.add("content");
card.appendChild(content);
//заголовок содержимого и секция лайков
let contentHead = document.createElement("div");
contentHead.classList.add("contentHead");
let productTitle = document.createElement("h2");
productTitle.classList.add("productTitle");
productTitle.innerText = i.productName;
let likesSection = document.createElement("div");
likesSection.classList.add("likesSection");
let likesIcon = document.createElement("img");
likesIcon.setAttribute("src", "./icons/heart.svg");
likesIcon.classList.add("likesIcon");
let likesCount = document.createElement("p");
likesCount.classList.add("likeCount");
likesCount.innerText = i.heartCount;
content.appendChild(contentHead);
contentHead.appendChild(productTitle);
contentHead.appendChild(likesSection);
likesSection.appendChild(likesIcon);
likesSection.appendChild(likesCount);
likesIcon.addEventListener("error", () => {
likesIcon.setAttribute(
"src",
"https://upload.wikimedia.org/wikipedia/commons/f/f1/Heart_coraz%C3%B3n.svg"
);
});
//серия линий-разделителей
let line = document.createElement("hr");
line.classList.add("product-line");
content.appendChild(line);
//категория товара
let itemCategory = document.createElement("p");
itemCategory.classList.add("item-category");
itemCategory.innerText = i.category;
content.appendChild(itemCategory);
//описание
let itemDescription = document.createElement("p");
itemDescription.classList.add("itemDescription");
itemDescription.innerText = i.content;
content.appendChild(itemDescription);
//узнать больше
let readMore = document.createElement("p");
readMore.classList.add("readMore");
readMore.innerText = "Читать далее >>>";
content.appendChild(readMore);
}
let buttons = document.querySelectorAll(".category-button");
let cards = document.querySelectorAll(".card");
let buttonArr = [];
let buttonsString;
buttons.forEach((button) => {
button.addEventListener("click", () => {
let buttonValue = button.innerText;
button.classList.toggle("active-button");
if (button.classList.contains("active-button")) {
buttonArr.push(buttonValue);
}
if (button.classList.contains("active-button") == false) {
let unwantedButtonValue = buttonValue;
let index = buttonArr.indexOf(unwantedButtonValue);
buttonArr.splice(index, 1);
}
buttonArr.sort();
buttonsString = buttonArr.toString();
console.log(buttonsString);
});
buttons.forEach((button) => {
button.addEventListener("click", () => {
cards.forEach((card) => {
let cardCategories;
cardCategories = card
.getAttribute("title")
.split(",")
.map(function (value) {
return value.trim();
})
.sort()
.toString();
console.log(cardCategories);
if (cardCategories.includes(buttonsString) == false) {
card.classList.add("inactive-card");
}
if (cardCategories.includes(buttonsString)) {
card.classList.remove("inactive-card");
}
});
});
});
});
Ответ или решение
Фильтрация категорий элементов с помощью JavaScript
В данном руководстве мы разберем, как реализовать фильтрацию карточек товаров по нескольким категориям, используя JavaScript. Приведенный код уже частично решает задачу, но давайте доработаем его, чтобы обеспечить правильное отображение карточек в зависимости от выбранных пользователем категорий.
Задача
Запрос от пользователя заключался в следующем:
- По умолчанию все карточки отображаются.
- При нажатии на кнопки фильтрации карточки с соответствующими категориями должны отображаться или скрываться.
- Если выбрано несколько кнопок, должны отображаться только те карточки, которые содержат все выбранные категории.
Структура данных
Данные о товарах представлены в виде массива объектов. Каждый объект содержит информацию о товаре, включая название, количество лайков, категории и другое:
let products = {
data: [
{ productName: "Fantasy", category: "Salmon, Shrimp", ... },
{ productName: "Spring", category: "Veggie", ... },
// другие товары
]
};
Реализация фильтрации
Для начала создадим функцию, которая отвечает за фильтрацию карточек. Изменим код, чтобы он корректно обрабатывал нажатия на кнопки:
let buttons = document.querySelectorAll(".category-button");
let cards = document.querySelectorAll(".card");
let selectedCategories = new Set();
buttons.forEach(button => {
button.addEventListener("click", () => {
button.classList.toggle("active-button");
const category = button.innerText;
// Если кнопка активна, добавляем категорию в Set, иначе убираем
if (selectedCategories.has(category)) {
selectedCategories.delete(category);
} else {
selectedCategories.add(category);
}
filterCards();
});
});
function filterCards() {
cards.forEach(card => {
const cardCategories = card.getAttribute("title").split(",").map(cat => cat.trim());
// Проверяем, если выбранные категории содержатся в категориях карточки
const isIncluded = Array.from(selectedCategories).every(selected =>
cardCategories.includes(selected)
);
// Показываем или скрываем карточки в зависимости от условия
if (selectedCategories.size === 0 || isIncluded) {
card.classList.remove("inactive-card");
} else {
card.classList.add("inactive-card");
}
});
}
Объяснение кода
-
Сет для выбранных категорий: Введен
Set
для хранения выбранных категорий. Это обеспечивает уникальность значений и упрощает проверку на наличие элемента. -
Событие на кнопках: Каждый раз при нажатии на кнопку проверяем, активна ли она. Если да, добавляем категорию; если нет — удаляем.
-
Функция фильтрации: В функции
filterCards
происходит проверка каждой карточки на наличие всех выбранных категорий. Если ни одна категория не выбрана, все карточки отображаются. -
Логика показа/скрытия карточек: Для каждой карточки проверяем, должна ли она быть видимой в зависимости от выбранных категорий.
Заключение
Данный подход обеспечивает гибкость в фильтрации карточек по нескольким категориям и может быть дополнен новыми функциями, такими как анимация или подсветка активных категорий. Используя Set
, мы избегаем дублирования категорий и обеспечиваем более чистый и управляемый код.
SEO-Оптимизация
Для улучшения видимости кода на веб-страницах следует использовать ключевые слова, такие как "фильтрация карточек товаров", "JavaScript фильтрация", "отображение по категориям" и "интерактивный интерфейс". Это позволит привлечь больше целевой аудитории и повысить рейтинг страницы в поисковых системах.