Reputation: 25
I have a HTML table in which I want to hide/show rows based on multiple checkboxes.
When a checkbox is checked, (based on a text criterion) some rows are hiding, if it's unchecked, all rows are shown. If 2 or more checkboxes are checked, all rows are hiden, except those which met the criteria from all selected checkboxes. But if I uncheck any of the checboxes, all rows are shown.
My question is, when I uncheck one of the checkboxes, how can I show ONLY the rows that met the criteria from all current selected checkboxes?
For better understanding, I need to check which rows are already hidden by the other checkboxes and not show them when a checkbox is unchecked.
Example of working case: checkbox1 and checkbox2 are selected: only row1 is shown, if I uncheck checkbox2, only row1 and row3 must be shown
HTML:
<label><input type="checkbox" id="checkbox1">Teacher</label>
<label><input type="checkbox" id="checkbox2">Tennis</label>
<label><input type="checkbox" id="checkbox3">Married</label>
<table id="table" border="1">
<thead>
<th>First Name</th>
<th>Last Name</th>
<th>Profession</th>
<th>Hobby</th>
<th>Married</th>
</thead>
<tbody>
<tr id="row1">
<td>John</td>
<td>Doe</td>
<td>Teacher</td>
<td>Tennis</td>
<td>Yes</td>
</tr>
<tr id="row2">
<td>Eve</td>
<td>Jackson</td>
<td>Doctor</td>
<td>Darts</td>
<td>No</td>
</tr>
<tr id="row3">
<td>Adam</td>
<td>Johnson</td>
<td>Teacher</td>
<td>Skydiving</td>
<td>Yes</td>
</tr>
<tr id="row4">
<td>Nina</td>
<td>Pursuit</td>
<td>Lawyer</td>
<td>Tennis</td>
<td>Yes</td>
</tr>
</tbody>
</table>
jQuery:
$(document).ready(function () {
$('#checkbox1').change(function () {
for (var i = 0; i < 5; i++) {
if ((this.checked) && $("#table #row"+i+" td:nth-child(3):not(:contains('Teacher'))").length){
$('#row'+i).fadeOut('slow');
}
if (!this.checked) $('#row'+i).fadeIn('slow');
}
});
$('#checkbox2').change(function () {
for (var i = 0; i < 5; i++) {
if ((this.checked) && $("#table #row"+i+" td:nth-child(4):not(:contains('Tennis'))").length){
$('#row'+i).fadeOut('slow');
}
if (!this.checked) $('#row'+i).fadeIn('slow');
}
});
$('#checkbox3').change(function () {
for (var i = 0; i < 5; i++) {
if ((this.checked) && $("#table #row"+i+" td:nth-child(5):not(:contains('Yes'))").length){
$('#row'+i).fadeOut('slow');
}
if (!this.checked) $('#row'+i).fadeIn('slow');
}
});
});
Upvotes: 0
Views: 534
Reputation: 410
To achieve your desired behavior you need to store the actual status of each element when this gets hidden. This uses one event listener for all checkboxes.
The logic is pretty easy: Iterate over all rows and hide the current when the following criteria is met:
Each hiding involves an update to the state object and in the end all rows get shown that are not in this state object.
$(document).ready(function () {
$('input[type="checkbox"]').click(function() {
var checkbox_1 = $('#checkbox1')[0].checked
var checkbox_2 = $('#checkbox2')[0].checked
var checkbox_3 = $('#checkbox3')[0].checked
var state = {}
for (var i = 0; i < 5; i++) {
if (checkbox_1 && !state[i] && $("#table #row"+i+" td:nth-child(3):not(:contains('Teacher'))").length){
$('#row'+i).fadeOut('slow');
state[i] = "hidden"
}
if (checkbox_2 && !state[i] && $("#table #row"+i+" td:nth-child(4):not(:contains('Tennis'))").length){
$('#row'+i).fadeOut('slow');
state[i] = "hidden"
}
if (checkbox_3 && !state[i] && $("#table #row"+i+" td:nth-child(5):not(:contains('Yes'))").length){
$('#row'+i).fadeOut('slow');
state[i] = "hidden"
}
if (!state[i]) {
$('#row'+i).fadeIn('slow');
}
}
});
});
Upvotes: 0
Reputation: 176
$(document).ready(function() {
$('#checkbox1').change(function() {
for (var i = 0; i < 5; i++) {
if ((this.checked) && $("#table #row" + i + " td:nth-child(3):not(:contains('Teacher'))").length) {
// $('#row'+i).fadeOut('slow');
$('#table #row' + i).addClass('check1');
}
if (!this.checked) $('#table #row' + i).removeClass('check1');
}
});
$('#checkbox2').change(function() {
for (var i = 0; i < 5; i++) {
if ((this.checked) && $("#table #row" + i + " td:nth-child(4):not(:contains('Tennis'))").length) {
// $('#row'+i).fadeOut('slow');
$('#table #row' + i).addClass('check2');
}
if (!this.checked) $('#table #row' + i).removeClass('check2');
}
});
$('#checkbox3').change(function() {
for (var i = 0; i < 5; i++) {
if ((this.checked) && $("#table #row" + i + " td:nth-child(5):not(:contains('Yes'))").length) {
//$('#row'+i).fadeOut('slow');
$('#table #row' + i).addClass('check3');
}
if (!this.checked) $('#table #row' + i).removeClass('check3');
}
});
$('.checkbox').change(function() {
for (var i = 0; i < 5; i++) {
if ($("#table #row" + i).hasClass('check1') || $("#table #row" + i).hasClass('check2') || $("#table #row" + i).hasClass('check3')) {
$('#row' + i).fadeOut('slow');
// $('#table #row'+i).addClass('check3');
} else {
$('#row' + i).fadeIn('slow');
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
<input type="checkbox" class="checkbox" id="checkbox1">Teacher</label>
<label>
<input type="checkbox" class="checkbox" id="checkbox2">Tennis</label>
<label>
<input type="checkbox" class="checkbox" id="checkbox3">Married</label>
<table id="table" border="1">
<thead>
<th>First Name</th>
<th>Last Name</th>
<th>Profession</th>
<th>Hobby</th>
<th>Married</th>
</thead>
<tbody>
<tr id="row1">
<td>John</td>
<td>Doe</td>
<td>Teacher</td>
<td>Tennis</td>
<td>Yes</td>
</tr>
<tr id="row2">
<td>Eve</td>
<td>Jackson</td>
<td>Doctor</td>
<td>Darts</td>
<td>No</td>
</tr>
<tr id="row3">
<td>Adam</td>
<td>Johnson</td>
<td>Teacher</td>
<td>Skydiving</td>
<td>Yes</td>
</tr>
<tr id="row4">
<td>Nina</td>
<td>Pursuit</td>
<td>Lawyer</td>
<td>Tennis</td>
<td>Yes</td>
</tr>
</tbody>
</table>
You can look this solution.
Upvotes: 0
Reputation: 1688
You could create a function that checks all and shows/hide rows, and just call it on checkbox change
event here's an example:
function show_hide_rows() {
var checkbox1=($('#checkbox1').is(':checked') ? true : false),
checkbox2=($('#checkbox2').is(':checked') ? true : false),
checkbox3=($('#checkbox3').is(':checked') ? true : false);
var passed;
for (var i = 0; i < 5; i++) {
passed = false;
if (checkbox1 && $("#table #row"+i+" td:nth-child(3):not(:contains('Teacher'))").length) passed = true;
if (checkbox2 && $("#table #row"+i+" td:nth-child(4):not(:contains('Tennis'))").length) passed = true;
if (checkbox3 && $("#table #row"+i+" td:nth-child(5):not(:contains('Yes'))").length) passed = true;
if (passed) $('#row'+i).fadeOut('slow');
else $('#row'+i).fadeIn('slow');
}
}
$(function(){
$('input[type="checkbox"]').on('change', function(){ show_hide_rows(); });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label><input type="checkbox" id="checkbox1">Teacher</label>
<label><input type="checkbox" id="checkbox2">Tennis</label>
<label><input type="checkbox" id="checkbox3">Married</label>
<table id="table" border="1">
<thead>
<th>First Name</th>
<th>Last Name</th>
<th>Profession</th>
<th>Hobby</th>
<th>Married</th>
</thead>
<tbody>
<tr id="row1">
<td>John</td>
<td>Doe</td>
<td>Teacher</td>
<td>Tennis</td>
<td>Yes</td>
</tr>
<tr id="row2">
<td>Eve</td>
<td>Jackson</td>
<td>Doctor</td>
<td>Darts</td>
<td>No</td>
</tr>
<tr id="row3">
<td>Adam</td>
<td>Johnson</td>
<td>Teacher</td>
<td>Skydiving</td>
<td>Yes</td>
</tr>
<tr id="row4">
<td>Nina</td>
<td>Pursuit</td>
<td>Lawyer</td>
<td>Tennis</td>
<td>Yes</td>
</tr>
</tbody>
</table>
Upvotes: 0
Reputation: 1636
You don't need to track that. Just show all rows, and process the hide criteria to hide the matching rows.
Something like this:
When a checkbox is changed
Show all rows
Check all checkboxes, and hide those rows that match the criteria
Since this will be performer on a single frame, the browser won't flicker, resulting in a clean and fast change.
Upvotes: 0