Question

I have a HTML table with check boxes for filtering, while I can get the filtering working for individual checkboxes, and soon as I try and use them together, then the results don't work as expected.

[]Male []Popular []Active
============================================================
= FirstName  = LastName  = Sex    =  Popular  = Active     =
= John       = Doe       = Male   =  No       = Yes        =
= Eve        = Jackson   = Female =  Yes      = No         =
= Adam       = Johnson   = Child  =  Yes      = Yes        =
============================================================

Above is what the table looks like

HTML code for the table

<input type="checkbox" id="male">Male<br>
<input type="checkbox" id="popular">Popular<br>
<input type="checkbox" id="active">Active<br>

<table>
<thead>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Sex</th>
    <th>Popular</th>
    <th>Active</th>
</thead>
<tbody>
<tr>
  <td>John</td>
  <td>Doe</td>
  <td>Male</td>
  <td>No</td>
  <td>Yes</td>
</tr>
<tr>
  <td>Eve</td>
  <td>Jackson</td>
  <td>Female</td>
  <td>Yes</td>
  <td>No</td>
</tr>
<tr>
  <td>Adam</td>
  <td>Johnson</td>
  <td>Child</td>
  <td>Yes</td>
  <td>Yes</td>
</tr>
</tbody>
</table> 

Javascript

//a check box has been checked
$(':checkbox').change(function() {
    //are there no check boxes selected?
    if ($('input:checkbox:checked').length > 0) {
        //hide all rows
        $('tbody tr').each(function() {
            $(this).hide();
        });
        //show only rows needed to be show
        if ($('#male').is(':checked')) {
            ShowRow('Male','2');
        }
        if ($('#popular').is(':checked')) {
            ShowRow('Yes','3');
        }
        if ($('#active').is(':checked')) {
            ShowRow('Yes','4');
        }
    } else {
        //there are no check boxes selected, show all rows
        $('tr').each(function() {
            $(this).show();
        });
    }
});

function ShowRow(text, column) {
    $('tr').each(function() {
        if ($(this).children('td:eq(' + column + ')').text().indexOf(text) != '-1') {
            $(this).show();
        }
    });
}

Individually the checkboxes work correctly,things go awry if I use multiple boxes at the same time, as an example, if I tick, Male, then only males will show, if I then check Popular, then everyone shows up.

Here is the JSFiddle URL; http://jsfiddle.net/3XhCa/5/

I would appreciate if someone could point me in the right direction, after about 3 days of searching, I'm running out of ideas.

My other idea was to build a really big if statement, but I don't think this is the correct way to go.

Was it helpful?

Solution 2

Try this,

$(':checkbox').change(function () {
    $('tr').show();
    if ($('input:checkbox:checked').length > 0) {
        if ($('#male').is(':checked')) {
            ShowRow('Male', '2');
        }
        if ($('#popular').is(':checked')) {
            ShowRow('Yes', '3');
        }
        if ($('#active').is(':checked')) {
            ShowRow('Yes', '4');
        }
    }
});

function ShowRow(text, column) {
    $('tr:visible:not(:first)').each(function () {
        if ($(this).children('td:eq(' + column + ')').text().indexOf(text) != '-1') {
            $(this).show();
        } else {
            $(this).hide();
        }
    });
}

OTHER TIPS

The issue was that the predicate you had logically constructed was a disjunction (a combination of "or"s). As such, when you checked "Male" and "Active" the script showed all rows that contained males OR active users, which were all of them in your example.

@Rajaprabhu Aravindasamy's answer is fine, but requires multiple passes over your table's rows. If you want, you could take a more functional approach and construct a predicate that will allow you to make a single pass over them:

http://jsfiddle.net/3XhCa/10/

function tautology() {
    return true;
}

function makePredicate(text, column) {
    return function(row) {
        return -1 !== $(row).children('td:eq(' + column + ')').text().indexOf(text);
    };
}

var isMale = makePredicate('Male', 2);
var isPopular = makePredicate('Yes', 3);
var isActive = makePredicate('Yes', 4);

function conjoin(f, g) {
    return function (row) {
        return f(row) && g(row);
    };
};

//a check box has been checked
$(':checkbox').change(function() {
    var isVisible = tautology;

    //are there no check boxes selected?
    if ($('input:checkbox:checked').length > 0) {
        //show only rows needed to be show
        if ($('#male').is(':checked')) {
            isVisible = conjoin(isVisible, isMale);
        }
        if ($('#popular').is(':checked')) {
            isVisible = conjoin(isVisible, isPopular);
        }
        if ($('#active').is(':checked')) {
            isVisible = conjoin(isVisible, isActive);
        }
        $('tbody > tr').each(function() {
            $(this).toggle(isVisible(this));
        });
    } else {
        //there are no check boxes selected, show all rows
        $('tr').show();
    }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top