Mike L Mike L - 1 month ago 13
jQuery Question

Using Checkbox "groups" to filter table data based on data-attributes/array

I have an existing site with a table of mattresses. I previously had a list of checkboxes that allowed a visitor to filter (show/hide) certain rows in the table based on sizes they would select via checkboxes. I passed in the sizes for each row into a data-attribute and then filtered based on matching the array of checkboxes to the array of sizes. (Currently there is only one size per row but the client indicated that they may need to add multiple sizes to any given mattress/row so we needed the ability to have a comma separated list).

Recently the client requested that I also add "brand" checkboxes to filter (show/hide) based on brand, I've done this and added the brands to the data-attribute. The problem I am having is when a user checks a combination of sizes and brands the jQuery filters on whatever was recently selected rather than looking at all checkboxes and the entire array in the data-attribute to make sure that it only shows the combination of filters.

Here's my current jQuery:

$('ul.filters input[type="checkbox"]').on('change', function() {
$('.dataTable tbody tr').hide();
var results = true;
var noneAreChecked = true;

var checkboxArray = $('.filters input[type="checkbox"]:checked').map( function () {
return $(this).attr('id');
}).get().join();

checkboxArray = checkboxArray.split(',');
//console.log('Checkbox Array: ' + checkboxArray);

$('ul.filters input[type="checkbox"]').each(function() {
if ( $(this).is(':checked') ) {

$('.dataTable tbody tr').each(function() {
var $this = $(this);
if ($this.data('context')) {

var contextArray = $this.data('context');
contextArray = contextArray.split(', ');
//console.log('Sizes Array: ' + filtersArray);

for (var i = 0; contextArray.length > i; i++) {
for (var j = 0; checkboxArray.length > j; j++) {
if (contextArray[i] === checkboxArray[j]) {
//console.log(contextArray[i] + ' matched!');
$(this).show();
}

}

}
}
});

noneAreChecked = false;
}
});

if (noneAreChecked) {
$('.dataTable tbody tr').show();
$('tr.no-results').remove();
}

var bgFlag = true;

$('.dataTable tbody tr:visible').each(function() {
$(this).removeClass('even odd');
if (bgFlag) {
$(this).addClass('odd');
} else {
$(this).addClass('even');
}
bgFlag = !bgFlag;
});
});


View the JS Bin:
http://jsbin.com/xusequ/4/

Thank you for any help you can provide here!

Answer

It looks like you'd be better off doing things a little differently.

I did something like this:

$('.dataTable tbody tr').each(function() {
        var $this = $(this);
        var context = $this.data('context');
        $this.hide();
        if (context) {
            for (var i = 0; brandArray.length > i; i++) {
                if ( context.indexOf(brandArray[i]) === -1) {
                    return;
                }
            }
            for (var i = 0; sizeArray.length > i; i++) {
                if ( context.indexOf(sizeArray[i]) === -1) {
                    return;
                }
            }
            $this.show();
        }
    });