Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a filter in javascript which filters div by checkboxes

I need make a filter by checkboxes, which will specify two or more options in one category. My filter filters one option in each category.

function change() {
  let results = Array.from(document.querySelectorAll('.result > div'));
  // Hide all results
  results.forEach(function(result) {
    result.style.display = 'none';
  });
  // Filter results to only those that meet ALL requirements:
  Array.from(document.querySelectorAll('.filter input[rel]:checked'), function(input) {
    const attrib = input.getAttribute('rel');
    results = results.filter(function(result) {
      return result.classList.contains(attrib);
    });
  });
  // Show those filtered results:
  results.forEach(function(result) {
    result.style.display = 'block';
  });
}
change();
<div class="filter">
  <h1>Select models</h1>
  <div class="checkbox">
    <label><input type="checkbox" rel="apple" onchange="change()"/>Apple</label>
  </div>
  <div class="checkbox">
    <label><input type="checkbox" rel="samsung" onchange="change()"/>Samsung</label>
  </div>
  <div class="checkbox">
    <label><input type="checkbox" rel="xiaomi" onchange="change()"/>Xiaomi</label>
  </div>
  <h1>Select processors</h1>
  <div class="checkbox">
    <label><input type="checkbox" rel="a9" onchange="change()"/>A9</label>
  </div>
  <div class="checkbox">
    <label><input type="checkbox" rel="a8" onchange="change()"/>A8</label>
  </div>
  <div class="checkbox">
    <label><input type="checkbox" rel="snapdragon" onchange="change()"/>Snapdragon</label>
  </div>
  <div class="checkbox">
    <label><input type="checkbox" rel="exynos" onchange="change()"/>Exynos</label>
  </div>
</div>

<div class="result">
  <div class="apple a9">
    <h1>iPhone 7</h1>
  </div>
  <div class="apple a8">
    <h1>iPhone 6</h1>
  </div>
  <div class="samsung exynos">
    <h1>Samsung s7</h1>
  </div>
  <div class="xiaomi snapdragon">
    <h1>Xiaomi Redmi note 4x</h1>
  </div>
</div>

So in result I cannot choose Apple and Samsung simultaneously. I can choose only one options in each group. It is like a radiobutton. But I need checkbox with multiply options

like image 359
Shyngys Rakhad Avatar asked Oct 15 '25 22:10

Shyngys Rakhad


1 Answers

As I understand you (by reading the comments) You want to have the the following behaviour:

  • The model or processor checkboxes are "OR" correlation inside their filter-group.
  • But the phone has to be of any checked model and must have any of the checked processors.

This code should solve your issue/question:

function change() {
  var modelCbs = document.querySelectorAll(".models input[type='checkbox']");
  var processorCbs = document.querySelectorAll(".processors input[type='checkbox']");
  var filters = {
    models: getClassOfCheckedCheckboxes(modelCbs),
    processors: getClassOfCheckedCheckboxes(processorCbs)
  };

  filterResults(filters);
}

function getClassOfCheckedCheckboxes(checkboxes) {
  var classes = [];

  if (checkboxes && checkboxes.length > 0) {
    for (var i = 0; i < checkboxes.length; i++) {
      var cb = checkboxes[i];

      if (cb.checked) {
        classes.push(cb.getAttribute("rel"));
      }
    }
  }

  return classes;
}

function filterResults(filters) {
  var rElems = document.querySelectorAll(".result div");
  var hiddenElems = [];

  if (!rElems || rElems.length <= 0) {
    return;
  }

  for (var i = 0; i < rElems.length; i++) {
    var el = rElems[i];

    if (filters.models.length > 0) {
      var isHidden = true;

      for (var j = 0; j < filters.models.length; j++) {
        var filter = filters.models[j];

        if (el.classList.contains(filter)) {
          isHidden = false;
          break;
        }
      }

      if (isHidden) {
        hiddenElems.push(el);
      }
    }

    if (filters.processors.length > 0) {
      var isHidden = true;

      for (var j = 0; j < filters.processors.length; j++) {
        var filter = filters.processors[j];

        if (el.classList.contains(filter)) {
          isHidden = false;
          break;
        }
      }

      if (isHidden) {
        hiddenElems.push(el);
      }
    }
  }

  for (var i = 0; i < rElems.length; i++) {
    rElems[i].style.display = "block";
  }

  if (hiddenElems.length <= 0) {
    return;
  }

  for (var i = 0; i < hiddenElems.length; i++) {
    hiddenElems[i].style.display = "none";
  }
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
</head>

<body>
  <div class="filter">
    <h1>Select models</h1>
    <div class="models">
      <div class="checkbox">
        <label><input type="checkbox" rel="apple" onchange="change();"/>Apple</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" rel="samsung" onchange="change();"/>Samsung</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" rel="xiaomi" onchange="change();"/>Xiaomi</label>
      </div>
    </div>
    <h1>Select processors</h1>
    <div class="processors">
      <div class="checkbox">
        <label><input type="checkbox" rel="a9" onchange="change();"/>A9</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" rel="a8" onchange="change();"/>A8</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" rel="snapdragon" onchange="change();"/>Snapdragon</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" rel="exynos" onchange="change();"/>Exynos</label>
      </div>
    </div>
  </div>

  <div class="result">
    <div class="apple a9">
      <h1>iPhone 7</h1>
    </div>
    <div class="apple a8">
      <h1>iPhone 6</h1>
    </div>
    <div class="samsung exynos">
      <h1>Samsung s7</h1>
    </div>
    <div class="xiaomi snapdragon">
      <h1>Xiaomi Redmi note 4x</h1>
    </div>
  </div>
</body>
like image 87
flx Avatar answered Oct 18 '25 12:10

flx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!