let aside = document.body.querySelector('aside'),
set = new Set(),
arr = [];
aside.addEventListener('click', () => {
let target = event.target;
let click = false;
while (target != aside) {
if (target.tagName == 'LABEL') {
let text = target.querySelector('span.label').textContent,
check = target.querySelector('input');
if (check.checked && check.getAttribute('type') == 'checkbox') {
set.add(text);
} else {
set.delete(text);
}
if (check.checked && check.getAttribute('type') == 'radio') {
set.add(text);
} else {
let newText;
if (target.nextSibling && check.getAttribute('type') == 'radio') {
newText = target.nextSibling.querySelector('span.label').textContent;
}
if (target.previousSibling && check.getAttribute('type') == 'radio') {
newText = target.previousSibling.querySelector('span.label').textContent;
}
set.delete(newText);
click = true;
}
}
target = target.parentNode;
}
if (click == false) {
return;
}
arr.length = 0;
arr = [...set];
let json = JSON.stringify(arr);
let xhr = new XMLHttpRequest();
xhr.open('POST', 'server.js', true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.send(json);
xhr.onreadystatechange = () => {
if (xhr.readyState != 4) return;
let object = JSON.parse(xhr.responseText);
let article = document.querySelector('article');
while (article.lastChild) {
article.removeChild(article.lastChild);
};
for (let value in object) {
let template = document.querySelector('#template').content;
let item = template.querySelector('.item');
let newItem = item.cloneNode(true);
newItem.querySelector('img').src = `${object[value].img}`;
newItem.querySelector('.description').textContent = object[value].description;
newItem.querySelector('.price-rub').textContent = object[value].rub;
newItem.querySelector('.price-penny').textContent = object[value].penny;
newItem.querySelector('.country').textContent = object[value].country;
article.appendChild(newItem);
}
}
});
<aside>
<section>
<h3>Страна производства</h3><label> <input type="checkbox"/><span class="checkbox"></span><span class="label">Беларусь</span></label><label> <input type="checkbox"/><span class="checkbox"></span><span class="label">Россия</span></label><label> <input type="checkbox"/><span class="checkbox"></span><span class="label">Украина</span></label><label> <input type="checkbox"/><span class="checkbox"></span><span class="label">Нидерланды</span></label><label> <input type="checkbox"/><span class="checkbox"></span><span class="label">Германия</span></label></section>
<section>
<h3>Цена</h3>
<div class="price-range"><input type="number" placeholder="от: " min="0" /><input type="number" placeholder="до: " min="1" /></div>
</section>
<section>
<h3>Количество в упаковке</h3><label><input type="checkbox"/><span class="checkbox"></span><span class="label">1</span></label><label><input type="checkbox"/><span class="checkbox"></span><span class="label">4 </span></label><label><input type="checkbox"/><span class="checkbox"></span><span class="label">8</span></label></section>
<section>
<h3>Наличие втулки</h3>
<div class="radio"><label><input type="radio" name="sss"/><span class="radiobutton"></span><span class="label">Да</span></label><label><input type="radio" name="sss"/><span class="radiobutton"></span><span class="label">Нет</span></label></div>
</section>
</aside>
Решил написать интернет-магазин для практики. При каждом нажатии по чекбоксам сохраняю их значение(label) в массив и через AJAX посылаю их на сервер, где сравниваю их с полями объекта.
Пример объекта:
{
img: "picture/52.jpg",
description: "Туалетная бумага „Kleenex“ нежная ромашка, трехслойная, 8 рулонов.",
rub: "9р.",
penny: "99к.",
country: "Россия",
sleeve: "Да",
amount: 8
},
{
img: "picture/53.jpg",
description: "Туалетная бумага „Kleenex“ сочная клубника, трехслойная, 8 рулонов.",
rub: "9р.",
penny: "99к.",
country: "Россия",
sleeve: "Да",
amount: 8
}
Код фильтрации на сайте:
object.length = 0;
set.clear();
for (let i of set) {
set.delete(set[i]);
}
arr.forEach(obj => {
for (let value in obj) {
for (let i = 0; i < req.body.length; i++) {
if (obj[value] == req.body[i]) {
count++;
set.add(obj);
}
}
}
})
object = [...set];
json = JSON.stringify(object)
res.end(json);
Знаю, что это неправильный код, т.к. он добавляет товар даже в том случае, если только один из критериев удовлетворяет. Как реализовать поиск товаров, удовлетворяющий сразу нескольким пунктам? Возможно надо посылать не массив, а массив массивов. В любом случае я не могу додуматься :)
target.nextSibling.querySelector('span.label').textContent
Могу ошибаться: возможно, что на серверах с Node это делается именно так, но, наверное, вместо таких конструкций все же стоит воспользоваться тегом form
, задать всем полям ввода (input, select, checkbox) атрибуты name
, value
и собирать данные при помощи FormData
. Конечно, если вы не практикуетесь в выборках узлов по DOM.
document.getElementById('filter_form')
.addEventListener('input', function(event) {
const formData = new FormData(this);
log(formData);
/**
* Пример отправки FormData.
const xhr = new XMLHttpRequest();
xhr.open('POST', API_URL, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
// Рендеринг списка товаров.
console.log(response);
}
}
xhr.send(formData);*/
});
const log = function logToConsoleforDemo(data) {
console.clear();
console.log('Эти данные будут отправлены:');
for (let pair of data.entries()) {
console.log(...pair);
}
};
#app {
display: flex;
flex-wrap: wrap;
}
.sidebar {
flex: 0 0 288px;
padding: 18px;
padding-bottom: 188px;
}
label {
display: block;
}
<div id="app">
<aside class="sidebar">
<form id="filter_form" action="" method="post">
<section>
<h3>Страна производства</h3>
<label>
<input type="checkbox" name="country[]" value="belarus" />
<span class="checkbox"></span>
<span class="label">Беларусь</span>
</label>
<label>
<input type="checkbox" name="country[]" value="russia" />
<span class="checkbox"></span>
<span class="label">Россия</span>
</label>
<label>
<input type="checkbox" name="country[]" value="ukraine" />
<span class="checkbox"></span>
<span class="label">Украина</span>
</label>
<label>
<input type="checkbox" name="country[]" value="netherlands" />
<span class="checkbox"></span>
<span class="label">Нидерланды</span>
</label>
<label>
<input type="checkbox" name="country[]" value="germany" />
<span class="checkbox"></span>
<span class="label">Германия</span>
</label>
</section>
<section>
<h3>Цена</h3>
<div class="price-range">
<input type="number" name="price[]" placeholder="от: " min="100" value="100" />
<input type="number" name="price[]" placeholder="до: " min="1000" value="1000" />
</div>
</section>
<section>
<h3>Количество в упаковке</h3>
<select name="quantity-per-pack">
<option value="1">1</option>
<option value="4">4</option>
<option value="8">8</option>
</select>
</section>
<section>
<h3>Наличие втулки</h3>
<div class="radio">
<label>
<input type="radio" name="thimble" value="1" />
<span class="radiobutton"></span>
<span class="label">Да</span>
</label>
<label>
<input type="radio" name="thimble" value="0" />
<span class="radiobutton"></span>
<span class="label">Нет</span>
</label>
</div>
</section>
</form>
</aside>
<main class="main"></main>
</div>
Как реализовать поиск товаров, удовлетворяющий сразу нескольким пунктам?
Небольшой пример, просто он нагляднее без использования for
:
// Массив товаров.
const products = [{
"name": "Первый",
"price": "100",
"country": "russia",
"thimble": "true",
}, {
"name": "Второй",
"price": "200",
"country": "belarus",
"thimble": "true",
}, {
"name": "Третий",
"price": "1000",
"country": "russia",
"thimble": "false",
}, {
"name": "Четвертый",
"price": "800",
"country": "netherlands",
"thimble": "false",
}];
// Предположим, что это фильтр с фронта.
const query = {
"country": [
"netherlands",
"belarus"
],
"thimble": "false"
};
// Ключи из фильтра, по ним будет фильтрация.
const queryKeys = Object.keys(query);
// Здесь желательно не забывать о типах данных.
// ... code.
// Фильтрация массива объектов по нескольким ключам.
const filtered = products.filter((product) => {
// При помощи метода `every` проверяем,
// чтобы значения каждого ключа совпадали
// со значениями ключей в товаре.
return queryKeys.every((key) => {
// Если несколько значений у ключа.
// В нашем случае это массив `country` с фронта.
if (Array.isArray(query[key])) {
return query[key].includes(product[key]);
}
return product[key] == query[key];
});
});
console.log(filtered);
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Как реализовать подобную таблицу с использованием React MATERIAL-UI?
Уже много времени ломаю голову над событием onclickПодскажите, почему то что стоит в событии onclick (к примеру, просто console
Как сделать, чтобы вот такая scroll to кнопка приводила не к координатам, а к конкретному диву что-ли?