简体   繁体   中英

Filtering multiple classes with checkboxes

I've created a Multiple Checkbox Filter where there are 2 filter options: Gender and State

What I want to achieve is:

Filter the elements that have AT LEAST one of the STATE categories, but as soon as the GENDER is checked, hide the elements that are not from that gender

So for example, I am filtering by standing AND walking (this shows all female and male standing and walking), but as soon as I check MALE, this has to hide all females, so it'll show all male standing and walking.

 function run() { $(".item").hide(); const checked = $(":checked"); var gender = $("[name='gender']:checked").val(); var state = $("[name='state']:checked").val(); if (checked.length === 0) { return $(".item").show(); } checked.each(function() { //$(".item." + this.id).show(); //Works, but it doesn't hide the non checked gender return $(this).hasClass(gender) || $(".item." + this.state); }).show(); }; 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> <div id="gender"> <input type="radio" id="male" name="gender" onclick="run()" /> Male <input type="radio" id="female" name="gender" onclick="run()" /> Female </div> <div id="state"> <input type="checkbox" id="walking" name="state" onclick="run()" /> Walking <input type="checkbox" id="standing" name="state" onclick="run()" /> Standing </div> <br/> <div class="item male walking" >male walking</div> <div class="item male standing walking">male standing and walking</div> <div class="item standing female walking">female standing and walking</div> <div class="item female walking">female walking</div> 

Logic has been updated to show male OR female using radio buttons instead of select. All inline click handlers has been removed and updated to use the change handler

 var genderSelector = ""; var stateSelector = ""; var filter = function() { var selector = stateSelector + genderSelector; if (selector) { $(".item").hide(); $(stateSelector + genderSelector).show(); //console.log(stateSelector + genderSelector); } else { $(".item").show(); } }; $("#gender input").change(function() { genderSelector = this.value == "male" ? ".male:not(.female)" : ".female:not(.male)"; filter(); }); $("#state input").change(function() { if ($(this).is(":checked")) { stateSelector = stateSelector + "." + this.id; } else { stateSelector = stateSelector.replace("." + this.id, ""); } filter(); }); // this runs on load so the initial view will be pdated genderSelector = $("#gender :checked").val() == "male" ? ".male:not(.female)" : ".female:not(.male)"; filter(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> <div id="gender"> <input type="radio" id="male" value="male" name="gender" checked /> Male <input type="radio" id="female" value="female" name="gender" /> Female </div> <div id="state"> <input type="checkbox" id="walking" name="state" /> Walking <input type="checkbox" id="standing" name="state" /> Standing </div> <br/> <div class="item male walking">male walking</div> <div class="item male standing walking">male standing and walking</div> <div class="item standing female walking">female standing and walking</div> <div class="item female walking">female walking</div> <div class="item male female standing">male+female standing</div> 

You can do it like this: gather the checked items, and for each of them query the DOM for their names and show them.

Note that this is fairly inefficient because you are querying the DOM multiple times for the same elements. You should ideally save the elements collections and just call show/hide them when needed.

Also, note that I added the labels to improve the UX of your input elements. Now you can click on the labels themselves to check the inputs.


Edit: If inputs are supposed to be mutually exclusive, a radio buttons is a better fit. I have changed the UI to use radio buttons and added a box to reset the button (do not filter for gender). I am not sure how the male+female is supposed to work. At the moment, it is not included in neither gender.

 function run() { $(".item").hide(); let opposingGender = ''; $(":checked").each(function() { let selector = '.' + this.value; if (this.name === 'gender') { opposingGender = ':not(.' + (this.value === 'male' ? 'female' : 'male') +')'; } selector += opposingGender; $(selector).show(); }); }; function unselect() { $('[name=gender]').prop('checked', false); run(); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script> <div id="gender"> <input type="radio" id="male" value="male" name="gender" onclick="run()" /> <label for="male">Male</label> <input type="radio" id="female" value="female" name="gender" onclick="run()" /> <label for="female">Female</label> <button onclick="unselect()">Unselect</button> </div> <div id="state"> <input type="checkbox" id="walking" value="walking" name="state" onclick="run()" /> <label for="walking">Walking</label> <input type="checkbox" id="standing" value="standing" name="state" onclick="run()" /> <label for="standing">Standing</label> </div> <br/> <div class="item male walking" >male walking</div> <div class="item male standing walking">male standing and walking</div> <div class="item standing female walking">female standing and walking</div> <div class="item female walking">female walking</div> <div class="item male female standing">male+female standing</div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM