0

How do I implement multiple filters using checkboxes preferably using jQuery?

I have multiple div elements with their own data attributes which represent the difficulties of levels the user has completed.

I want to create a filter using checkboxes so that when they check a box for a specific difficulty which are completed, that difficulty is filtered out (hidden). If the user wants to filter multiple difficulties, then those difficulties are filtered out as well. If the user unchecks the box, then obviously it reappears.

Here is the div elements containing the data attributes. The data attributes which are set to true are the ones which are completed. E.g. (data-normal=true means normal difficulty is completed)

<div class="map-col-container col-xs-12 col-sm-6 col-md-4" data-mapname="Level One" data-completed="2" data-easy="true" data-normal="false" data-hard="true" data-expert="false">
        <div class="map-col">
        <!--Content Here-->
        </div>
    </div>
<div class="map-col-container col-xs-12 col-sm-6 col-md-4" data-mapname="Level Two" data-completed="4" data-easy="true" data-normal="true" data-hard="true" data-expert="true">
        <div class="map-col">
        <!--Content Here-->
        </div>
    </div>
<div class="map-col-container col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="true" data-normal="false" data-hard="false" data-expert="false">
        <div class="map-col">
        <!--Content Here-->
        </div>
    </div>

In this example, if I checked expert, then Level Two should become hidden. If I also checked hard, then both Level One and Level Two should be hidden.

Here are my checkboxes

      <div class="checkbox">
        <label><input type="checkbox" id="hideEasyChkBox">Hide Easy</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" id="hideNormalChkBox">Hide Normal</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" id="hideHardChkBox">Hide Hard</label>
      </div>
      <div class="checkbox">
        <label><input type="checkbox" id="hideExpertChkBox">Expert</label>
      </div>

I did attempt this using a bool for each difficulty however if a box became unchecked despite other boxes being checked, it would unhide all the levels ignoring the fact other boxes are still checked.

If anything is unclear, please ask. Thanks

Edit: Here is the method I used however this does not work as when I uncheck one of the checkboxes, the div's reset and display all the levels ignoring the fact that the other boxes are still checked.

var hideCompleted = false;
var hideEasy = false;
var hideNormal = false;
var hideHard = false;
var hideExpert = false;

function mapCompletionFilter(filterBy){
  var $wrapper = $('.map-container');

  if(filterBy == "hideCompleted" && !hideCompleted){
    //$wrapper.find(".map-col-container[data-completed*=4]").hide();
    $wrapper.find(".map-col-container").filter('[data-completed="4"]').hide();
    hideCompleted = true;
  }
  else if(filterBy == "hideCompleted" && hideCompleted){
    $wrapper.find(".map-col-container[data-completed*=4]").show();
    hideCompleted = false;
  }

  if(filterBy == "hideEasy" && !hideEasy){
    //$wrapper.find(".map-col-container[data-completed*=4]").hide();
    $wrapper.find(".map-col-container").filter('[data-easy="true"]').hide();
    hideEasy = true;
  }
  else if(filterBy == "hideEasy" && hideEasy){
    $wrapper.find(".map-col-container").filter('[data-easy="true"]').show();
    hideEasy = false;
  }

  if(filterBy == "hideNormal" && !hideNormal){
    //$wrapper.find(".map-col-container[data-completed*=4]").hide();
    $wrapper.find(".map-col-container").filter('[data-normal*="true"]').hide();
    hideNormal = true;
  }
  else if(filterBy == "hideNormal" && hideNormal){
    $wrapper.find(".map-col-container").filter('[data-normal*="true"]').show();
    hideNormal = false;
  }

  if(filterBy == "hideHard" && !hideHard){
    //$wrapper.find(".map-col-container[data-completed*=4]").hide();
    $wrapper.find(".map-col-container").filter('[data-hard*="true"]').hide();
    hideHard = true;
  }
  else if(filterBy == "hideHard" && hideHard){
    $wrapper.find(".map-col-container").filter('[data-hard*="true"]').show();
    hideHard = false;
  }

  if(filterBy == "hideExpert" && !hideExpert){
    //$wrapper.find(".map-col-container[data-completed*=4]").hide();
    $wrapper.find(".map-col-container").filter('[data-expert*="true"]').hide();
    hideExpert = true;
  }
  else if(filterBy == "hideExpert" && hideExpert){
    $wrapper.find(".map-col-container").filter('[data-expert*="true"]').show();
    hideExpert = false;
  }
}

Buttons

$("#hideAllCompletedChkBox").click(function(){
  mapCompletionFilter("hideCompleted");
});
$("#hideEasyChkBox").click(function(){
  mapCompletionFilter("hideEasy");
});
$("#hideNormalChkBox").click(function(){
  mapCompletionFilter("hideNormal");
});
$("#hideHardChkBox").click(function(){
  mapCompletionFilter("hideHard");
});
$("#hideExpertChkBox").click(function(){
  mapCompletionFilter("hideExpert");
});

The main issue I am having is when I use multiple checkboxes for hiding each individual difficulty whereby if one of these checkboxes are unticked, all div's become unhidden.

Gazz
  • 1,017
  • 3
  • 17
  • 31
  • Please post you javascript code – Vasilij Altunin Mar 06 '17 at 21:10
  • Please read [ask]. Key phrases: "Search, and research" and "Explain ... any difficulties that have prevented you from solving it yourself". – Heretic Monkey Mar 06 '17 at 21:20
  • [Selecting elements by data attribute](http://stackoverflow.com/questions/2487747/selecting-element-by-data-attribute). [Hide a selected element](http://api.jquery.com/hide/). – John Wu Mar 06 '17 at 21:32
  • @JohnWu thanks for the reply. I know how to select elements by data attribute and hide elements. I have edited my post to show an example of where this is in use in my project currently. What I am trying to achieve is having multiple filters working at once. – Gazz Mar 06 '17 at 22:03
  • Can you post the code that you've tried that doesn't work? – John Wu Mar 06 '17 at 22:35
  • @JohnWu Updated post to show what I attempted and explained why it doesn't work as it should. Thanks. – Gazz Mar 06 '17 at 23:32

1 Answers1

1

Here, i prepare fiddle t show how it works - https://jsfiddle.net/skyr9999/nynbupwh/

I update you html a bit to make sure and test all works fine.

Here's is html:

<div id="elems">
    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level One" data-completed="2" data-easy="true" data-normal="false" data-hard="true" data-expert="false">
        <div class="map-col">
            Easy, hard
        </div>
    </div>
    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Two" data-completed="3" data-easy="true" data-normal="true" data-hard="true" data-expert="true">
        <div class="map-col">
            Easy, Normal, Expert
        </div>
    </div>
    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="true" data-normal="false" data-hard="false" data-expert="false">
        <div class="map-col">
            Easy
        </div>
    </div>

    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="true" data-hard="false" data-expert="false">
        <div class="map-col">
            Normal
        </div>
    </div>

    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="false" data-hard="true" data-expert="false">
        <div class="map-col">
            Hard
        </div>
    </div>

    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="false" data-hard="false" data-expert="true">
        <div class="map-col">
            Expert
        </div>
    </div>

    <div class="datadiv col-xs-12 col-sm-6 col-md-4" data-mapname="Level Three" data-completed="1" data-easy="false" data-normal="false" data-hard="false" data-expert="false">
        <div class="map-col">
            None
        </div>
    </div>

    <div class="checkbox">
        <label><input type="checkbox" id="hideEasyChkBox">Hide Easy</label>
    </div>
    <div class="checkbox">
        <label><input type="checkbox" id="hideNormalChkBox">Hide Normal</label>
    </div>
    <div class="checkbox">
        <label><input type="checkbox" id="hideHardChkBox">Hide Hard</label>
    </div>
</div>


<div class="checkbox">
    <label><input type="checkbox" id="hideExpertChkBox">Expert</label>
</div>

And js:

jQuery(document).ready(function ($) {

    updateVisible = function () {
        $("#elems>div.datadiv").each(function (index, value)
        {
            $(value).show();

            if ($(value).attr("data-expert") === "true")
            {
                if ($("#hideExpertChkBox").is(':checked'))
                {
                    $(value).hide();
                }
            }

            if ($(value).attr("data-hard") === "true")
            {
                if ($("#hideHardChkBox").is(':checked'))
                {
                    $(value).hide();
                }
            }


            if ($(value).attr("data-normal") === "true")
            {
                if ($("#hideNormalChkBox").is(':checked'))
                {
                    $(value).hide();
                }
            }


            if ($(value).attr("data-easy") === "true")
            {
                if ($("#hideEasyChkBox").is(':checked'))
                {
                    $(value).hide();
                }
            }
        });

    };

    $(document).on("change", "#hideEasyChkBox", function () {
        updateVisible();
    });

    $(document).on("change", "#hideNormalChkBox", function () {
        updateVisible();
    });

    $(document).on("change", "#hideHardChkBox", function () {
        updateVisible();
    });

    $(document).on("change", "#hideExpertChkBox", function () {
        updateVisible();
    });

});

So how it works - on checkbox change it call updateVisible() function. Than it get first div and show all it. After that it test if checkbox of filter checked and if div have atrr and if so, just hide it, if none attr set to true it just ingore such div. And then all repeated for all other divs.

Vasilij Altunin
  • 754
  • 1
  • 5
  • 18