Фильтрация категорий товаров с несколькими категориями – Javascript

Вопрос или проблема

У меня есть вопрос о том, как показать несколько категорий на странице, нажав на несколько кнопок. Кодпен:
https://codepen.io/alena-chuyankova/pen/YzmWYKZ

  1. По умолчанию все страницы активны;
  2. Когда я нажимаю и снимаю нажатие с определенных кнопок, карточки с одинаковыми категориями должны появляться и скрываться (пока работает только для одной категории);
  3. Когда у меня есть несколько кнопок, они должны показывать и скрывать карточки с соответствующими категориями. Например, если пользователь хочет увидеть продукты с карточками лосося и креветок, должны показать карточки, которые содержат лосося и креветок. Если какая-то кнопка активна, она должна показывать все, что содержит текст этой кнопки, если это имеет смысл.
    Большое спасибо!

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. Приведенный код уже частично решает задачу, но давайте доработаем его, чтобы обеспечить правильное отображение карточек в зависимости от выбранных пользователем категорий.

Задача

Запрос от пользователя заключался в следующем:

  1. По умолчанию все карточки отображаются.
  2. При нажатии на кнопки фильтрации карточки с соответствующими категориями должны отображаться или скрываться.
  3. Если выбрано несколько кнопок, должны отображаться только те карточки, которые содержат все выбранные категории.

Структура данных

Данные о товарах представлены в виде массива объектов. Каждый объект содержит информацию о товаре, включая название, количество лайков, категории и другое:

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");
    }
  });
}

Объяснение кода

  1. Сет для выбранных категорий: Введен Set для хранения выбранных категорий. Это обеспечивает уникальность значений и упрощает проверку на наличие элемента.

  2. Событие на кнопках: Каждый раз при нажатии на кнопку проверяем, активна ли она. Если да, добавляем категорию; если нет — удаляем.

  3. Функция фильтрации: В функции filterCards происходит проверка каждой карточки на наличие всех выбранных категорий. Если ни одна категория не выбрана, все карточки отображаются.

  4. Логика показа/скрытия карточек: Для каждой карточки проверяем, должна ли она быть видимой в зависимости от выбранных категорий.

Заключение

Данный подход обеспечивает гибкость в фильтрации карточек по нескольким категориям и может быть дополнен новыми функциями, такими как анимация или подсветка активных категорий. Используя Set, мы избегаем дублирования категорий и обеспечиваем более чистый и управляемый код.

SEO-Оптимизация

Для улучшения видимости кода на веб-страницах следует использовать ключевые слова, такие как "фильтрация карточек товаров", "JavaScript фильтрация", "отображение по категориям" и "интерактивный интерфейс". Это позволит привлечь больше целевой аудитории и повысить рейтинг страницы в поисковых системах.

Оцените материал
Добавить комментарий

Капча загружается...