views:

324

answers:

2

Hi,

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]') ?

<script type="text/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();    
        }
    });
</script>

This is what the html looks like:

<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>
+1  A: 

You can build a list of items to show by using add():

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

    var groupsToShow = ['firstgroup','thirdgroup'];
    var namesToShow = ['Fred','Pete'];
    var applicationsToShow = ['light'];

    var $itemsToShow = $();

    for(var i=0;i<groupsToShow;i++) {
        $itemsToShow = $itemsToShow.add('div[group='+groupsToShow[i]+']');
    }

    for(var i=0;i<namesToShow;i++) {
        $itemsToShow = $itemsToShow.add('div[name='+namesToShow[i]+']');    
    }

    for(var i=0;i<applicationsToShow;i++) {
        $itemsToShow = $itemsToShow.add(('div[application='+applicationsToShow[i]+']');    
    }

    $itemsToShow.show();
});
Philippe Leybaert
But this would mean that the first div (with group=firstgroup name=rob application=special) would be contained in the $(itemsToShow) array (based on the first groupsToShow array), but it should eventually be hidden because it isn't contained in namesToShow and applicationsToShow... In other words, the filters aren't affecting each other.
Ropstah
I had the impression that you wanted to OR them.
Philippe Leybaert
True, however that was for the values, not the attributes... Thanks for the effort though
Ropstah
+1  A: 

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();
J-P
I think you've got my needs. I'm gonna try, let you know in a bit.
Ropstah
Works like a charm! Many, many thanks!
Ropstah