英文:
Javascript filter sorting by 2 or more values
问题
我是新手学习JavaScript,并且有一些根据颜色和尺寸筛选产品的代码。它运行得很好,但我想知道是否可能让JavaScript根据两个筛选器来减去产品。
例如,如果您勾选所有颜色筛选器,它会显示所有产品,这很好。但是,只要我勾选了"small",它仍然显示所有产品,因为它使用的是颜色筛选器的值。
是否有一种方法可以只显示"Product B",因为它具有颜色和small的数据筛选?
感谢您的帮助!
英文:
I'm new to javascript and have some code that filters products based on color and size. It works great, but I'm wondering if it's possible to have the javascript also SUBTRACT products based on two filters.
For example; if you check all the color filters it shows all the products, great. But as soon as I check "small" for example, it still shows all the products since it's using the filters values from Color.
Is there a way to have it only show "Product B", which has a data filter of a color AND small?
Thanks for your help!
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const filterCheckboxes = document.querySelectorAll('.filter-checkbox');
const filterables = document.querySelectorAll('.filterable');
function updateFilter() {
const checkedValues = Array.from(filterCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
if (!checkedValues.length > 0) {
filterables.forEach(filterable => {
filterable.style.display = 'block';
})
return;
}
filterables.forEach(filterable => {
const colors = filterable.dataset.colors.split(' ');
if (checkedValues.some(value => colors.includes(value)) || checkedValues.length === 0) {
filterable.style.display = 'block';
} else {
filterable.style.display = 'none';
}
});
}
filterCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateFilter);
});
updateFilter(); // initial filter based on default checkbox state
<!-- language: lang-html -->
<div>
<h3>Color</h3>
<label><input type="checkbox" class="filter-checkbox" value="red">Red</label>
<label><input type="checkbox" class="filter-checkbox" value="green">Green</label>
<label><input type="checkbox" class="filter-checkbox" value="blue">Blue</label>
</div>
<div>
<h3>Size</h3>
<label><input type="checkbox" class="filter-checkbox" value="small">Small</label>
<label><input type="checkbox" class="filter-checkbox" value="medium">Medium</label><label>
<input type="checkbox" class="filter-checkbox" value="large">Large</label>
</div>
<div>
<h1>Filtered Result</h1>
<div class="filterable" data-colors="blue large">Product A</div>
<div class="filterable" data-colors="green small">Product B</div>
<div class="filterable" data-colors="red medium">Product C</div>
<div class="filterable" data-colors="red large">Product D</div>
</div>
<!-- end snippet -->
I was hoping that Javascript can also subtract products based on multiple values.
答案1
得分: 1
以下是翻译好的内容:
为了使其按预期工作,您应该更好地确定每个值是哪种类型(颜色或大小):
- 为复选框组的父级
div
添加一个命名维度(颜色或大小)的 CSS 类 - 将所有
data-colors
属性替换为data-color
和data-size
属性 - 为颜色和大小分别执行
includes
测试
以下是代码示例:
<!-- 开始代码片段: js 隐藏: false 控制台: true Babel: false -->
<!-- 语言: lang-js -->
const filterables = document.querySelectorAll('.filterable');
function getChecked(dimension) {
// 只查看与给定维度相关的复选框
let checked = document.querySelectorAll(`.${dimension} .filter-checkbox:checked`);
if (checked.length == 0) checked = document.querySelectorAll(`.${dimension} .filter-checkbox`);
return Array.from(checked, box => box.value);
}
function updateFilter() {
const filterColors = getChecked("color");
const filterSizes = getChecked("size");
for (const filterable of filterables) {
const {color, size} = filterable.dataset;
const match = filterColors.includes(color) && filterSizes.includes(size);
filterable.style.display = match ? 'block' : 'none';
}
}
// 您可以在文档级别监听 change 事件
document.addEventListener('change', updateFilter);
updateFilter(); // 基于默认复选框状态的初始筛选
<!-- 语言: lang-css -->
h3 { display: inline-block; }
h1, h3 { margin: 0; }
<!-- 语言: lang-html -->
<div class="color">
<h3>Color</h3>
<label><input type="checkbox" class="filter-checkbox" value="red">Red</label>
<label><input type="checkbox" class="filter-checkbox" value="green">Green</label>
<label><input type="checkbox" class="filter-checkbox" value="blue">Blue</label>
</div>
<div class="size">
<h3>Size</h3>
<label><input type="checkbox" class="filter-checkbox" value="small">Small</label>
<label><input type="checkbox" class="filter-checkbox" value="medium">Medium</label>
<label><input type="checkbox" class="filter-checkbox" value="large">Large</label>
</div>
<div>
<h1>Filtered Result</h1>
<div class="filterable" data-color="blue" data-size="large">Product A</div>
<div class="filterable" data-color="green" data-size="small">Product B</div>
<div class="filterable" data-color="red" data-size="medium">Product C</div>
<div class="filterable" data-color="red" data-size="large">Product D</div>
</div>
<!-- 结束代码片段 -->
请注意,上述内容是根据您提供的代码进行的翻译。如果有任何其他疑问,请随时提出。
英文:
For it to work as desired, you should better identify what each value is an instance of (either color or size):
- Give the parent
div
of a checkbox group a CSS class that names the dimension (color or size) - Replace all
data-colors
attributes bydata-color
anddata-size
attributes - Perform a separate
includes
test for color and for size
Here is how it could be coded:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const filterables = document.querySelectorAll('.filterable');
function getChecked(dimension) {
// Only look at the checkboxes that relate to the given dimension
let checked = document.querySelectorAll(`.${dimension} .filter-checkbox:checked`);
if (checked.length == 0) checked = document.querySelectorAll(`.${dimension} .filter-checkbox`);
return Array.from(checked, box => box.value);
}
function updateFilter() {
const filterColors = getChecked("color");
const filterSizes = getChecked("size");
for (const filterable of filterables) {
const {color, size} = filterable.dataset;
const match = filterColors.includes(color) && filterSizes.includes(size);
filterable.style.display = match ? 'block' : 'none';
}
}
// You can listen to the change event at the document level
document.addEventListener('change', updateFilter);
updateFilter(); // initial filter based on default checkbox state
<!-- language: lang-css -->
h3 { display: inline-block; }
h1, h3 { margin: 0; }
<!-- language: lang-html -->
<div class="color">
<h3>Color</h3>
<label><input type="checkbox" class="filter-checkbox" value="red">Red</label>
<label><input type="checkbox" class="filter-checkbox" value="green">Green</label>
<label><input type="checkbox" class="filter-checkbox" value="blue">Blue</label>
</div>
<div class="size">
<h3>Size</h3>
<label><input type="checkbox" class="filter-checkbox" value="small">Small</label>
<label><input type="checkbox" class="filter-checkbox" value="medium">Medium</label>
<label><input type="checkbox" class="filter-checkbox" value="large">Large</label>
</div>
<div>
<h1>Filtered Result</h1>
<div class="filterable" data-color="blue" data-size="large">Product A</div>
<div class="filterable" data-color="green" data-size="small">Product B</div>
<div class="filterable" data-color="red" data-size="medium">Product C</div>
<div class="filterable" data-color="red" data-size="large">Product D</div>
</div>
<!-- end snippet -->
答案2
得分: 1
以下是您要翻译的内容:
你可以像这样基于颜色和尺寸进行排序:
const filterCheckboxes = document.querySelectorAll('.filter-checkbox');
const colorCheckboxes = document.querySelectorAll('.color-checkbox');
const sizeCheckboxes = document.querySelectorAll('.size-checkbox');
const filterables = document.querySelectorAll('.filterable');
function updateFilter() {
const colorChecked = Array.from(colorCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
const sizeChecked = Array.from(sizeCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
if (!(colorChecked.length || sizeChecked.length)) {
filterables.forEach(filterable => {
filterable.style.display = 'block';
})
return;
}
filterables.forEach(filterable => {
const colors = filterable.dataset.colors.split(' ');
if (colorChecked.length >= 1 && sizeChecked.length >= 1) {
if (colorChecked.includes(colors[0]) && sizeChecked.includes(colors[1])) {
filterable.style.display = 'block';
} else {
filterable.style.display = 'none';
}
} else {
if (colorChecked.includes(colors[0]) || sizeChecked.includes(colors[1])) {
filterable.style.display = 'block';
} else {
filterable.style.display = 'none';
}
}
});
}
filterCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateFilter);
});
updateFilter(); // initial filter based on default checkbox state
<div>
<h3>Color</h3>
<label><input type="checkbox" class="filter-checkbox color-checkbox" value="red">Red</label>
<label><input type="checkbox" class="filter-checkbox color-checkbox" value="green">Green</label>
<label><input type="checkbox" class="filter-checkbox color-checkbox" value="blue">Blue</label>
</div>
<div>
<h3>Size</h3>
<label><input type="checkbox" class="filter-checkbox size-checkbox" value="small">Small</label>
<label><input type="checkbox" class="filter-checkbox size-checkbox" value="medium">Medium</label>
<label><input type="checkbox" class="filter-checkbox size-checkbox" value="large">Large</label>
</div>
<div>
<h1>Filtered Result</h1>
<div class="filterable" data-colors="blue large">Product A</div>
<div class="filterable" data-colors="green small">Product B</div>
<div class="filterable" data-colors="red medium">Product C</div>
<div class="filterable" data-colors="red large">Product D</div>
</div>
希望对您有所帮助。
英文:
You can sort based on both color and size like this:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const filterCheckboxes = document.querySelectorAll('.filter-checkbox');
const colorCheckboxes = document.querySelectorAll('.color-checkbox');
const sizeCheckboxes = document.querySelectorAll('.size-checkbox');
const filterables = document.querySelectorAll('.filterable');
function updateFilter() {
const colorChecked = Array.from(colorCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
const sizeChecked = Array.from(sizeCheckboxes)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
if (!(colorChecked.length || sizeChecked.length)) {
filterables.forEach(filterable => {
filterable.style.display = 'block';
})
return;
}
filterables.forEach(filterable => {
const colors = filterable.dataset.colors.split(' ');
if (colorChecked.length >= 1 && sizeChecked.length >= 1) {
if (colorChecked.includes(colors[0]) && sizeChecked.includes(colors[1])) {
filterable.style.display = 'block';
} else {
filterable.style.display = 'none';
}
} else {
if (colorChecked.includes(colors[0]) || sizeChecked.includes(colors[1])) {
filterable.style.display = 'block';
} else {
filterable.style.display = 'none';
}
}
});
}
filterCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', updateFilter);
});
updateFilter(); // initial filter based on default checkbox state
<!-- language: lang-html -->
<div>
<h3>Color</h3>
<label><input type="checkbox" class="filter-checkbox color-checkbox" value="red">Red</label>
<label><input type="checkbox" class="filter-checkbox color-checkbox" value="green">Green</label>
<label><input type="checkbox" class="filter-checkbox color-checkbox" value="blue">Blue</label>
</div>
<div>
<h3>Size</h3>
<label><input type="checkbox" class="filter-checkbox size-checkbox" value="small">Small</label>
<label><input type="checkbox" class="filter-checkbox size-checkbox" value="medium">Medium</label><label>
<input type="checkbox" class="filter-checkbox size-checkbox" value="large">Large</label>
</div>
<div>
<h1>Filtered Result</h1>
<div class="filterable" data-colors="blue large">Product A</div>
<div class="filterable" data-colors="green small">Product B</div>
<div class="filterable" data-colors="red medium">Product C</div>
<div class="filterable" data-colors="red large">Product D</div>
</div>
<!-- end snippet -->
Hope it will be helpful.
答案3
得分: 0
你需要检查元素是否具有N个过滤器值,这里有一个示例代码:
<script>
const filterCheckboxes = document.querySelectorAll('.filter-checkbox');
const filterables = document.querySelectorAll('.filterable');
let filters = [];
// 创建一个处理检查事件的函数
function handleCheck(event) {
if (event) {
// 如果复选框被选中,将值添加到filters数组中
if (event.target.checked) {
filters.push(event.target.value);
updateFilteredItems();
}
// 如果取消选中复选框,从filters数组中删除该值
if (!event.target.checked) {
let index = filters.indexOf(event.target.value);
if (index != -1) {
filters.splice(index, 1);
updateFilteredItems();
}
}
}
}
function updateFilteredItems() {
filterables.forEach(item => {
if (filters.length > 0) {
// 检查项目是否具有过滤器值
let itemValues = item.dataset.colors.split(' ');
// 检查项目值是否在filters数组中
if (filters.length > 1) {
if (filters.includes(itemValues[0]) && filters.includes(itemValues[1])) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
} else {
if (filters.includes(itemValues[0]) || filters.includes(itemValues[1])) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
}
} else {
item.style.display = 'block';
}
})
}
filterCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', handleCheck);
});
</script>
这是你提供的示例代码的翻译部分。
英文:
You have to check if the element has the N filters values, there is a example code:
<script>
const filterCheckboxes = document.querySelectorAll('.filter-checkbox');
const filterables = document.querySelectorAll('.filterable');
let filters = [];
//Create a function to handle the check event
function handleCheck(event) {
if (event) {
//If the box is chjecked, add the value to filters array
if (event.target.checked) {
filters.push(event.target.value);
updateFilteredItems();
}
//If uncheck the box, remove the value form filters array
if (!event.target.checked) {
let index = filters.indexOf(event.target.value);
if (index != -1) {
filters.splice(index, 1);
updateFilteredItems();
}
}
}
}
function updateFilteredItems() {
filterables.forEach(item => {
if (filters.length > 0) {
// lets check if the item has the filters values
let itemValues = item.dataset.colors.split(' ');
//Check if the item values are in the filters array
if (filters.length > 1) {
if (filters.includes(itemValues[0]) && filters.includes(itemValues[1])) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
} else {
if (filters.includes(itemValues[0]) || filters.includes(itemValues[1])) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
}
} else {
item.style.display = 'block'
}
})
}
filterCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', handleCheck);
});
</script>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论