How can I filter products on multiple checkboxes?

I am working on a product page where the user has an option to filter on different boardgames. What I want to do is to give the user an option to filter on time, category of the game, number of players and age. When the user enters a checkbox on all 4 options there should be some games recommended based on the criteria. However when I check multiple boxes I get no result, what am I doing wrong? (I have more games in my file but post small amount)

Here’s my code:

// set up variables
var categoryFilters = [];
var categoryFilter;

// init Isotope
var $container = $('#products').isotope({
  itemSelector: '.boardgame',
  filter: function() {
    var $this = $(this);
    categoryFilter = categoryFilters.length ? categoryFilters.join(' ') : 'all';
    console.log(categoryFilter)
    var categoryResult = categoryFilter ? $this.is('[data-category*=' + categoryFilter + ']') : true;
    console.log(categoryResult)
    return categoryResult;
  }
});

// filter with checkboxes
var $checkboxes = $('#filtering input');

$checkboxes.change( function() {
  categoryFilters.length = 0;
  $checkboxes.each( function( i, elem ) {
    if ( elem.checked ) {
      categoryFilters.push( elem.value );
    }
    $container.isotope();
  });
});
* { 
    box-sizing: border-box;
}

body { 
    font-family: sans-serif;
}

img{
    height: 265px;
    width: 265px;
}
select, label, input { 
    font-size: 20px; 
}

label { 
    margin-right: 10px; 
}

.productbutton {
  background: #85bf31;
  border: none;
  border-radius: 2px;
  color: #FFF;
  font-weight: bold;
  font-size: 20px;
  padding: 0.6em 2em;
  margin-top: auto;
  text-decoration: none;
}
.productbutton:hover {
  background: rgb(0, 51, 109);
  border-radius: 2px;
  color: #FFF;
  text-decoration: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://npmcdn.com/[email protected]/dist/isotope.pkgd.js"></script>

<div id="filtering" class="filterlist">
    <h4>Minutes</h4>
        <label class="container"><input type="checkbox" value="15" /> tot 15 min <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="30" /> 15 - 30 min. <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="60" /> 30 - 60 min. <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="90" /> Meer dan 60 min. <span class="checkmark"></span></label>          

    <h4>Category</h4>
        <label class="container"><input type="checkbox" value="Strategie" /> Strategie <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="Family" /> Familie <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="Kaartspel" /> Kaart <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="Coop" /> Coöperatief <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="Deductief" /> Deductief <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="Kinder" /> Kinder <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="Fantasy" /> Fantasy <span class="checkmark"></span></label>

    <h4>Players</h4>
        <label class="container"><input type="checkbox" value="1" /> 1 <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="2" /> 2 <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="3" /> 3 <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="4" /> 4 <span class="checkmark"></span></label>

    <h4>Age</h4>
        <label class="container"><input type="checkbox" value="8" /> 8 jaar <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="10" /> 10 jaar <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="12" /> 12 jaar <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="15" /> 15 jaar <span class="checkmark"></span></label>
        <label class="container"><input type="checkbox" value="18" /> 18 jaar <span class="checkmark"></span></label>
</div>


<div>
    <div id="products">
    <ul class="products" id="products">
            <div class="boardgame" data-category="90 3 all 12 Strategie">
                    <li>
                    <img src="img/Catan-Inkas-1.jpg" alt="Catan Histories: Rise of the Inkas">
                    <h3>Catan Histories: Rise of the Inkas</h3>
                    <a href="catan-rise-of-the-incas.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="30 2 all 8 Family">
                    <li>
                    <img src="img/Carcassonne.jpg" alt="Carcassonne">
                    <h3>Carcassonne</h3>
                    <a href="carcassonne.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="30 2 all 12 Coop">
                    <li>
                    <img src="img/Paranormal-Detectives.jpg" alt="Paranormal Detectives">
                    <h3>Paranormal Detectives</h3>
                    <a href="paranormaldetectives.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="90 3 all 12 Strategie">
                    <li>
                    <img src="img/catan-cities-and-knights.jpg" alt="Catan: Cities & Knights Expansion">
                    <h3>Catan: Cities & Knights Expansion</h3>
                    <a href="catan-cities-and-knights.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="60 2 all 12 Coop">
                    <li>
                    <img src="img/Thanos-Rising.jpg" alt="Thanos Rising – Avengers: Infinity War">
                    <h3>Thanos Rising – Avengers: Infinity War</h3>
                    <a href="thanos-rising.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="90 2 all 12 Strategie">
                    <li>
                    <img src="img/Marco-Polo-II.jpg" alt="Marco Polo II: In the Service of the Khan">
                    <h3>Marco Polo II: In the Service of the Khan</h3>
                    <a href="marco-polo-2-in-the-service-of-the-khan.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="90 2 all 15 Fantasy">
                    <li>
                    <img src="img/dune.jpg" alt="Dune">
                    <h3>Dune</h3>
                    <a href="dune.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="60 1 all 15 Deductief">
                    <li>
                    <img src="img/Chronicles.jpg" alt="Chronicles of Crime">
                    <h3>Chronicles of Crime</h3>
                    <a href="chronicles-of-crime.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="30 2 all 8 Family">
                    <li>
                    <img src="img/Kingdom-Builder-Family-Box.jpg" alt="Kingdom Builder Family Box">
                    <h3>Kingdom Builder Family Box</h3>
                    <a href="kingdom-builder-family-box.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="15 3 all 8 Family">
                    <li>
                    <img src="img/just-one.jpg" alt="Just One">
                    <h3>Just One</h3>
                    <a href="just-one.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="60 3 all 15 Strategie">
                    <li>
                    <img src="img/AGOT-Catan-Brotherhood-of-the-watch.jpg" alt="A Game of Thrones Catan – Brotherhood of the Wall">
                    <h3>A Game of Thrones Catan – Brotherhood of the Wall</h3>
                    <a href="a-game-of-thrones-catan-brotherhood-of-the-watch.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="90 1 all 12 Deductief">
                    <li>
                    <img src="img/jacktheripper.jpg" alt="Sherlock Holmes Consulting Detective: Jack the Ripper & West End Adventures">
                    <h3>Sherlock Holmes Consulting Detective: Jack the Ripper & West End Adventures</h3>
                    <a href="sherlock-holmes-jack-the-ripper.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="60 2 all 12 Coop">
                    <li>
                    <img src="img/unlock.jpg" alt="Unlock!">
                    <h3>Unlock!</h3>
                    <a href="unlock.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="30 1 all 8 Strategie">
                    <li>
                    <img src="img/pandemic-inthelab.jpg" alt="Pandemic: In the Lab">
                    <h3>Pandemic: In the Lab</h3>
                    <a href="pandemic-in-the-lab.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
                    <div class="boardgame" data-category="30 2 all 8 Strategie">
                    <li>
                    <img src="img/pandemic.jpg" alt="Pandemic">
                    <h3>Pandemic</h3>
                    <a href="pandemic.html" class="productbutton">Meer info</a> 
                    </li>
                    </div>
    </div>

</div>

Answer

So here is the problem :

categoryFilter = categoryFilters.length ? categoryFilters.join(' ') : 'all';

You’re trying to join every filter in the same order user clicks on checkboxes but there is an exception.
Consider this data-category as below:

data-category="90 3 all 12 Strategie"

This product will only be displayed when user clicks on filter 90 and then 3 and so on …
But what if user clicks on 90 filter and then Strategie. The code will generate 90 Strategie string. So there will be no products.
To fix this problem, you need to check for every categoryFilter on your data-category :

function checkCategory(element) {
      const cat = element.attr('data-category');
      let flag = true;
      for(i=0; i<categoryFilters.length; i++) {
        if(!cat.includes(categoryFilters[i])) {
          flag = false;
        } 
      }
      return flag;
}

And then use it :

var categoryResult = categoryFilter ? checkCategory($this) : true;

Live code on codepen


Here is the complete JS file along with above changes:

// set up variables
var categoryFilters = [];
var categoryFilter;

// init Isotope
var $container = $('#products').isotope({
  itemSelector: '.boardgame',
  filter: function() {
    var $this = $(this);
    categoryFilter = categoryFilters.length ? categoryFilters.join(' ') : 'all';
var categoryResult = categoryFilter ? checkCategory($this) : true;
    return categoryResult;
  }
});

function checkCategory(element) {
  const cat = element.attr('data-category');
  let flag = true;
  for(i=0; i<categoryFilters.length; i++) {
    if(!cat.includes(categoryFilters[i])) {
      flag = false;
    } 
  }
  return flag;
}

// filter with checkboxes
var $checkboxes = $('#filtering input');

$checkboxes.change( function() {
  categoryFilters.length = 0;
  $checkboxes.each( function( i, elem ) {
    if ( elem.checked ) {
      categoryFilters.push( elem.value );
    }
    $container.isotope();
  });
});