Abbey Abbey - 1 month ago 8
HTML Question

Advanced Filtering with Javascript

I am trying to create an advanced filter with javascript. Where I am running into issues is, when I select more than one check box, I want to show results matching items tagged with all selected checkboxes, not just ones tagged with one of the selected checkboxes. I want the search to become narrowed down as you select more checkboxes.

For example, my website is about damage caused by wildlife. If you select tree damage and flooding, the only thing that should show up is beavers. However, right now you get anything tagged with flooding or tree damage.

Can someone help me set up the "and" filtering rather than the "or" filtering on this? Also, is there a way to make a button clear all search criteria?

Here is a link to my codepen: http://codepen.io/aahmed2/pen/xEBJkL?editors=0010



var $filterCheckboxes = $('input[type="checkbox"]');
var filterFunc = function() {

var selectedFilters = {};

$filterCheckboxes.filter(':checked').each(function() {

if (!selectedFilters.hasOwnProperty(this.name)) {
selectedFilters[this.name] = [];
}

selectedFilters[this.name].push(this.value);
});

var $filteredResults = $('.animal');

$.each(selectedFilters, function(name, filterValues) {
$filteredResults = $filteredResults.filter(function() {

var matched = false,
currentFilterValues = $(this).data('category').split(' ');

$.each(currentFilterValues, function(_, currentFilterValue) {

if ($.inArray(currentFilterValue, filterValues) != -1) {
matched = true;
return false;
}
});
return matched;

});
});

$('.animal').hide().filter($filteredResults).show();
}

$filterCheckboxes.on('change', filterFunc);

body {
font-family: 'Arial';
color: #646464;
}
.animals {
margin-top: 30px;
}
.animal {
padding: 15px 20px;
width: 100%;
font-weight: 700;
background: rgba(0, 0, 0, 0.1);
margin-bottom: 5px;
}

<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h1>Wildlife Damage</h1>
<div class="row">
<div class="col-sm-2">
<div class="btn btn-default">Clear Filters</div>
</div>
<div class="col-sm-2">
<p><strong>Filter Type of Damage:</strong>
<br><small>(Select All That Apply)</small>
</p>
</div>
<form>
<div class="col-sm-2">
<label>
<input type="checkbox" value="vehicle-damage" id="vehicle-damage" />Vehicle Damage</label>
<br>
<label>
<input type="checkbox" value="land-damage" id="land-damage" />Land Damage</label>
<br>
<label>
<input type="checkbox" value="tree-damage" id="tree-damage" />Tree Damage</label>
<br>
<label>
<input type="checkbox" value="plant-damage" id="plant-damage" />Plant Damage</label>
<br>
</div>
<div class="col-sm-2">
<label>
<input type="checkbox" value="structural-invasion" id="structural-invasion" />Structural Invasions</label>
<br>
<label>
<input type="checkbox" value="flooding" id="flooding" />Flooding</label>
<br>
<label>
<input type="checkbox" value="electrical-damage" id="electrical-damage" />Electrical Damage</label>
<br>
<label>
<input type="checkbox" value="nests" id="nests" />Nests</label>
<br>
</div>
<div class="col-sm-2">
<label>
<input type="checkbox" value="holes" id="holes" />Holes</label>
<br>
<label>
<input type="checkbox" value="holes-w-mounds" id="holes-w-mounds" />Holes with Mounds</label>
<br>
<label>
<input type="checkbox" value="bird-egg-loss" id="bird-egg-loss" />Bird and Egg Loss</label>
<br>
</div>
</form>
</div>

<div class="animals">
<div class="animal" data-id="aloe" data-category="structural-invasion">Bats</div>
<div class="animal" data-category="flooding tree-damage">Beaver</div>
<div class="animal" data-category="tree-damage plant-damage vehicle-damage">Deer</div>
<div class="animal" data-category="bird-egg-loss">Feral Cats</div>
<div class="animal" data-category="structural-invasion">Mice</div>
<div class="animal" data-category="holes-w-mounds">Moles</div>
<div class="animal" data-category="structural-invasion land-damage plant-damage bird-egg-loss">Opossum</div>
<div class="animal" data-category="holes-w-mounds land-damage">Pocket Gopher</div>
<div class="animal" data-category="plant-damage land-damage holes-w-mounds">Prairie Dogs</div>
<div class="animal" data-category="plant-damage nests">Rabbits</div>
<div class="animal" data-category="structural-invasion tree-damage land-damage plant-damage bird-egg-loss">Raccoons</div>
<div class="animal" data-category="structural-invasion land-damage">Rats</div>
<div class="animal" data-category="land-damage bird-egg-loss">Skunks</div>
<div class="animal" data-category="structural-invasion">Garter Snakes</div>
<div class="animal" data-category="vehicle-damage electrical-damage structural-invasion tree-damage">Squirrels</div>
<div class="animal" data-category="holes">13-lined Ground Squirrel</div>
<div class="animal" data-category="plant-damage land-damage">Voles</div>
</div>
</div>




Answer

Try this, I removed some code and comments for brevity. Essentially, for each element, you want to make sure all selectedFilters are found. This example uses Array.prototype.every() for this:

var $filterCheckboxes = $('input[type="checkbox"]');
var filterFunc = function() {

  var selectedFilters = [];

  $filterCheckboxes.filter(':checked').each(function() {
    var v = this.value;
    if (selectedFilters.indexOf(v) === -1) 
        selectedFilters.push(v);
  });
  
  $('.animal')
    .hide()
    .filter( 
       function(_,a) {
          var itemCat = $(a).data('category').split(' ');
          return selectedFilters.every( 
            function(c){
               return itemCat.indexOf(c) > -1;
            })
    })
    .show();

}

$filterCheckboxes.on('change', filterFunc);
body {
  font-family: 'Arial';
  color: #646464;
}
.animals {
  margin-top: 30px;
}
.animal {
  padding: 15px 20px;
  width: 100%;
  font-weight: 700;
  background: rgba(0, 0, 0, 0.1);
  margin-bottom: 5px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <h1>Wildlife Damage</h1>
  <div class="row">
    <div class="col-sm-2">
      <div class="btn btn-default">Clear Filters</div>
    </div>
    <div class="col-sm-2">
      <p><strong>Filter Type of Damage:</strong>
        <br><small>(Select All That Apply)</small>
      </p>
    </div>
    <form>
      <div class="col-sm-2">
        <label>
          <input type="checkbox" value="vehicle-damage" id="vehicle-damage" />Vehicle Damage</label>
        <br>
        <label>
          <input type="checkbox" value="land-damage" id="land-damage" />Land Damage</label>
        <br>
        <label>
          <input type="checkbox" value="tree-damage" id="tree-damage" />Tree Damage</label>
        <br>
        <label>
          <input type="checkbox" value="plant-damage" id="plant-damage" />Plant Damage</label>
        <br>
      </div>
      <div class="col-sm-2">
        <label>
          <input type="checkbox" value="structural-invasion" id="structural-invasion" />Structural Invasions</label>
        <br>
        <label>
          <input type="checkbox" value="flooding" id="flooding" />Flooding</label>
        <br>
        <label>
          <input type="checkbox" value="electrical-damage" id="electrical-damage" />Electrical Damage</label>
        <br>
        <label>
          <input type="checkbox" value="nests" id="nests" />Nests</label>
        <br>
      </div>
      <div class="col-sm-2">
        <label>
          <input type="checkbox" value="holes" id="holes" />Holes</label>
        <br>
        <label>
          <input type="checkbox" value="holes-w-mounds" id="holes-w-mounds" />Holes with Mounds</label>
        <br>
        <label>
          <input type="checkbox" value="bird-egg-loss" id="bird-egg-loss" />Bird and Egg Loss</label>
        <br>
      </div>
    </form>
  </div>

  <div class="animals">
    <div class="animal" data-id="aloe" data-category="structural-invasion">Bats</div>
    <div class="animal" data-category="flooding tree-damage">Beaver</div>
    <div class="animal" data-category="tree-damage plant-damage vehicle-damage">Deer</div>
    <div class="animal" data-category="bird-egg-loss">Feral Cats</div>
    <div class="animal" data-category="structural-invasion">Mice</div>
    <div class="animal" data-category="holes-w-mounds">Moles</div>
    <div class="animal" data-category="structural-invasion land-damage plant-damage bird-egg-loss">Opossum</div>
    <div class="animal" data-category="holes-w-mounds land-damage">Pocket Gopher</div>
    <div class="animal" data-category="plant-damage land-damage holes-w-mounds">Prairie Dogs</div>
    <div class="animal" data-category="plant-damage nests">Rabbits</div>
    <div class="animal" data-category="structural-invasion tree-damage land-damage plant-damage bird-egg-loss">Raccoons</div>
    <div class="animal" data-category="structural-invasion land-damage">Rats</div>
    <div class="animal" data-category="land-damage bird-egg-loss">Skunks</div>
    <div class="animal" data-category="structural-invasion">Garter Snakes</div>
    <div class="animal" data-category="vehicle-damage electrical-damage structural-invasion tree-damage">Squirrels</div>
    <div class="animal" data-category="holes">13-lined Ground Squirrel</div>
    <div class="animal" data-category="plant-damage land-damage">Voles</div>
  </div>
</div>

Comments