javascript - 多个单选按钮作为过滤器
问题描述
问题
我正在尝试创建一个双重过滤器,您可以在其中组合来自多个类别的过滤器。例如,第一类过滤器是年份,第二类是媒体。我想让您只能过滤年份、媒体类型或两种年份 x 类型的媒体(1960 年代的音乐)。另外,我试图保持选定的过滤器突出显示,以便您可以跟踪哪些是活动的(我试图使它们加粗,它适用于第一组过滤器,但第二组失败。我该如何解决这个问题?
密码笔
https://codepen.io/erutuf/pen/ZPwdBq
试图
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
element.className += " " + arr2[i];
}
}
}
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
.filterDiv {
float: left;
background-color: white;
color: black;
width: 37vw;
line-height: 100px;
text-align: center;
margin: 5px;
display: none;
margin-right: 15px;
}
.show {
display: block;
}
.container {
margin-top: 20px;
overflow: hidden;
}
/* Style the buttons */
.btn {
border: none;
outline: none;
padding: 0;
padding-right: 40px;
background-color: white;
cursor: pointer;
font-size: 16px;
font-weight: normal;
}
.btn:hover {}
.btn.active {
font-weight: bold;
}
.content {
font-size: 16px;
line-height: 20px;
text-align: left;
}
<div id="myBtnContainer" align="center" style="line-height: 20pt">
<!-- <button class="btn active" onclick="filterSelection('all')"> Show all</button> Show ALL -->
<button class="btn active" onclick="filterSelection('ShowAll')">Show all</button>
<button class="btn" onclick="filterSelection('1950')">1950</button>
<button class="btn" onclick="filterSelection('1960')">1960</button>
<button class="btn" onclick="filterSelection('1970')">1970</button>
</div>
<br>
<div id="myBtnContainer" align="center" style="line-height: 20pt">
<!-- <button class="btn active" onclick="filterSelection('all')"> Show all</button> Show ALL -->
<button class="btn" onclick="filterSelection('AllMedia')">All Media</button>
<button class="btn" onclick="filterSelection('Movies')">Movies</button>
<button class="btn" onclick="filterSelection('Music')">Music</button>
<button class="btn" onclick="filterSelection('Newspapers')">Newspapers</button>
</div>
<br><br>
<div class="filterDiv AllShapes ShowAll 1950 Newspapers">
<div class="content">
1950 Newspapers Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
</div>
<div class="filterDiv AllShapes ShowAll 1960 Music">
<div class="content">
1960 Music Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
</div>
<div class="filterDiv AllShapes ShowAll 1960 Newspapers">
<div class="content">
1960 Newspapers Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
</div>
解决方案
最简单的方法是使用<label>
和type="radio"
输入。您可以设置与输入 相邻 ( )
的内部元素的样式。<i>
+
:checked
将过滤器引用 ( props ) 存储到data-filterable="value1 value2 valueZ"
空格分隔中。
诀窍是:
- 在更改事件中,将检查的输入值作为数组获取。
- 隐藏所有元素(添加一个
.is-hidden
类) - 获取要显示的元素的过滤子集- 基于是否所有检查的值都存在于
data-filterable
道具中(也作为数组)。
以下示例适用于任意数量的过滤器集:
const el_filters = document.querySelectorAll('[name="year"], [name="type"]'),
el_filterable = document.querySelectorAll('[data-filterable]');
const applyFilter = () => {
// Filter checked inputs
const el_checked = [...el_filters].filter(el => el.checked && el.value);
// Collect checked inputs values to array
const filters = [...el_checked].map(el => el.value);
// Get elements to filter
const el_filtered = [...el_filterable].filter(el => {
const props = el.getAttribute('data-filterable').trim().split(/\s+/);
return filters.every(fi => props.includes(fi))
});
// Hide all
el_filterable.forEach(el => el.classList.add('is-hidden'));
// Show filtered
el_filtered.forEach(el => el.classList.remove('is-hidden'));
}
// Assign event listener
el_filters.forEach(el => el.addEventListener('change', applyFilter));
// Init
applyFilter();
/* FILTER INPUTS */
.filterInputs {
padding-bottom: 5px;
}
.filterInputs input {
display: none;
}
.filterInputs label {
display: inline-block;
position: relative;
padding: 10px 20px;
cursor: pointer;
user-select: none; /* prevent highlight */
}
.filterInputs i {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-shadow: inset 0 0 0 2px #0bf;
z-index: -1;
}
.filterInputs input:checked + i {
background: #0bf;
}
/* HELPER CLASSES */
.is-hidden {
display: none;
}
<div class="filterInputs">
<label><input type="radio" name="year" value="" checked><i></i>All years</label>
<label><input type="radio" name="year" value="1950"><i></i>1950</label>
<label><input type="radio" name="year" value="1960"><i></i>1960</label>
<label><input type="radio" name="year" value="1970"><i></i>1970</label>
</div>
<div class="filterInputs">
<label><input type="radio" name="type" value=""><i></i>All types</label>
<label><input type="radio" name="type" value="movies"><i></i>Movies</label>
<label><input type="radio" name="type" value="music" checked><i></i>Music</label>
<label><input type="radio" name="type" value="newspapers"><i></i>Newspapers</label>
</div>
<div data-filterable="1950 newspapers">1950 Newspapers</div>
<div data-filterable="1960 music">1960 Music</div>
<div data-filterable="1960 newspapers">1960 Newspapers</div>
推荐阅读
- visual-studio-code - 命令选择器的 VSCode 导航键绑定
- swift - TPPDF 表格对齐方式
- python - 如何更改屈服值
- c# - 弹出控件中的控件在第二次打开时失去交互
- html - 使用 selenium 下载文件时的 ERR_BLOCKED_BY_XSS_AUDITOR
- selenium - 我们是否需要在 Selenium 网格上安装 Chrome 二进制文件以避免出现“WebDriverError:未知错误:找不到 Chrome 二进制文件”?
- node.js - 如何捕获 child_process 重新启动/分叉自身
- python - 甜甜圈图并排
- android - 如何在活动中从 MediaBrowserServiceCompat 访问 exoplayer 实例?
- c# - 文件上传到 ASP.NET Core 中的 wwwroot 文件夹