04.02.2023, 16:07
|
Новичок на форуме
|
|
Регистрация: 04.02.2023
Сообщений: 3
|
|
Фильтр категории-подкатегории-товары
Подскажите, пожалуйста, как сделать так чтобы при клике по категории появлялись её подкатегории (изначально не видны), а после клика по подкатегории уже фильтровались товары. Категории и подкатегории подтягиваются из БД. Сейчас получилось сделать только подкатегории и фильтрацию товаров. В JS полный ноль, всё собираю по кускам из сети. Помогите, пожалуйста.
Код у меня есть по ссылке: https://codepen.io/KuParty/pen/WNKPLbL Здесь тоже дублирую:
HTML:
Код:
|
<header class="header">
<div class="filter-category">
<button class="button button_type_all" data-filter="all">All</button>
<button class="button button_type_running" data-filter="running">Running</button>
<button class="button button_type_flying" data-filter="flying">Flying</button>
</div>
<div class="filter">
<button class="button button_type_cat" data-filter="cat">Cat</button>
<button class="button button_type_dog" data-filter="dog">Dog</button>
<button class="button button_type_bird" data-filter="bird">Bird</button>
</div>
</header>
<main class="content">
<div class="container">
<div class="card cat running">Cat</div>
<div class="card dog running">Dog</div>
<div class="card bird flying">Bird</div>
<div class="card dog running">Dog</div>
<div class="card cat running">Cat</div>
<div class="card bird flying">Bird</div>
<div class="card bird flying">Bird</div>
<div class="card dog running">Dog</div>
<div class="card cat running">Cat</div>
</div>
</main> |
CSS:
Код:
|
:root {
--color-orange: #ffa728;
--color-red: #e66c6e;
--color-green: #a7d6bb;
--color-blue: #1c4961;
--color-sky: #58C9E2FF;
--color-brown: #a56e47;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Courier New", Courier, monospace;
font-size: 16px;
line-height: 1.2;
background-color: #faebd7;
}
.header {
padding: 20px 0;
margin-bottom: 48px;
}
.filter {
display: flex;
justify-content: center;
max-width: 1024px;
margin: 0 auto;
}
.filter-category {
display: flex;
justify-content: center;
max-width: 1024px;
margin: 0 auto;
padding-bottom: 20px;
}
.button {
padding: 12px 24px;
margin-right: 18px;
cursor: pointer;
color: white;
text-transform: uppercase;
font-weight: bold;
border: 0;
outline: none;
border-radius: 0;
position: relative;
}
.button:last-child {
margin-right: 0;
}
.button:active {
bottom: -1px;
}
.button_type_all {
background-color: var(--color-orange);
}
.button_type_flying {
background-color: var(--color-sky);
}
.button_type_running {
background-color: var(--color-brown);
}
.button_type_cat {
background-color: var(--color-green);
}
.button_type_dog {
background-color: var(--color-red);
}
.button_type_bird {
background-color: var(--color-blue);
}
.container {
display: flex;
flex-wrap: wrap;
max-width: 1024px;
margin: 0 auto;
}
.card {
width: calc(33.3333333% - 72px);
margin: 36px;
height: 200px;
line-height: 200px;
text-align: center;
color: white;
font-weight: bold;
font-size: 48px;
overflow: hidden;
transition: 0.5s all;
}
.cat {
background-color: var(--color-green);
}
.dog {
background-color: var(--color-red);
}
.bird {
background-color: var(--color-blue);
}
.anime {
transform: scale(0);
opacity: 0;
}
.hide {
animation-name: hide;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
@keyframes hide {
0% {
visibility: visible;
height: 200px;
}
100% {
visibility: hidden;
width: 0;
height: 0;
max-width: 0;
font-size: 0;
margin: 0;
}
} |
JS:
function app() {
const buttons = document.querySelectorAll('.button')
const cards = document.querySelectorAll('.card')
function filter (category, items) {
items.forEach((item) => {
const isItemFiltered = !item.classList.contains(category)
const isShowAll = category.toLowerCase() === 'all'
if (isItemFiltered && !isShowAll) {
item.classList.add('anime')
} else {
item.classList.remove('hide')
item.classList.remove('anime')
}
})
}
buttons.forEach((button) => {
button.addEventListener('click', () => {
const currentCategory = button.dataset.filter
filter(currentCategory, cards)
})
})
cards.forEach((card) => {
card.ontransitionend = function () {
if (card.classList.contains('anime')) {
card.classList.add('hide')
}
}
})
}
app()
Всё это сейчас прикручено к Jango таким образом:
Код:
|
<header class="header-filter">
<div class="filter-category">
<button class="button button_type_all" data-filter="all">Все</button>
{% for sc in subcategories %}
{% if sc.get_prods__count > 0 %}
<button class="button button_type_cat"
data-filter="{{ sc.slug }}">{{ sc.sub_cat_name }}</button>
{% endif %}
{% endfor %}
</div>
</header>
<main class="content">
<div class="container">
{% for sc in subcategories %}
{% if sc.get_prods__count > 0 %}
{% for p in prods %}
{% if p.subcategory_id == sc.pk %}
{% if p.photo %}
<div class="card {{ sc.slug }}">
<a href="{{ p.get_absolute_url }}">
{{ p.title }}
</a>
</div>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
</div>
</main> |
Последний раз редактировалось KuParty, 04.02.2023 в 17:38.
|
|
04.02.2023, 17:38
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
фильтр по категориям
KuParty,
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<style type="text/css">
:root {
--color-orange: #ffa728;
--color-red: #e66c6e;
--color-green: #a7d6bb;
--color-blue: #1c4961;
--color-sky: #58C9E2FF;
--color-brown: #a56e47;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Courier New", Courier, monospace;
font-size: 16px;
line-height: 1.2;
background-color: #faebd7;
}
.header {
padding: 20px 0;
margin-bottom: 48px;
}
.filter {
display: flex;
justify-content: center;
max-width: 1024px;
margin: 0 auto;
}
.filter-category {
display: flex;
justify-content: center;
max-width: 1024px;
margin: 0 auto;
padding-bottom: 20px;
}
.button {
padding: 12px 24px;
margin-right: 18px;
cursor: pointer;
color: white;
text-transform: uppercase;
font-weight: bold;
border: 0;
outline: none;
border-radius: 0;
position: relative;
}
.button:last-child {
margin-right: 0;
}
.button:active {
bottom: -1px;
}
.button_type_all {
background-color: var(--color-orange);
}
.button_type_flying {
background-color: var(--color-sky);
}
.button_type_running {
background-color: var(--color-brown);
}
.button_type_cat {
background-color: var(--color-green);
}
.button_type_dog {
background-color: var(--color-red);
}
.button_type_bird {
background-color: var(--color-blue);
}
.container {
display: flex;
flex-wrap: wrap;
max-width: 1024px;
margin: 0 auto;
}
.card {
width: calc(33.3333333% - 72px);
margin: 36px;
height: 100px;
line-height: 100px;
text-align: center;
color: white;
font-weight: bold;
font-size: 48px;
overflow: hidden;
transition: 0.5s all;
}
.cat {
background-color: var(--color-green);
}
.dog {
background-color: var(--color-red);
}
.bird {
background-color: var(--color-blue);
}
.anime {
transform: scale(0);
opacity: 0;
}
.hide {
animation-name: hide;
animation-duration: 0.5s;
animation-fill-mode: forwards;
animation-delay: 0.6s;
}
@keyframes hide {
0% {
visibility: visible;
height: 200px;
}
100% {
visibility: hidden;
width: 0;
height: 0;
max-width: 0;
font-size: 0;
margin: 0;
}
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
const header = document.querySelector('.header');
header.addEventListener("click", function({
target
}) {
if (target.closest('[data-filter]')) {
let categorys = target.dataset.filter;
const isShowAll = categorys == 'all'
categorys = categorys.split(',');
document.querySelectorAll('[data-filter]').forEach(elem => {
let keys = elem.dataset.filter;
const isKeyAll = keys == 'all';
keys = keys.split(',');
const isItemFiltered = isKeyAll || isShowAll || keys.some(key => categorys.includes(key));
elem.classList.remove("hide");
elem.classList.toggle("anime", !isItemFiltered);
if (!isItemFiltered) elem.classList.add("hide");
})
};
})
})
</script>
</head>
<body>
<header class="header">
<div class="filter-category">
<button class="button button_type_all" data-filter="all">All</button>
<button class="button button_type_running" data-filter="cat,dog">Running</button>
<button class="button button_type_flying" data-filter="bird">Flying</button>
</div>
<div class="filter">
<button class="button button_type_cat" data-filter="cat">Cat</button>
<button class="button button_type_dog" data-filter="dog">Dog</button>
<button class="button button_type_bird" data-filter="bird">Bird</button>
</div>
</header>
<main class="content">
<div class="container">
<div class="card cat" data-filter="cat">Cat</div>
<div class="card dog" data-filter="dog">Dog</div>
<div class="card bird" data-filter="bird">Bird</div>
<div class="card dog" data-filter="dog">Dog</div>
<div class="card cat" data-filter="cat">Cat</div>
<div class="card bird" data-filter="bird">Bird</div>
<div class="card bird" data-filter="bird">Bird</div>
<div class="card dog" data-filter="dog">Dog</div>
<div class="card cat" data-filter="cat">Cat</div>
</div>
</main>
</body>
</html>
Последний раз редактировалось рони, 04.02.2023 в 17:41.
|
|
04.02.2023, 17:52
|
Новичок на форуме
|
|
Регистрация: 04.02.2023
Сообщений: 3
|
|
рони
Спасибо за помощь. Но это немного не то. Я хотел чтобы все карточки и подкатегории DOG CAT BIRD изначально не были видны. После нажатия на категорию появлялись её подкатегории и карточки относящиеся к этим подкатегориям. При нажатии на подкатегорию фильтровались по ней.
|
|
04.02.2023, 20:00
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
KuParty,
надо брать объект и отображать его текущее состояние, тогда будет что-то такое
|
|
06.02.2023, 23:37
|
Новичок на форуме
|
|
Регистрация: 04.02.2023
Сообщений: 3
|
|
Сообщение от рони
|
надо брать объект и отображать его текущее состояние, тогда будет что-то такое
|
Спасибо, но, к сожалению, не смог разобраться, JS вообще не знаю(
|
|
07.02.2023, 02:14
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,123
|
|
Сообщение от рони
|
надо брать объект и отображать его текущее состояние,
|
примерно так ... кликайте по названиям
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
<script>
document.addEventListener("DOMContentLoaded", function() {
const data = {
child: {
all: {
child: {
running: {
child: {
cat: {
child: {
cat1: {
title: 'mmm'
},
cat2: {
title: 'ppp'
}
}
},
dog: {
child: {
dog1: {
title: 'rrr'
},
dog2: {
title: 'gav'
}
}
}
}
},
flying: {
child: {
bird: {
child: {
bird1: {
title: 'fly'
}
}
}
}
}
},
}
},
show: true
}
const createHtml = data => {
let ul = document.createElement('ul');
if (data.child) {
for (let key in data.child) {
let li = document.createElement('li');
li.textContent = key;
ul.append(li);
li.addEventListener("click", function(event) {
event.preventDefault();
event.stopPropagation();
data.child[key].show = !data.child[key].show;
create();
})
let el = data.child[key],
show = data.child[key].show;
if (typeof el == 'object' && show) li.append(createHtml(el))
}
}
if (data.title) {
let li = document.createElement('li');
li.textContent = `my name is ${data.title}`;
ul.append(li);
}
return ul
}
const create = () => {
let html = createHtml(data);
document.querySelector('.test').innerHTML = '';
document.querySelector('.test').append(html)
}
create()
})
</script>
</head>
<body>
<div class="test"></div>
</body>
</html>
|
|
|
|