Javascript – How to show/hide elements based on multiple-attributes and multiple-attribute-values

filterhtmljavascriptjquery

I would like to view/hide divs on a page, based on attribute filters. I've made several attributes which can have multiple values. Users can choose which ones they want to see displayed.

I can't get the right algorythm (or I don't know which Javascript/jQuery function to use). The following obviously doesn't work. I'm first showing ALL items, and then loop through the filters, hiding the ones that don't match the attributes (read: the current attribute in the loop). This means items get hidden even though they might match an attribute later on…

How can I make this filtermechanism work and don't exclude/hide items that needn't be hidden based on selected attributes later in the loop? Maybe there is some OR-operator I can use with attribute selecting ('div[group=firstgroup|thirdgroup]') ?

Javascript:

    $(document).ready(function() {
        var items = $('#items').find('div');
        $(items).show();

        var groupsToShow = Array('firstgroup','thirdgroup');
        var namesToShow = Array('Fred','Pete');
        var applicationsToShow = Array('light');

        for(var i=0;i<groupsToShow;i++) {
            $(items).find('div[group!='+groupsToShow[i]+']').hide();    
        }

        for(var i=0;i<namesToShow;i++) {
            $(items).find('div[name!='+namesToShow[i]+']').hide();    
        }

        for(var i=0;i<applicationsToShow;i++) {
            $(items).find('div[application!='+applicationsToShow[i]+']').hide();    
        }
    });

HTML Code:

<div id="items">
    <div group="firstgroup" name="Rob" application="special"></div>
    <div group="firstgroup" name="Fred" application="light"></div>
    <div group="secondgroup" name="Pete" application="special"></div>
    <div group="thirdgroup" name="Pete" application="special"></div>
    <div group="thirdgroup" name="Pete" application="light"></div>
    <div group="secondgroup" name="Pete" application="normal"></div>
    <div group="thirdgroup" name="Pete" application="special"></div>
</div>

Best Solution

As I understand it, you only want elements to be shown if they satisfy what's contained in all three arrays. So in the above situation the second and fifth DIVs would be the only ones showing... Is that correct?

If my assumptions are correct then this should work:

var show = {
    'group': ['firstgroup','thirdgroup'],
    'name': ['Fred','Pete'],
    'application': ['light']
};

$('#items div')
    .hide()
    .filter(function(){
        // Only returns true for elements
        // that satisfy all three arrays
        for (var i in show) {
            var attr = $(this).attr(i),
                match = ('|' + show[i].join('|') + '|').indexOf(attr) > -1;
            if (!match) {
                return false;
            }
        }
        // If we reach this point then we can assert
        // that the element contains all required attributes
        return true;
    })
    .show();