Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I filter a list having multiple values using jQuery and CSS?

Having tested various solutions found here and on the rest of the web, I can't figure out the logic to do this the "simple" way (or make it work at all).

I have the following list:

<ul class="store-list">
    <li data-categories="Bags Shoes Accessories Belts">
        <h3 itemprop="name">Enzo Poli</h3>
    </li>
    <li data-categories="Womenswear Shoes">
        <h3 itemprop="name">Ilse Jacobsen</h3>
    </li>
    <li data-categories="Menswear Womenswear Shoes Ties">
        <h3 itemprop="name">Kiman (Shoes Ties)</h3>
    </li>
    <li data-categories="Menswear Womenswear Shoes Knitwear">
        <h3 itemprop="name">Riccovero</h3>
    </li>
</ul>

<button class="a">Ties</button>
<button class="b">Ties & Shoes</button>
<button class="c">Menswear</button>

I've tried using Attribute Not Equal Selector, but that definitely does not work.

var stores = $('.store-list');

$('button.b').on('click', function(){
  stores.find('li[data-categories!="Ties"][data-categories!="Shoes"]').fadeOut();  
});

Another problem is when I select a different categories, the hidden elements are not shown.

I know I can use $.each() and go through each element and use a lot of code to see if it contains the category and check if it's visible or not. But I was just hoping there would be a better and simpler alternative.

So the Q is; How can I show / hide list items based on what filters I select?
See my fiddle here.

like image 902
Steven Avatar asked Jun 03 '15 14:06

Steven


3 Answers

Try this:

var stores = $('.store-list');

$('button.a').on('click', function() {
  stores.find('li').not('[data-categories~="Ties"]').fadeOut();
  stores.find('li[data-categories~="Ties"]').fadeIn();
});

$('button.b').on('click', function() {
  stores.find('li').not('[data-categories~="Ties"], [data-categories~="Shoes"]').fadeOut();
  stores.find('li[data-categories~="Ties"], [data-categories~="Shoes"]').fadeIn();
});

$('button.c').on('click', function() {
  stores.find('li').not('[data-categories~="Menswear"]').fadeOut();
  stores.find('li[data-categories~="Menswear"]').fadeIn();
});
body {
  font-size: 0.7em;
}
ul,
li {
  list-style: none;
}
a {
  text-decoration: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<ul class="store-list">
  <li data-categories="Bags Shoes Accessories Belts">
    <h3 itemprop="name">Enzo Poli</h3>
  </li>
  <li data-categories="Womenswear">
    <h3 itemprop="name">Ilse Jacobsen</h3>
  </li>
  <li data-categories="Menswear Womenswear Shoes Ties">
    <h3 itemprop="name">Kiman (Shoes Ties)</h3>
  </li>
  <li data-categories="Menswear Womenswear Shoes Knitwear">
    <h3 itemprop="name">Riccovero</h3>
  </li>
</ul>

<button class="a">Ties</button>
<button class="b">Ties & Shoes</button>
<button class="c">Menswear</button>

As you can see I use data~='item' instead of != that way it checks if it contains that word on the data-attribute.

Also, I force the fade in of those that have the category so that all the management is done. Surely there is a better way to do this, but this is the default logic.

like image 61
Joel Almeida Avatar answered Oct 10 '22 19:10

Joel Almeida


I think the misconception to blame here is that data-* attributes work like classes in separating multiple values by spaces. Not so, here you are just setting the arbtirary data-categories attribute to a single string containing spaces, so trying to match on any given single category is probably not going to work. Offhand, you could loop through all the elements and pattern-match their data-categories attribute against your target, like:

$('button.a').on('click', function(){
    stores.find('li').each(function() {
        if($(this).attr("data-categories").split(" ").indexOf('Ties') == -1) {
           $(this).fadeOut();
        }
    });
});

A better approach might be to in fact use classes instead of a data attribute, then you can easily make selections based on not having a class.

like image 43
swornabsent Avatar answered Oct 10 '22 19:10

swornabsent


var stores = $('ul.store-list > li');

$('button.a').on('click', function(){
    stores.fadeIn(':hidden').not('li[data-categories~="Ties"]', stores).fadeOut();  
});

$('button.b').on('click', function(){
   stores.fadeIn(':hidden').not('li[data-categories~="Shoes"], li[data-categories~="Ties"]', stores).fadeOut();  
});

$('button.c').on('click', function(){
   stores.fadeIn(':hidden').not('li[data-categories~="Menswear"]', stores).fadeOut();  
});
body {
    font-size: 0.7em;
}

ul, li {
    list-style: none;
}
a { text-decoration: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="store-list">
    <li data-categories="Bags Shoes Accessories Belts">
        <h3 itemprop="name">Enzo Poli</h3>
    </li>
    <li data-categories="Womenswear ">
        <h3 itemprop="name">Ilse Jacobsen</h3>
    </li>
    <li data-categories="Menswear Womenswear Shoes Ties">
        <h3 itemprop="name">Kiman (Shoes Ties)</h3>
    </li>
    <li data-categories="Menswear Womenswear Shoes Knitwear">
        <h3 itemprop="name">Riccovero</h3>
    </li>
</ul>

<button class="a">Ties</button>
<button class="b">Ties & Shoes</button>
<button class="c">Menswear</button>
like image 1
DiceYaPrice Avatar answered Oct 10 '22 17:10

DiceYaPrice