2

I have three categories of controls, each with several options:

    <ul class="series-selector-items">
        <li id="filter-type-A">A</li>
        <li id="filter-type-B">B</li>
        <li id="filter-type-C">C</li>
    </ul>
    <ul class="series-selector-items">
        <li id="filter-type-E">E</li>
        <li id="filter-type-F">F</li>
        <li id="filter-type-G">G</li>
    </ul>
    <ul class="series-selector-items">
       <li id="filter-type-H">H</li>
       <li id="filter-type-I">I</li>
       <li id="filter-type-J">J</li>
       <li id="filter-type-K">K</li>
    </ul>

Then I have a list with items that have combinations of attributes from the above controls:

    <ul>
     <li class="A E H">Item AEH</li>
     <li class="A F I">Item AFI</li>
     <li class="A G J">Item AGJ</li>
     <li class="A G H">Item AGH</li>
     <li class="B E H">Item BEH</li>
     <li class="B F H">Item BFH</li>
     <li class="B F H">Item BFH</li>
     <li class="C E I">Item CEI</li>
     <li class="C G K">Item CEI</li>
etc etc...
    </ul>

I am trying to find a way to filter results based on combinations of selected control options. I need to be able to select any combination of control options, (ex. A E H) and show all the items that have the correct attributes (item AEH).

Multiple options should be selectable in each category (A B E K), and the categories should work together to show options that have the correct combination of elements. If multiple options are selected from the same category, their results should still show up. I have made the control list as li's but they could also be checkboxes.

What's the best way to do this with jQuery?

EDIT: Here is one approach I tried so far, adding selected options to an array:

var seriesSelected = [];    
$('ul.series-selector-items').click(function(){

            //Select the series clicked and give it the "selected" class
            $(this).toggleClass("selected");

            //Once selected, add the series to the seriesSelected array
            if ($(this).hasClass('selected')) {
               seriesSelected.push($(this).attr('id'));
            }
            //If de-selecting (by toggling off the "selected class"), then remove from the seriesSelected array
            else {
                seriesToRemove = $(this).attr('id');
                seriesSelected = $.grep(seriesSelected, function(value) {
                return seriesToRemove != value;
               });
            }
        });

Not sure where to go from there...

4
  • 2
    Have you attempted anything? Are you encountering a specific problem? Commented Aug 1, 2012 at 1:37
  • StackOverflow 101: Take a stab at it and post some code. Then we'll fix it for you. :) Commented Aug 1, 2012 at 1:44
  • Yes please show us what you've done so far! Commented Aug 1, 2012 at 1:44
  • I've tried a few different methods based on some similar problems but they aren't able to show multiple options from the same category stackoverflow.com/a/6527773 Commented Aug 1, 2012 at 1:49

4 Answers 4

0

Maybe something like:

$('li').not($("#sec li")).on('click', function() {
    if ($('.active').length < 3) {
        $(this).toggleClass('active');
        var letters=[];
        $('.active').each(function(i,e) {
            letters.push(e.id.replace('filter-type-',''));
        });
        if ($('.active').length == 3) {
            var elms = $('#sec li').filter(function() {
                if ($(this).is('.'+letters[0])&&$(this).is('.'+letters[1])&&$(this).is('.'+letters[2])) {
                    return this;
                }
            }).show();
            $('#sec li').not(elms).hide();
        }else{
            $('#sec li').hide();                               
        }
    }else{
        if ($(this).is('.active')) $(this).removeClass('active');
    }
});​

FIDDLE

Sign up to request clarification or add additional context in comments.

1 Comment

This solution also only displays items when there is a combination. I probably didn't explain what I am looking for so well but you should be able to see any options that meet the specified controls. So if you select only A, then you will get any items that have an A class. If you select A and B then you will get A and B items. Where it gets tricky for me is when you select A (category 1) then E (category 2) it should show everything that has both A and E, not just everything with an A and everything with an E.
0

Here is my solution: http://jsfiddle.net/NukGM/2/ Hope you enjoy!

Click on the letters, the selected ones (in red) accumulate the selected IDs in an array. After each selection, a separate method is called which highlights any results who's classes exist in the selected ID array.

5 Comments

I looked at your code but it only seems to highlight options when you make a combination. I wanted the following functionality too: If you only select one option then all items with that attribute are displayed.
Ah, I see, I've updated my answer. Let me know if that looks right. Of course, my example only shows how to target the elements, you will need to do the hiding/showing ;)
Ok I see what you did but what I'm trying to figure out is how to use the control options to qualify the results. So If you select control options from 2 different categories, they filter down the list to items which only include both attributes. The same should go for when you select options from all 3 categories. Also you should be able to select 2 or more options from the same category.
Ok, lol, this is getting hairy quick! So, to clarify, when you select 'A', the result should be anything with the 'A' class. If I then add 'B' to my selection, this should result in anything with BOTH the 'A' and 'B' class, correct? Finally, if I add 'C' to my selection, we should only get results that have the specific combo of 'A B C' or any orientation thereof, yes?
Almost... There are 3 categories. Each item has 1 attribute from each category. You will only get SPECIFIC combos by selecting only 1 control option from each category. For example if controls are: ABC DEF GHIJ, then you will create a specific combo by selecting ADG (like in the scenario you outlined). If you only select A and D you should get all items with both attributes A and D. If you select A B D, you should get all items with attributes both A and D, and both B and D. Does that make sense?
0

Update with even better filtering

function filterItems() {
    var classSelectors = $(".selected").map(function() {
        var cls = this.id.split('-');
        return '.' + cls.splice(2).join('-');
    }).toArray().join('');

    if (classSelectors) {
        $('#items > li').filter(classSelectors).show('slow');
        $('#items > li').not(classSelectors).hide('slow');
    }
    else {
        //if no filter, show all
        $('#items > li').show('slow');
    }
}​


Updated Demo

$(document).ready(function() {
    $(".series-selector-items > li").click(function() {
        $(this).toggleClass('selected');
        filterItems();
    });
});

function filterItems() {
    var classSelectors = $(".selected").map(function() {
        var cls = this.id.split('-');
        return '.'+cls.splice(2).join('-');
    }).toArray();

    //if no filter, show all
    if(!classSelectors.length){
        $('#items > li').show('slow');
    }

    $('#items > li').filter(classSelectors.join('')).show('slow');

    $('#items > li').not(function() {
        var self = this;
        var showThis = true;
        $.each(classSelectors, function(i,value) {
            if(!$(self).is(value)) {
                showThis = false;
            }
        });
        return showThis;
    }).hide('slow');
}
​

8 Comments

Actually, you should be able to select multiple items from each category (list).
@digitopo Sorry, didn't realize that. Updated.
Thanks... this looks close. I don't need generated items as there is a set list of items that I have that is specific to the application. The letters I used are actually just placeholders to make this problem more generic. The actual control options and item attributes are more like "filter-type-womens" and "filter-type-youth" Also the order in which the attributes (classes) appear should not matter (don't think that you included this, but just to clarify). I got rid of the generation function (minus .click) but now $('#series-selector-series > li').not(function() doesn't seem to work...
@digitopo Oh ok. I updated without the generated elements. It works fine without that (see jsfiddle.net/XPUrt/6). You might have been missing part of the html.
I think the part that is missing for me when I change over the attributes is this line: return '.'+$(this).text(); Since there are a couple of control options with apostrophes in the attribute ex. Men's, I'd prefer to use the id's of the element. I tried to replace the line with return $(this).attr("id"); but it doesn't work at that point.
|
0

Here i have done complete bins in a few steps with understandable script for above query. you can find demo link as below:

Demo: http://codebins.com/bin/4ldqp90

HTML:

<!-- Select Category Combinators -->
<ul class="series-selector-items">
  <li id="filter-type-A">
    A
  </li>
  <li id="filter-type-B">
    B
  </li>
  <li id="filter-type-C">
    C
  </li>
</ul>
<ul class="series-selector-items">
  <li id="filter-type-E">
    E
  </li>
  <li id="filter-type-F">
    F
  </li>
  <li id="filter-type-G">
    G
  </li>
</ul>
<ul class="series-selector-items">
  <li id="filter-type-H">
    H
  </li>
  <li id="filter-type-I">
    I
  </li>
  <li id="filter-type-J">
    J
  </li>
  <li id="filter-type-K">
    K
  </li>
</ul>
<!-- Search Item from Follwing List based on selected category combinator-->
<ul class="list">
  <li class="A B H">
    Item ABH
  </li>
  <li class="A E H">
    Item AEH
  </li>
  <li class="A F I">
    Item AFI
  </li>
  <li class="A G J">
    Item AGJ
  </li>
  <li class="A G H">
    Item AGH
  </li>
  <li class="B C I">
    Item BCI
  </li>
  <li class="B E H">
    Item BEH
  </li>
  <li class="B F H">
    Item BFH
  </li>
  <li class="C B K">
    Item CBK
  </li>
  <li class="C E I">
    Item CEI
  </li>
  <li class="C G K">
    Item CGK
  </li>
</ul>

CSS:

.series-selector-items{
  display:inline-block;
  list-style:none;
  border:1px solid #3355f9;
  margin:0px;
  padding:0px;
  vertical-align:top;
  background:#fba5a2;
}
.series-selector-items li{
  padding:5px;
}
.series-selector-items li.selected{
  background:#f855f9;
}
.list{
  display:inline-block;
  list-style:none;
  border:1px solid #3355f9;
  margin:0px;
  padding:0px;
  vertical-align:top;
  background:#abd5f9;

}
.list li.searched{
  background: #3344ad;
  color:#dfdbab;
}
.list li{
  padding:3px;
}

jQuery:

$(function() {

     $(".series-selector-items li").click(function() {

            //Set Default UnSearched List
            $(".list li").removeClass("searched");

            var seriesSelected = new Array();
            //Select the series clicked and give it the "selected" class
            $(this).toggleClass("selected");

            //Get All selected combinators 
            $("li.selected").each(function() {
                seriesSelected.push($.trim($(this).attr('id')).replace('filter-type-', ''));

            });


            //Combinator Exists Then...
            if (seriesSelected.length == 3) {

                //Generate Class Name Combination
                var ClassNames = "." + seriesSelected[0] + "." + seriesSelected[1] + "." + seriesSelected[2];

                //Search Item based on Combinator
                if ($(".list li" + ClassNames).length > 0) {
                    //if Found then add Searched Class on Item
                    $(".list li" + ClassNames).addClass("searched");
                }

            } else {
                $(".list li").removeClass("searched");
            }


    });

});

Demo: http://codebins.com/bin/4ldqp90

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.