jqueryfiltercustom-data-attribute

jQuery filtering divs based on multiple data attributes


I have multiple divs on a page, each with the following data attributes: data-one, data-two, data-three, data-four & data-five. The following code is creating a filterList array like so: ['one-value', 'two-value', 'three-value', 'four-value', 'five-value'] depending on which values are selected in the five dropdowns. Building of the filterList array is working.

However some of the divs have multiple data attribute values, i.e. data-one="one-value,one-value-2,one-value-3"

If the divs contain only one data attribute value, it seems to work fine, but it's not working when there are multiple values separated by a comma.

Any help would be hugely appreciated!

var filterList = [];

jQuery("#jsonFilters ul#one ul li a.active").each(function() {
  var dataOne = jQuery(this).attr("data-one");
  filterList.push(dataType);
});

jQuery("#jsonFilters ul#two ul li a.active").each(function() {
  var dataTwo = jQuery(this).attr("data-two");
  filterList.push(dataTwo);
});

jQuery("#jsonFilters ul#three ul li a.active").each(function() {
  var dataThree = jQuery(this).attr("data-three");
  filterList.push(dataThree);
});

jQuery("#jsonFilters ul#four ul li a.active").each(function() {
  var dataFour = jQuery(this).attr("data-four");
  filterList.push(dataFour);
});

jQuery("#jsonFilters ul#five ul li a.active").each(function() {
  var dataFive = jQuery(this).attr("data-five");
  filterList.push(dataFive);
});

if (filterList.length == 0) {
  jQuery('.div').removeClass('hidden');
  jQuery('.div').fadeIn();
  console.log('No Filters');
} else {
  jQuery('.div').each(function() {
    offeringOne = jQuery(this).attr('data-one');
    offeringTwo = jQuery(this).attr('data-two');
    offeringThree = jQuery(this).attr('data-three');
    offeringFour = jQuery(this).attr('data-four');
    offeringFive = jQuery(this).attr('data-five');

    if (jQuery.inArray(offeringOne, filterList) != -1 && jQuery.inArray(offeringTwo, filterList) != -1 && jQuery.inArray(offeringThree, filterList) != -1 && jQuery.inArray(offeringFour, filterList) != -1 && jQuery.inArray(offeringFive, filterList) != -1) {
      jQuery(this).fadeIn('slow');
    } else {
      jQuery(this).hide();
    }

  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div> Now if we just had some HTML here...</div>


Solution

  • Since your data-attribute values contain string values that represent lists of offerings delimited by commas, you will need to split those values into arrays so you can compare each offering value against the filterList.

    You could re-write your jQuery('.div').each handler to something like the following:

    var filterList = [
      'one-value',
      // 'one-value-2'
    ];
    
    if (filterList.length == 0) {
      jQuery('.div').removeClass('hidden');
      jQuery('.div').fadeIn();
      console.log('No Filters');
    } else {
      jQuery('.div').each(function() {
        const isVisible = ['data-one', 'data-two', 'data-three', 'data-four', 'data-five'].some(attr => {
          const attrValue = jQuery(this).attr(attr);
          if (!attrValue) { return; }
    
          const offerings = attrValue.split(',');
          
          return filterList.every(offering => offerings.indexOf(offering) > -1);
        });
        
        if (isVisible) {
          jQuery(this).fadeIn('slow');
        } else {
          jQuery(this).hide();
        }
      });
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="div" data-one="one-value,one-value-2,one-value-3">
      Div One
    </div>
    <div class="div">
      Div Two
    </div>
    <div class="div" data-one="one-value">
      Div Three
    </div>
    <div class="div">
      Div Four
    </div>
    <div class="div" data-one="one-value-2">
      Div Five
    </div>