1

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>

1
  • If i get your question right then make matched a integer and use matched += 1 every time it matches and if matched count equals to the filter selected count it should show that record. Commented Oct 25, 2016 at 16:11

2 Answers 2

4

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>

Sign up to request clarification or add additional context in comments.

4 Comments

Also, to go back to OR logic just replace selectedFilters.every(...) with selectedFilters.some(...).
Perfect! Thank you for your help!
Absolutely perfect, I was searching for something like this for a looong time :) Just FYI for other noobs than me: you need to have the bootstrap.min.css and jquery.min.js under <head> and script in <script> tags in the bottom of your body. Or at least didn't work for me if I didn't do it that way. Thanks and cheers!
0

You can filter .animal and then filter $filterCheckboxes

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

var filterFunc = function() {
  $('.animal').hide().filter(function(){
    var cat = $(this).attr('data-category').split(' ');
    return $filterCheckboxes.filter(function(){
      return this.checked && $.inArray(this.value, cat) !== -1;
    }).length;
  }).show();
}

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

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

var filterFunc = function() {
  $('.animal').hide().filter(function(){
    var cat = $(this).attr('data-category').split(' ');
    return $filterCheckboxes.filter(function(){
      return this.checked && $.inArray(this.value, cat) !== -1;
    }).length;
  }).show();
}

$filterCheckboxes.on('change', filterFunc).change();
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.