首页 > 解决方案 > 多个单选按钮作为过滤器

问题描述

问题

我正在尝试创建一个双重过滤器,您可以在其中组合来自多个类别的过滤器。例如,第一类过滤器是年份,第二类是媒体。我想让您只能过滤年份、媒体类型或两种年份 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>

标签: javascripthtmlonclick

解决方案


最简单的方法是使用<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>


推荐阅读