Search code examples
javascriptjquerynested-loops

filter list with nested loop: if first loop finish successfully, do something


It might be a silly question but i really cannot wrap my head around it. I'm implementing a filter, which is made by select input and it should select divs with given value saved in data-* attribute.

I do so with a nested loop: I first loop through all divs and then i list through all given values coming from select inputs. If even one value from the select doesn't mach, i move on to the next div. If it does, i move on to the next value of the select inputs values's array. I almost get there, i miss the last little step which is: When i'm done looping all the values from the select and they all match with my div's data attr, then i should show this div. I cannot get where i should put the code to show this div!

Here my (simplify) code. Please no comment about how i could just use javascript, i know it could work perfectly too but i cannot with this project so it has to be in jQuery.

html:

<select class="filter">
  <option value="01">1</option>
  <option value="02">2</option>
  <option value="03">3</option>
</select>

<select class="filter">
  <option value="jan">Jan</option>
  <option value="feb">feb</option>
  <option value="march">march</option>
</select>

<div class="list-item" data-day="01" data-month="jan">01 jan </div>
<div class="list-item" data-day="02" data-month="feb">02 feb </div>
<div class="list-item" data-day="03" data-month="jan">03 jan </div>
<div class="list-item" data-day="02" data-month="march">02 march </div>
<div class="list-item" data-day="03" data-month="jan"> 03 jan</div>

jQuery:

function combinedFilters() {
  var valuesArray = [];
  var items = jQuery('.list-item');

  jQuery('select').each(function() {
    valuesArray.push(jQuery(this).val());
  });

  console.log(valuesArray);

  jQuery(items).each(function(i, item) {

    if (jQuery(this).data('month') && jQuery(this).data('day') ) {
      var month = jQuery(this).data('month');
      var day = jQuery(this).data('day').toString();

      jQuery.each(valuesArray, function(i, value) {
        if (value != null) {
        console.log(value);

          if (value == month || value == day) {
            return true; // keep looping into values Array
          } else {
            return false; //go out of the Values loop to the next div
          }
        }
        //jQuery(this).show();
        console.log('show the div');
      });
    }

  });
}


function trigger() {
  jQuery('select').change(function() {

    jQuery('.list-item').hide();
    combinedFilters();

  });
}

jQuery('.list-item').hide();
trigger();

And here a jsFiddle: https://jsfiddle.net/n2x5yc9g/1/

Any suggestion with explanation is really appreciated!

UPDATE:

Based on the solution proposed by @Michal Młoźniak i fix my filters, if anyone is interested in the final result here is the whole code: https://codepen.io/designbygio/pen/NRxvWo


Solution

  • Will that work for you or do you really need to have nested loop?

    function combinedFilters() {
      var valuesArray = [];
      var items = jQuery('.list-item');
    
      jQuery('select').each(function() {
        valuesArray.push(jQuery(this).val());
      });
    
      items.each(function(i, item) {
        if (jQuery(item).data('month') === valuesArray[1] && jQuery(item).data('day') === valuesArray[0] ) {
          jQuery(item).show();
        }
      });
    }
    
    function trigger() {
      jQuery('select').change(function() {
    
      jQuery('.list-item').hide();
        combinedFilters();
      });
    }
    
    jQuery(function() {
      jQuery('.list-item').hide();
      trigger();
    });