samedi 28 août 2021

How can I exclude a certain checkbox class from a jQuery filter if another class's checkbox is already checked?

I'm brand new to coding and have no idea what I'm doing. I feel like I'm not very good at explaining things, either, so I'm sorry if this post is a bit hard to understand. Hopefully looking at the code itself makes more sense.

Basically, I have a list that can be filtered. Each list item contains multiple classes. I also have checkboxes to display each individual class.

However, there are a couple of classes that overlap in terms of list items they apply to but are not exactly the same.

Say, for example, somebody wants to look for things in Class A, but not include things in Class D. If Class A is checked, it will automatically display all list items that Class D also applies to.

What I would like to do is make it so that if Class A is checked, you have the option to also exclude Class D from your search, so that overlapping data can be displayed. Vice versa applies too (ie if Class D is checked, have an option to exclude Class A).

I want the exclusion of classes to be an option, not the default state. Some users may be interested in looking at both Class A and Class D, others may only want one.

<div class="options">
  <label><input type="radio" name="operation" value="union" id="op-union" checked>A or B</label>
  <label><input type="radio" name="operation" value="intersection" id="op-inter">A and B</label>
</div>

<div class="categories">
<span class="category"><input type="checkbox" value="classa" id="cat-classa"><label for="cat-classa">Class A</label></span>
<span class="category"><input type="checkbox" value="classb" id="cat-classb"><label for="cat-classb">Class B</label></span>
<span class="category"><input type="checkbox" value="classc" id="cat-classc"><label for="cat-classc">Class C</label></span>
<span class="category"><input type="checkbox" value="classd" id="cat-classd"><label for="cat-classd">Class D</label></span>
<span class="category"><input type="checkbox" value="classe" id="cat-classe"><label for="cat-classe">Class E</label></span>
<span class="category"><input type="checkbox" value="classf" id="cat-classf"><label for="cat-classf">Class F</label></span>
</div>

<div class="container"> 
<ul>
<div class="filterDiv classa classd"><li>List 1</li></div>
<div class="filterDiv classa classe"><li>List 2</li></div>
<div class="filterDiv classb classd classe"><li>List 3</li></div>
<div class="filterDiv classc classf">List 4</li></div>
<div class="filterDiv classb classd classf">List 5</li></div>
</ul>
</div>

Given the nature of the list, any combination of class and type is possible. Typically, there is only one class, but on occasion there are two. In the actual list, I have far more than just three classes attached to one list item, too.

Script:

<script>
var checkboxes = document.querySelectorAll(".categories input");
for(var i = 0; i < checkboxes.length; i++) {
  checkboxes[i].addEventListener("change", filter);
}
var radios = document.getElementsByName("operation");
for(var i = 0; i < radios.length; i++) {
  radios[i].addEventListener("change", filter);
}
filter();
function filter() {
  var i, j;

  // Choose an operation
  var operation = document.getElementById("op-union").checked ? "union" : "intersection";

  // Get the selected categories
  var checkboxes = document.querySelectorAll(".categories input");
  var categories = [];
  var c;
  for(i = 0; i < checkboxes.length; i++) {
    if(checkboxes[i].checked) {
      c = checkboxes[i].value;
      categories.push(c);
    }
  }

  // Apply the filter
  var items = document.querySelectorAll(".filterDiv");
  var item, show;
  for(i = 0; i < items.length; i++) {
    item = items[i];
    if(categories.length == 0) {
      show = true;
    } else if(operation == "union") {
      // Union: Only one of the categories needs to exist
      show = false;
      for(j = 0; j < categories.length; j++) {
        if(item.classList.contains(categories[j])) {
          show = true;
          break;
        }
      }
    } else {
      // Intersection: All of the categories must apply
      show = true;
      for(j = 0; j < categories.length; j++) {
        if(!item.classList.contains(categories[j])) {
          show = false;
          break;
        }
      }
    }

    if(show) {
      item.classList.add("show");
    } else {
      item.classList.remove("show");
    }
  }
}
</script>

Thanks heaps in advance to anyone who helps! Once again I apologise for the wording, I'm new to this and still figuring my way around it all. Any attempts are much appreciated.




Aucun commentaire:

Enregistrer un commentaire