javascript - 多个单选按钮作为过滤器

标签 javascript html onclick

问题

我正在尝试创建一个双重过滤器,您可以在其中组合来自多个类别的过滤器。例如,第一类过滤器是年份,第二类是媒体。我想让您只能通过年份、媒体类型或年份 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 中是否存在所有选中的值,获取元素的过滤子集以显示 props(也作为数组)。

以下示例适用于任意数量的过滤器集:

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>

关于javascript - 多个单选按钮作为过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55329176/

相关文章:

javascript - 我应该导入 useState 和 useEffect 还是可以使用 React.useState 和 React.useEffect ?

Javascript 嵌套 AJAX 请求

html - 容器中溢出滚动的图像右侧的额外空间

java - 如何将我的 Android 应用程序链接到另一个内置应用程序(例如谷歌地图)?

javascript - 在移动设备的 safari 中,<a href ="#"onclick ="return false"> 不起作用,为什么?

javascript - 如何播放/服务/流式传输视频到本地 html 站点? vlc/ffmpeg?

java - 当我尝试运行此应用程序时出现 setOnClickListener 错误

html - 如何选择 ID 以数字开头的元素?

javascript - 我如何知道用户正在浏览网页的哪一部分?

javascript - 单击 img border = #color - 多个图像 - 一次只需要突出显示 1 个图像