使用onclick JavaScript和HTML的多个过滤器

时间:2019-03-24 22:25:29

标签: javascript html onclick

问题

我正在尝试创建一个双重过滤器,您可以在其中组合多个类别的过滤器。例如,第一类过滤器是年份,第二类过滤器。我想做的是仅过滤年份,媒体类型或年份x类型的媒体(1960年代的音乐)。另外,我试图以某种方式使选定的过滤器保持突出显示状态,以便您可以跟踪哪些过滤器处于活动状态(我试图将它们设为粗体,并且该过滤器适用于第一组过滤器,但对于第二组过滤器却不起作用。如何解决这个问题吗?

Codepen

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>

3 个答案:

答案 0 :(得分:1)

最简单的方法是使用<label>type="radio"输入。
您可以设置内部<i>元素的样式,该元素与+输入相邻(:checked)。

将过滤器引用( props )存储在data-filterable="value1 value2 valueZ" 分隔的空格中。

诀窍是:

  • 发生 change 事件时,将选中的输入值作为数组。
  • 隐藏所有元素(添加一个.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>

答案 1 :(得分:1)

在这种情况下,我使用了属性选择器([filter][group]

(function(){
  const selectedFilters = [];

  // [].slice.call => converts HTMLCollection to Array

  const yearFilters = [].slice.call(document.querySelectorAll('[filter][group="year"]'));
  const mediaFilters = [].slice.call(document.querySelectorAll('[filter][group="media"]'));
  const allFilters = yearFilters.concat(mediaFilters);
  
  const filterContents = [].slice.call(document.querySelectorAll('.filterDiv'));

  // add click event to all filters
  allFilters.forEach((filter) => {
    filter.addEventListener('click', filterToggle);
  });
    
  function filterToggle() {
    const filter = this.getAttribute('filter');
    const group = this.getAttribute('group');

    resetMediaFilters();
    
    if(group === 'year') {
      resetYearFilters();
      mediaFilters[0].classList.add('active');
    }    

    this.classList.add('active');
    applyFilter();
  }
  
  function resetYearFilters() {
    yearFilters.forEach(filter => filter.classList.remove('active'));
  }
  
  function resetMediaFilters() {
    mediaFilters.forEach(filter => filter.classList.remove('active'));
  }
  
  function resetFilterContent() {
    filterContents.forEach(content => content.classList.remove('show'));
  }

  function applyFilter() {
    const selectedFilters = [].slice.call(document.querySelectorAll('[filter].active'))
                        .map(filter => filter.getAttribute('filter'));

// class starts with number is a invalid query selector, so using attribute selector for class
    const selector = ["filterDiv"].concat(selectedFilters).map(filter => '[class~="'+ filter +'"]').join('');
    
    resetFilterContent();
    
    document.querySelectorAll(selector).forEach(content => content.classList.add('show'));
  }
  
  // initialize
  applyFilter();
})();
.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" filter="ShowAll" group="year">Show all</button>
  <button class="btn" filter="1950" group="year">1950</button>
  <button class="btn" filter="1960" group="year">1960</button>
  <button class="btn" filter="1970" group="year">1970</button>
</div>
<br>
<div id="myBtnContainer" align="center" style="line-height: 20pt">
  <button class="btn active" filter="AllMedia" group="media">All Media</button>
  <button class="btn" filter="Movies" group="media">Movies</button>
  <button class="btn" filter="Music" group="media">Music</button>
  <button class="btn" filter="Newspapers" group="media">Newspapers</button>
</div>

<br><br>

 <div class="filterDiv AllMedia 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 AllMedia 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 AllMedia 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>

答案 2 :(得分:-1)

您在javascript中有一个document.getElementsByClassName()函数,可在此处为您提供帮助。 DOCS:https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp 您可以获取与要定位的类匹配的元素数组,然后可以对其进行迭代以添加/删除使它们显示或隐藏的hidden属性或css类。 想要加粗的按钮也可以使用同样的方法。

伪代码示例:

package edu.psgv.sweng861;

import java.net.*; 
import java.util.Scanner; 
import java.io.*; 
/**
 * A complete Java class that demonstrates how to read content (text) from a
 * URL using the Java URL and URLConnection classes. There is no user input in
 * this program, just a hard-wired url to fetch a conforming Http live streaming
 * playlist.  
 */
 public class JavaUrlConnectionReader {
     public static void main(String[] args) {
         Scanner myObj = new Scanner(System.in);  // Create a Scanner object
         System.out.println("Enter URL:");
         String userUrl = myObj.nextLine();  // Read user input
         System.out.println("User URL is: " + userUrl);  // Output user input 
     }

     private static String getUrlContents(String theUrl) {
         String content = "";
         try {
             URL url = new URL(theUrl);
             URLConnection urlConnection = url.openConnection();
             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
             String line;
             while ((line = bufferedReader.readLine()) != null) {
                 content += line + "\n";
             }
             bufferedReader.close();
         } catch(Exception e) {
             System.out.println("The url was invalid, please try again");
         }
         return content;
    }
}

如果单击的按钮为ALL,则逻辑有些不同,但这只是使用if-elses的问题。

请记住,每个元素上还具有addClass和removeClass方法。您不必将类列​​表转换为类的数组并对其进行迭代。比这简单得多: https://www.w3schools.com/howto/howto_js_remove_class.asp