Filter list with multiple data-types

Hi all

I have a function that filters a list by one item. Click single - show single items, click groups - show group items. This works good.

The problem I have is that some items can be categorized as group and single, so if an item has single and groups - the filter does not work.

How can I change/modify the code so instead of filtering by a single data-type, if the data-type has multiple values, also filter these items as well?

See this in action codepen

The Single and Groups never get filtered?

HTML

<div class="filter-type">
    <a class="all active" data-filter="all" href="#">All</a> | 
    <a class="single" data-filter="single" href="#">Single</a> | 
    <a class="groups" data-filter="groups" href="#">Groups</a>
</div>
<ul id="list">
  <li data-type="single groups">Single and Groups</li>
  <li data-type="single">Single</li>
  <li data-type="single">Single</li>
  <li data-type="single">Single</li>
  <li data-type="groups">Groups</li>
  <li data-type="groups">Groups</li>
  <li data-type="groups">Groups</li>
  <li data-type="single groups">Single and Groups</li>
</ul>

JS

$(document).on('click', '.filter-type [data-filter]', function(e){
    e.preventDefault();

    var $filters = $('.filter-type [data-filter]'),
    $boxes = $('#list [data-type]');
    var $this = $(this);

    $filters.removeClass('active');
    $this.addClass('active');

    var $filterType = $this.attr('data-filter');

    if ($filterType == 'all') {
      $boxes.removeClass('is-animated')
        .fadeOut().promise().done(function() {
        $boxes.addClass('is-animated').fadeIn();
      });
    } else {
      $boxes.removeClass('is-animated')
        .fadeOut().promise().done(function() {
        $boxes.filter('[data-type = "' + $filterType + '"]')
          .addClass('is-animated').fadeIn();
      });
    }
  });

Thanks, Barry

This is the line that’s causing trouble:

       $boxes.filter('[data-type = "' + $filterType + '"]')

You can use a function for the filter instead.

       $boxes.filter(function () {
            return this.attr("data-type").substr($filterType) > -1;
        });

That way, you’re checking if the filterType occurs anywhere at all in the data-type attribute.

Edit:

Even better, use the * or ~= selector as shown below.

1 Like

Alternatively, just use the CSS selectors correctly :wink:

$('li[data-type*="'+$filterType+'"]')

(The * is the important part. It does CSS filtering on “attribute value includes”)

[Side note: You may actually want to use ~=, which is literally “Attribute is within a Space Separated List”]

2 Likes

I missed that one :smile:

Thanks @Paul_Wilkins, @m_hutley - both great solutions. I’ve gone with the simple fix using:
$boxes.filter('[data-type~="'+$filterType+'"]')

Updated Codepen

Cheers, working great :sunglasses:

Barry

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.