Joelgullander
Joelgullander

Reputation: 1684

Jquery filtering based on radio / checkbox states

I have an issue that I cant seem to figure out how to fix.. Im still green on javascript.

I am having this markup:

<div class="area-listing">
    <div id="list-filter">
        <input type="radio" id="all" name="rr" data-filter="all" checked />
        <label for="all"><span></span>Samtliga</label>

        <input type="radio" id="student" name="rr" data-filter="student" />
        <label for="student"><span></span>Studentboende</label>

        <input type="radio" id="construction" name="rr" data-filter="construction" />
        <label for="construction"><span></span>Nybyggnation</label>

        <input type="checkbox" id="available" name="cc" data-filter="available" />
        <label for="available"><span></span>Visa endast lediga lägenheter</label>

    </div>

    <div class="area col-sm-4"></div>
    <div class="area col-sm-4 construction"></div>
    <div class="area col-sm-4 available student"></div>
    <div class="area col-sm-4 available"></div>
    <div class="area col-sm-4 available"></div>
    <div class="area col-sm-4 available"></div>

</div>



function areaListing() {
    if ($(".area-listing").length) {
        var filters = $(".area-listing #list-filter");
        var areas = $(".area-listing .area");

        areas.show();

        var $areas = $('input').on("change", function () {
            if (this.id == 'all') {
                areas.fadeIn(450);
            } else {
                var $el = $('.' + this.id).fadeIn(450);
                areas.not($el).hide();
            }
            $areas.removeClass('filtered');
            $(this).addClass('filtered');
        })
    }
}

And with the javascript I am now filtering fine based on the radio buttons.. However I want to add the possibility to trigger another filter on the "checkbox" to filter out "available" elements. However I can't get it to work.. can anyone assist me? Right now it works on the first checkbox click, but doesnt register when untoggling it.

To clarify: When clicking the checkbox the filtering should remain but only show the areas with available. And when untoggled it should show all.

Upvotes: 0

Views: 1618

Answers (3)

Tushar
Tushar

Reputation: 87203

Here's code for the filtering based on both Checkbox AND Radio button. When any of the radio button or checkbox is checked(or checkbox is unchecked), you need to first get the checked status of checkbox. If this checkbox is checked, only areas with .available should be shown and others should be hidden. If this checkbox is unchecked, there is no need to bother about .available elements.

Here are some suggestions:

  1. Wrap the code interacting with DOM in ready
  2. $('.area-listing').length is not needed as it'll always be true provided that code is executed after page load
  3. filters is never used, thus can be removed.
  4. areas.show() is not needed if .area elements are not hidden.
  5. Instead of ID, use data-filter to get the class on which the filter is to be applied.

Fiddle Demo

// When DOM is completely loaded
$(document).ready(function() {
  'use strict';

  // Cache element references
  var $areas = $('.area');
  var $checkbox = $('#available');
  var $radios = $('#list-filter :radio');
  var checkboxFilter = $checkbox.data('filter');

  // Bind change event on radio buttons and checkbox
  $('#list-filter').on('change', ':radio, :checkbox', function(e) {

    // Get the checked status of checkbox
    var isCheckboxChecked = $checkbox.is(':checked');

    // Get the checked radio button filter
    var radio = $radios.filter(':checked').data('filter');
 
    // Create filter based on checked radio button and checkbox state
    var filter = isCheckboxChecked ? '.' + radio + '.' + checkboxFilter : '.' + radio;


    if (radio === 'all') {
      if (isCheckboxChecked) {
        // Show only .available
        $areas.filter('.' + checkboxFilter).fadeIn(450);
      } else {
        // Show all
        $areas.fadeIn(450);
      }
    } else {
      // Hide those except filtered
      $areas.not(filter).hide();

      // Show filtered
      $areas.filter(filter).fadeIn(450);
    }
  }).trigger('change'); // To call the handler on page load
});
label {
  margin-right: 2px;
}

div.area {
  margin: 5px;
  color: green;
  font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="area-listing">
  <div id="list-filter">
    <input type="radio" id="all" name="rr" data-filter="all" checked />
    <label for="all"><span></span>Samtliga</label>

    <input type="radio" id="student" name="rr" data-filter="student" />
    <label for="student"><span></span>Studentboende</label>

    <input type="radio" id="construction" name="rr" data-filter="construction" />
    <label for="construction"><span></span>Nybyggnation</label>

    <input type="checkbox" id="available" name="cc" data-filter="available" />
    <label for="available"><span></span>Visa endast lediga lägenheter</label>

  </div>

  <div class="area col-sm-4">First</div>
  <div class="area col-sm-4 construction">Second</div>
  <div class="area col-sm-4 available student">Third</div>
  <div class="area col-sm-4 available">Fourth</div>
  <div class="area col-sm-4 available">Fifth</div>
  <div class="area col-sm-4 available">Sixth</div>

</div>

Upvotes: 3

TriForce
TriForce

Reputation: 415

I think i know what you want to do, first of all, doing the checks from radios or checkboxes is a little bit weird for normal usage, i think you need to use a "filter" button, so i added one to filter every option selected.

This is the JS code:

//Launch the filter with a button
$("#list-filter input[type='button']").click(function(){ 

    //Get the element
    var input = $("#list-filter input[type='radio']:checked").attr("data-filter");
    var check = $("#list-filter input[type='checkbox']");

    //Check for available only
    if(check.is(":checked")){
        if(input=="all"){ //Show all available
            $(".area-listing .area").css("display","none");
            $(".area-listing .area.available").css("display","block");
        }
        else{ //Show only available in the desired area
            $(".area-listing .area").css("display","none");
            $(".area-listing .area.available."+input).css("display","block");
        }
    }
    else //If not available is checked
    {
        if(input=="all"){ //Show all
            $(".area-listing .area").css("display","block");
        }
        else{ //Show only the desired area
            $(".area-listing .area").css("display","none");
            $(".area-listing .area."+input).css("display","block");
        }
    }

});

This is the full test (i added a CSS to hide all areas by default, and the button to filter all options)

https://jsfiddle.net/psyzc79w/

Tell me if this way is useful for you.

Upvotes: 1

pan.goth
pan.goth

Reputation: 1485

You can store current filters in variables and change them after clicking on radio or checkbox input.

function areaListing() {
  if ($('.area-listing').length) {
    var filters = $('.area-listing #list-filter');
    var areas = $('.area-listing .area');

    areas.show();

    var currentFilter = 'all';
    var showOnlyAvailable = false;
    
    function filterAreas() {
    	var currentSelector = '.area';
      
      if (currentFilter !== 'all') {
      	currentSelector += '.' + currentFilter;
      }
      
      if (showOnlyAvailable) {
      	currentSelector += '.available';
      }
      
      var $el = $(currentSelector).fadeIn(450);
      areas.not($el).hide();
    }

    $('input[type="radio"]').on('change', function() {
      currentFilter = this.id;
      
      filterAreas();
    });
    
    $('input[type="checkbox"]').on('change', function() {
      showOnlyAvailable = $(this).is(':checked');
      
      filterAreas();
    });
  }
}

areaListing();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="area-listing">
    <div id="list-filter">
        <input type="radio" id="all" name="rr" data-filter="all" checked />
        <label for="all"><span></span>Samtliga</label>

        <input type="radio" id="student" name="rr" data-filter="student" />
        <label for="student"><span></span>Studentboende</label>

        <input type="radio" id="construction" name="rr" data-filter="construction" />
        <label for="construction"><span></span>Nybyggnation</label>

        <input type="checkbox" id="available" name="cc" data-filter="available" />
        <label for="available"><span></span>Visa endast lediga lägenheter</label>

    </div>

    <div class="area col-sm-4">a</div>
    <div class="area col-sm-4 construction">b</div>
    <div class="area col-sm-4 available student">c</div>
    <div class="area col-sm-4 available">d</div>
    <div class="area col-sm-4 available">e</div>
    <div class="area col-sm-4 available">f</div>

</div>

Upvotes: 3

Related Questions