skip to Main Content

I have a couple of divs that I’m trying to filter them according to some dropdown filters. I’m using a data-product_cost=true attribute to list to filter them, so if I were to pick product_cost in the dropdown, all product divs with the product_cost=true attribute would show up the list and not any of the rest.

From the "Kontogebühren" dropdown list, if “Kostenlose Kontoführung” is selected, currently it shows all the cards. it should show only N26, Comdirect and DKB cards for the “Kostenlose Kontoführung” option selection.

// select tag

jQuery(document).ready(function($) {

  jQuery("#products-filter").change(function() {
    filtering_vergleiche();
  });

  filtering_vergleiche();

  function filtering_vergleiche() {

    var choosen_filter = [];
    jQuery('.product-item').removeClass('filter_hidden');
    jQuery('.filter_no_results').remove();

    jQuery('.products-filter select option:selected').each(function(index) {

      var current_filter_name = jQuery(this).attr('name');

      var current_filter_value = jQuery(this).attr('value');

      //Create object with all necessary info
      choosen_filter.push({
        "name": current_filter_name,
        "value": current_filter_value
      });
    });
    count_item = 0;
    count_hidden = 0;
    jQuery('.product-item').each(function(index) {
      for (var i = 0; i < choosen_filter.length; ++i) {
        choosen_filter_item = choosen_filter[i];
        choosen_filter_name = choosen_filter_item.name;
        choosen_filter_value = choosen_filter_item.value;

        filter_value_on_product = jQuery(this).attr('data-' + choosen_filter_name);

        if (choosen_filter_value != 'alle') {
          if (filter_value_on_product.indexOf(',') > -1) {
            let segments = filter_value_on_product.split(',').map(element => element.trim());;
            if (!segments.includes(choosen_filter_value)) {
              jQuery(this).addClass('filter_hidden');
            }
          } else if (filter_value_on_product != choosen_filter_value) {
            jQuery(this).addClass('filter_hidden');
          }
        }
      }
      count_item++;
    });

    jQuery('.product-item.filter_hidden').each(function(index) {
      count_hidden++;
    });

    //Nachricht anzeigen wenn keine Produkte gefunden wurden
    if (count_hidden == count_item) {
      jQuery("<p class='filter_no_results'>Zu dieser Auswahl wurden leider keine Ergebnisse gefunden.<br>Bitte andere Kriterien auswählen.<p>").appendTo('.product-item-listing');
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
  <select id="filter_checkboxes" class="vergleich_select" size="1" name="term">
    <option id="filter_all" name="filter_alle" value="alle">
      Alle
    </option>
    <option id="product_cost" name="product_cost" value="true">
      Kostenlose Kontoführung
    </option>
    <option id="incentive" name="incentive" value="true">
      Mit Startguthaben
    </option>
  </select>
  <div class="product-item" data-incentive="false" data-partnercard="false" data-atm_euro_fee="false" data-atm_international_fee="false" data- incoming_pm_min="true" data-product_cost="true">
    N26
  </div>
  <div class="product-item " data-incentive="false" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="true" data- incoming_pm_min="false" data-product_cost="true">
    ComDirect
  </div>
  <div class="product-item" data-incentive="false" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="true" data- incoming_pm_min="false" data-product_cost="true">
    DKB
  </div>

  <div class="product-item" data-incentive="true" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="false" data-incoming_pm_min="false" data-product_cost="true">
    Revolut
  </div>
  </div>
</body>
</html>

I can’t seem to find what’s faulty in the filtering_vergleiche() function as I’m a bit of a newbie to jQuery.

2

Answers


  1. The problem is all in your selectors.

    The .change() handler should be on `jQuery("#filter_checkboxes").

    The loop to get option values should use jQuery("#filter_checkboxes option:selected").

    You need CSS for .filter_hidden to hide the element.

    jQuery(document).ready(function($) {
    
      jQuery("#filter_checkboxes").change(function() {
        filtering_vergleiche();
      });
    
      filtering_vergleiche();
    
      function filtering_vergleiche() {
    
        var choosen_filter = [];
        jQuery('.product-item').removeClass('filter_hidden');
        jQuery('.filter_no_results').remove();
    
        jQuery('#filter_checkboxes option:selected').each(function(index) {
    
          var current_filter_name = jQuery(this).attr('name');
    
          var current_filter_value = jQuery(this).attr('value');
    
          //Create object with all necessary info
          choosen_filter.push({
            "name": current_filter_name,
            "value": current_filter_value
          });
        });
        count_item = 0;
        count_hidden = 0;
        jQuery('.product-item').each(function(index) {
          for (var i = 0; i < choosen_filter.length; ++i) {
            choosen_filter_item = choosen_filter[i];
            choosen_filter_name = choosen_filter_item.name;
            choosen_filter_value = choosen_filter_item.value;
    
            filter_value_on_product = jQuery(this).attr('data-' + choosen_filter_name);
    
            if (choosen_filter_value != 'alle') {
              if (filter_value_on_product.indexOf(',') > -1) {
                let segments = filter_value_on_product.split(',').map(element => element.trim());;
                if (!segments.includes(choosen_filter_value)) {
                  jQuery(this).addClass('filter_hidden');
                }
              } else if (filter_value_on_product != choosen_filter_value) {
                jQuery(this).addClass('filter_hidden');
              }
            }
          }
          count_item++;
        });
    
        jQuery('.product-item.filter_hidden').each(function(index) {
          count_hidden++;
        });
    
        //Nachricht anzeigen wenn keine Produkte gefunden wurden
        if (count_hidden == count_item) {
          jQuery("<p class='filter_no_results'>Zu dieser Auswahl wurden leider keine Ergebnisse gefunden.<br>Bitte andere Kriterien auswählen.<p>").appendTo('.product-item-listing');
        }
      }
    });
    .filter_hidden {
      display: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <html>
    <body>
      <select id="filter_checkboxes" class="vergleich_select" size="1" name="term">
        <option id="filter_all" name="filter_alle" value="alle">
          Alle
        </option>
        <option id="product_cost" name="product_cost" value="true">
          Kostenlose Kontoführung
        </option>
        <option id="incentive" name="incentive" value="true">
          Mit Startguthaben
        </option>
      </select>
      <div class="product-item" data-incentive="false" data-partnercard="false" data-atm_euro_fee="false" data-atm_international_fee="false" data- incoming_pm_min="true" data-product_cost="true">
        N26
      </div>
      <div class="product-item " data-incentive="false" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="true" data- incoming_pm_min="false" data-product_cost="true">
        ComDirect
      </div>
      <div class="product-item" data-incentive="false" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="true" data- incoming_pm_min="false" data-product_cost="true">
        DKB
      </div>
    
      <div class="product-item" data-incentive="true" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="false" data-incoming_pm_min="false" data-product_cost="true">
        Revolut
      </div>
      </div>
    </body>
    </html>
    Login or Signup to reply.
  2. I think I see where you are going with this. A good number of syntax issues I fixed – post the HTML in an HTML validator to see those.

    Here I added a few options to make it more illustrative when you select (I changed to multiple so you can pick more than one)

    I used colors and a data attribute to do some to show what has been chosen.

    jQuery(function($) {
      $("#filter_select").on('change', filtering_vergleiche).first().trigger('change');
      //triggered instead of calling: filtering_vergleiche();
    
      function filtering_vergleiche(event) {
        let choosen_filter = [];
        $('.product-item').each(function() {
          this.dataset.chosen = "false";
        });
        let $choices = $(this).find('option:selected');
        $('.product-item').removeClass('filter_hidden');
        $('.product-item-listing').find('.filter_no_results').remove();
        // nothing picked so get out of here
        if (!$choices.length) {
          return;
        }
        $choices.each(function(index) {
          choosen_filter.push({
            "name": $(this).attr('name'),
            "value": $(this).attr('value')
          });
        });
        let $products = $('.product-item');
        let count_item = $products.length; //0;
        let count_hidden = 0;
        $products.each(function(index) {
          let isChoice = this.dataset.chosen == "true";
          // we already chose it so go to next one
          if (isChoice) return;
          for (var i = 0; i < choosen_filter.length; ++i) {
            let choosen_filter_item = choosen_filter[i];
            let choosen_filter_name = choosen_filter_item.name;
            let choosen_filter_value = choosen_filter_item.value;
    
            let filter_value_on_product = $(this).data(choosen_filter_name);
            filter_value_on_product = filter_value_on_product || $(this).data('choice') == choosen_filter_value;
            this.dataset.chosen = this.dataset.chosen == "true" || choosen_filter_value == 'alle' || filter_value_on_product ? "true" : "false";
          }
        });
        let hiddenOnes = $('.product-item').filter('.filter_hidden');
        count_hidden = hiddenOnes.length;
        if (count_hidden == count_item) {
          $("<p class='filter_no_results'>Zu dieser Auswahl wurden leider keine Ergebnisse gefunden.<br>Bitte andere Kriterien auswählen.<p>").appendTo('.product-item-listing');
        }
      }
    });
    .filter_hidden {
      border: solid green 1px;
    }
    
    .vergleich_select {
      height: 6rem;
    }
    
    .product-item-listing {
      margin-top: 1rem;
      border: solid 1px red;
    }
    
    .product-item[data-chosen="true"] {
      background-color: #ddffdd44;
    }
    
    .product-item[data-chosen="false"] {
      background-color: #ddddff44;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <select id="filter_select" class="vergleich_select" size="1" name="term" multiple>
      <option name="filter_alle" value="alle" data-choice="all">
        Alle (All)
      </option>
      <option name="product_cost" value="true" data-choice="product_cost">
        Kostenlose Kontoführung (Free Account Management)
      </option>
      <option name="incentive" value="true" data-choice="incentive">
        Mit Startguthaben (With starting credit)
      </option>
      <option name="incoming_pm_min" value="true" data-choice="incoming_pm_min">
        incoming_pm_min = true
      </option>
      <option name="incentive" value="true" data-choice="partnercard">
        partnercard = true
      </option>
      <option name="incentive" value="true" data-choice="atm_international_fee">
        atm_international_fee = true
      </option>
    </select>
    
    <div class="product-item" data-incentive="false" data-partnercard="false" data-atm_euro_fee="false" data-atm_international_fee="false" data-incoming_pm_min="true" data-product_cost="true">N26</div>
    <div class="product-item " data-incentive="false" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="true" data-incoming_pm_min="false" data-product_cost="true">ComDirect</div>
    <div class="product-item" data-incentive="false" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="true" data- incoming_pm_min="false" data-product_cost="true">DKB</div>
    <div class="product-item" data-incentive="true" data-partnercard="true" data-atm_euro_fee="true" data-atm_international_fee="false" data-incoming_pm_min="false" data-product_cost="true">Revolut</div>
    <div class="product-item-listing">empty</div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search