'Filtering result based on checkboxes with jQuery using value and class

To start off with here's a fiddle of what I have right now: link to JSFiddle, code below:

<!DOCTYPE html>   
<head>
<title>Homes Selection Tester</title>
<style>
body {width: 100%;}
#wrapper {width: 640px;overflow: auto;}
ul li {list-style-type: none;}
#aptresults {width: 300px;float: left;}
#selections {width: 330px;float: left;}
</style>
</head>
<body>

<div id="wrapper">
    <div id="content">

        <div id="heading">
            <h1 class="inline">Homes</h1>
        </div>

        <div id="selections">
            <b>Oppervlakte</b>
            <ul class="apt-opper">
                <li >
                    <input type="checkbox" value="o50" />
                    <label for="o50">50m2 - 100m2</label>
                </li>
                <li >
                    <input type="checkbox" value="o100" />
                    <label for="o100">100m2 - 150m2</label>
                </li>
                <li >
                    <input type="checkbox" value="o150" />
                    <label for="o150">150m2 - 200m2</label>
                </li>
                <li >
                    <input type="checkbox" value="o200" />
                    <label for="o200">200m2 +</label>
                </li>
            </ul>

            <b>Type</b>
            <ul class="apt-type">
                <li >
                    <input type="checkbox" value="tPe" />
                    <label for="tPe">Penthouse</label>
                </li>
                <li >
                    <input type="checkbox" value="tV" />
                    <label for="tV">Villa</label>
                </li>
                <li >
                    <input type="checkbox" value="tPa" />
                    <label for="tPa">Panorama</label>
                </li>
                <li >
                    <input type="checkbox" value="tU" />
                    <label for="tU">Urban</label>
                </li>
                <li >
                    <input type="checkbox" value="tZ" />
                    <label for="tZ">Zuid</label>
                </li>
            </ul>

            <b>Prijs</b>
            <ul class="apt-price">
                <li >
                    <input type="checkbox" value="p1" />
                    <label for="p1">1.000.000 - 2.000.000</label>
                </li>
                <li >
                    <input type="checkbox" value="p2" />
                    <label for="p2">2.000.000 - 3.000.000</label>
                </li>
                <li >
                    <input type="checkbox" value="p3" />
                    <label for="p3">3.000.000 - 4.000.000</label>
                </li>
                <li >
                    <input type="checkbox" value="p4" />
                    <label for="p4">4.000.000 - 5.000.000</label>
                </li>
            </ul>

            <b>Balkon</b>
            <ul class="apt-balkon">
                <li >
                    <input type="checkbox" value="b50" />
                    <label for="b50">50m2 - 100m2</label>
                </li>
                <li >
                    <input type="checkbox" value="b100" />
                    <label for="b100">100m2 - 150m2</label>
                </li>
                <li >
                    <input type="checkbox" value="b150" />
                    <label for="b150">150m2 - 200m2</label>
                </li>
                <li >
                    <input type="checkbox" value="b200" />
                    <label for="b200">200m2 +</label>
                </li>
            </ul>
        </div>

        <div id="aptresults">
            <div class="o50 tU p1 b50">50m2 - Urban - 1mil - 50m2 balkon</div>
            <div class="o100 tZ p2 b100">100m2 - Zuid - 2mil - 100m2 balkon</div>
            <div class="o150 tV p3 b150">150m2 - Villa - 3mil - 150m2 balkon</div>
            <div class="o200 tPa p4 b200">200m2 - Panorama - 4mil - 200m2 balkon</div>
            <div class="o50 tPe p1 b50">50m2 - Penthouse - 1mil - 50m2 balkon</div>
            <div class="o100 tU p2 b100">100m2 - Urban - 2mil - 100m2 balkon</div>
            <div class="o150 tV p3 b150">150m2 - Villa - 3mil - 150m2 balkon</div>
            <div class="o200 tZ p4 b200">200m2 - Zuid - 4mil - 200m2 balkon</div>
            <div class="o50 tPe p3 b50">50m2 - Penthouse - 3mil - 50m2 balkon</div>
            <div class="o100 tU p2 b100">100m2 - Urban - 2mil - 100m2 balkon</div>
            <div class="o50 tU p1 b50">50m2 - Urban - 1mil - 50m2 balkon</div>
            <div class="o100 tZ p2 b100">100m2 - Zuid - 2mil - 100m2 balkon</div>
            <div class="o150 tV p3 b150">150m2 - Villa - 3mil - 150m2 balkon</div>
            <div class="o200 tPa p4 b200">200m2 - Panorama - 4mil - 200m2 balkon</div>
            <div class="o50 tPe p1 b50">50m2 - Penthouse - 1mil - 50m2 balkon</div>
            <div class="o100 tU p2 b100">100m2 - Urban - 2mil - 100m2 balkon</div>
            <div class="o150 tV p3 b150">150m2 - Villa - 3mil - 150m2 balkon</div>
            <div class="o200 tZ p4 b200">200m2 - Zuid - 4mil - 200m2 balkon</div>
            <div class="o50 tZ p3 b150">50m2 - Zuid - 3mil - 150m2 balkon</div>
            <div class="o100 tU p2 b100">100m2 - Urban - 2mil - 100m2 balkon</div>
        </div>
    </div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">
 $(document).ready(function(){
     $('#aptresults div').show();

     $('input[type="checkbox"]').click(function(){
         select()
     })
 });

function select()
{
    $('#aptresults div').hide();

    var $div=$('#aptresults div');
    var check=false;    
    $('input[type="checkbox"]:checked').each(function(){
            var css=$(this).val();                    
            $div=$div.filter('.'+css);

        check=true;
    })

    if(check==true || check==false) $div.show();
}
</script>
</body>
</html>

Basically I have a list of homes, with the attributes of each home as various classes. For instance, a home will be between 50-100m2, be of type X, cost between 1 to 2 million, and have a balcony between 50-100m2.
There are 4 attributes, each with their own values, for instance there are 5 different types of home.

In the end, the user must be able to make one or more selection(s) of the various attributes and corresponding values. When the user does so, the list of available homes should be filtered. So say a user is looking for a home between 50-100m2, and 100-150m2, both boxes should be checked and the corresponding results should be displayed.

So far, thanks to some helpful answers in other posts, I've gotten it to filter the list for 1 of the attributes at a time.

If you look at the fiddle, you'll see that if you check the box for 50-100m2, it filters correctly and only shows homes that match the filter. If you then check the box for 'Urban', the results are filtered further and only 2 results are shown. Unchecking all boxes returns the original list, as intended.

Now if I select 50-100m2 and 100-150m2, the results are empty. I would expect to get 12 results back (6 for the former, and 6 for the latter selection). Within those results a user should again be able to check/select other attributes as well, to drill down even further in the results list.

Question is, how can I get this to work as intended? Is what I'm doing even on the right track, and if so, what am I missing here?

Appreciate any answers you might have!



Solution 1:[1]

Instead of overwriting $div within the .each-loop, collect the css classes you want to filter by and filter all items in a single filter action, like so:

$('input[type="checkbox"]:checked').each(function(){
        var css=$(this).val();
        filter.push('.'+css);
})

$div.filter(filter.join(',')).show();

complete fiddle at https://jsfiddle.net/9zxrby22/1/

Notice how this works as an OR-filter, even accross different groups (oppervlakte, type, prijs etc). If any class matches, the item is displayed, which is probably not what you want.

If you want to have an AND-filter accross groups, loop over the grouped checkboxes and overwrite the $div variable like so: https://jsfiddle.net/9zxrby22/2/

$('ul').each(function()
{
    filter = [];
    check = false;

    $(this).find('input[type="checkbox"]:checked').each(function()
    {
        var css=$(this).val();          
        filter.push('.'+css);
        check = true;
    });

    if (check)
    {
        $div = $div.filter(filter.join(','));
    }
})

Solution 2:[2]

check this out

$(document).ready(function(){
     $('#aptresults div').show();

     $('input[type="checkbox"]').click(function(){
         select()
     })
 });

function select()
{
    $('#aptresults div').hide();

    var $div=$('#aptresults div');
    var check=false;
    var css= [];    
    $('input[type="checkbox"]:checked').each(function(){       
            css.push("."+$(this).val());            
    })
    if(css.length>=1){
        $div=$div.filter(css.toString());              
        check=true;
    }
    if(check==true || check==false) $div.show();
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Ananth Cool