7

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.

3
  • Is expected result to display only one li element at click of button ? Commented Jun 3, 2015 at 14:20
  • No. I have about 13 categories. If I select 3 categories, all items having those categories will be shown. Everything else should be hidden. Commented Jun 3, 2015 at 14:21
  • Try utilizing .filter() ; though could substitute adding data-* to button element for testing against button .innerHTML Commented Jun 3, 2015 at 14:59

4 Answers 4

6

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.

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

3 Comments

now we check if data-categories contains A or B using ~=. How would I go about if I want to have A and B?
@Steven remove the comma in [data-categories~="Ties"], [data-categories~="Shoes"] and use [data-categories~="Ties"][data-categories~="Shoes"] and it checks A and B while with the comma it checks A or B
It's what I'm using now but it selects any store that has either Menswear or Shoes. Not Menswear and Shoes.
5

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.

Comments

1

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>

2 Comments

Hello! Your answer may be more helpful to the question asker and the community at large if you provide some context as to how your answer will solve the issue in the question. stackoverflow.com/help/how-to-answer
Although having all in one line works, you can see how elements are shown before hidden again. This makes the list "jump" whereas Joel's solution makes this smooth.
0

At no point to do use .fadeIn() - so once they're gone, they're gone.

None of the data-catagories uses a single value, so check for = or != will never give an exact match, use ~= to match words:

https://api.jquery.com/attribute-contains-word-selector/

[Joel has provided answer with code, so stopping here]

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.