Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                    <header class="jumbotron">
        <div class="container">

            <h1>Range Sliders with Combo Filters</h1>
            <p>Combination filters with range sliders. Using <a href="https://getbootstrap.com/">Bootstrap 3</a> and <a href="https://github.com/seiyria/bootstrap-slider" target="_blank">Bootstrap Slider</a> as well as <a href="https://isotope.metafizzy.co/" target="_blank">Isotope</a>.</p>
        </div>
    </header>

    <section class="container">
    <div class="filters filter-section">
        <div class="row">
            <div class="col-sm-4">
                <span class="filter-label">Color:</span>
                <div class="btn-group" role="group" data-filter-group="color">
                    <span class="btn btn-sm btn-default btn-filter is-checked" data-filter="">Any</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".red">Red</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".blue">Blue</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".yellow">Yellow</span>
                </div>
            </div>
            <div class="col-sm-4">
                <span class="filter-label">Size:</span>
                <div class="btn-group" role="group" data-filter-group="size">
                    <span class="btn btn-sm btn-default btn-filter is-checked" data-filter="">Any</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".small">Small</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".wide">Wide</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".big">Big</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".tall">Tall</span>
                </div>
            </div>
            <div class="col-sm-4">
                <span class="filter-label">Shape:</span>
                <div class="btn-group" role="group" data-filter-group="shape">
                    <span class="btn btn-sm btn-default btn-filter is-checked" data-filter="">Any</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".round">Round</span>
                    <span class="btn btn-sm btn-default btn-filter" data-filter=".square">Square</span>
                </div>
            </div>
        </div>
        <div class="sliders row">
            <div class="col-sm-4">
                <div class="bootstrap-slider">
                    <span class="filter-label">Weight Range: <span class="filter-selection"></span></span>
                    <b class="filter-min">40</b> <input id="filter-weight" type="text" class="bootstrap-slider" value="" data-filter-group="weight"> <b class="filter-max">150</b>
                </div>
            </div>
            <div class="col-sm-4">
                <div class="bootstrap-slider">
                    <span class="filter-label">Height Range: <span class="filter-selection"></span> </span>
                    <b>140</b><input id="filter-height" type="text" class="bootstrap-slider" value="" data-slider-step="1" data-filter-group="height"> <b>220</b>
                </div>
            </div>
        </div>

        <!-- This is the Isotope grid that contains all the elements to be filtered
             The JS references the item class to define which element to sort, filter and apply masonry layout to
             The item class could be renamed to anything you want e.g. card, product etc. and the JS from itemSelector: '.item'
        -->
        <div class="grid">
            <div class="item small round red" data-height="180" data-weight="75"><span class="content">Height:180<br>Weight: 75</span></div>
            <div class="item small round blue" data-height="179" data-weight="73"><span class="content">Height:179<br>Weight: 73</span></div>
            <div class="item small round yellow" data-height="162" data-weight="53"><span class="content">Height:162<br>Weight: 53</span></div>
            <div class="item small square red" data-height="173" data-weight="62"><span class="content">Height:173<br>Weight: 62</span></div>
            <div class="item small square blue" data-height="192" data-weight="95"><span class="content">Height:192<br>Weight: 95</span></div>
            <div class="item small square yellow" data-height="185" data-weight="83"><span class="content">Height:185<br>Weight: 83</span></div>
            <div class="item wide round red" data-height="170" data-weight="93"><span class="content">Height:170<br>Weight: 93</span></div>
            <div class="item wide round blue" data-height="150" data-weight="50"><span class="content">Height:150<br>Weight: 50</span></div>
            <div class="item wide round yellow" data-height="176" data-weight="61"><span class="content">Height:176<br>Weight: 61</span></div>
            <div class="item wide square red" data-height="155" data-weight="56"><span class="content">Height:155<br>Weight: 56</span></div>
            <div class="item wide square blue" data-height="188" data-weight="87"><span class="content">Height:188<br>Weight: 87</span></div>
            <div class="item wide square yellow" data-height="192" data-weight="89"><span class="content">Height:192<br>Weight: 89</span></div>
            <div class="item big round red" data-height="183" data-weight="88"><span class="content">Height:183<br>Weight: 88</span></div>
            <div class="item big round blue" data-height="189" data-weight="91"><span class="content">Height:189<br>Weight: 91</span></div>
            <div class="item big round yellow" data-height="178" data-weight="80"><span class="content">Height:178<br>Weight: 80</span></div>
            <div class="item big square red" data-height="156" data-weight="49"><span class="content">Height:156<br>Weight: 49</span></div>
            <div class="item big square blue" data-height="157" data-weight="58"><span class="content">Height:157<br>Weight: 58</span></div>
            <div class="item big square yellow" data-height="166" data-weight="60"><span class="content">Height:166<br>Weight: 60</span></div>
            <div class="item tall round red" data-height="163" data-weight="59"><span class="content">Height:163<br>Weight: 59</span></div>
            <div class="item tall round blue" data-height="161" data-weight="53"><span class="content">Height:161<br>Weight: 53</span></div>
            <div class="item tall round yellow" data-height="160" data-weight="51"><span class="content">Height:160<br>Weight: 51</span></div>
            <div class="item tall square red" data-height="170" data-weight="70"><span class="content">Height:170<br>Weight: 70</span></div>
            <div class="item tall square blue" data-height="175" data-weight="73"><span class="content">Height:175<br>Weight: 73</span></div>
            <div class="item tall square yellow" data-height="173" data-weight="67"><span class="content">Height:173<br>Weight: 67</span></div>
            <div class="item wide round red" data-height="181" data-weight="85"><span class="content">Height:181<br>Weight: 85</span></div>
            <div class="item small round blue" data-height="172" data-weight="63"><span class="content">Height:172<br>Weight: 63</span></div>
            <div class="item small round blue" data-height="152" data-weight="51"><span class="content">Height:152<br>Weight: 51</span></div>
            <div class="item small square yellow" data-height="173" data-weight="62"><span class="content">Height:173<br>Weight: 62</span></div>
            <div class="item small square blue" data-height="192" data-weight="95"><span class="content">Height:192<br>Weight: 95</span></div>
            <div class="item small square yellow" data-height="185" data-weight="83"><span class="content">Height:185<br>Weight: 83</span></div>
            <div class="item small square red" data-height="170" data-weight="93"><span class="content">Height:170<br>Weight: 93</span></div>
            <div class="item big round blue" data-height="150" data-weight="50"><span class="content">Height:150<br>Weight: 50</span></div>
            <div class="item tall round yellow" data-height="176" data-weight="61"><span class="content">Height:176<br>Weight: 61</span></div>
            <div class="item tall square red" data-height="155" data-weight="56"><span class="content">Height:155<br>Weight: 56</span></div>
            <div class="item big square blue" data-height="188" data-weight="87"><span class="content">Height:188<br>Weight: 87</span></div>
            <div class="item wide square red" data-height="192" data-weight="89"><span class="content">Height:192<br>Weight: 89</span></div>
        </div>
    </section>
              
            
!

CSS

              
                * {
  -webkit-box-sizing: border-box;
     -moz-box-sizing: border-box;
          box-sizing: border-box;
}
body { font-family: sans-serif; }


.btn {
  font-weight: bold;
  text-transform: uppercase;
}
.btn:hover {
  background-color: ccc;
  text-shadow: 0 1px hsla(0, 0%, 100%, 0.5);
  color: #222;
}
.btn:active,
.btn.is-checked {
  background-color: #2175b0;
  color: #fff;
}

/* --------------------------------------- */
/* Isotope Grid */
/* --------------------------------------- */
.grid {
  background: #EEE;
  max-width: 1200px;
}
/* clear fix */
.grid:after {
  content: '';
  display: block;
  clear: both;
}

/* --------------------------------------- */
/* Isotope item */
/* --------------------------------------- */
.item {
  width: 70px;
  height: 70px;
  margin: 5px;
  float: left;
  text-align: center;
}
.item.round { border-radius: 35px; }
.item.big.round { border-radius: 75px; }

.item.red { background: #b0221b; }
.item.blue { background: #2175b0; }
.item.yellow { background: #e8ce3c; }

.item.wide,
.item.big { width: 150px; }
.item.tall,
.item.big { height: 150px; }

.item .content {
  color: #fff;
  font-size: 10px;
  padding-top: 20px;
  display: inline-block;
}

/* --------------------------------------- */
/* Bootstrap Slider */
/* --------------------------------------- */
.sliders { padding: 15px 0 30px 0; }
.filter-section .filter-label {
  display: block;
  font-weight: bold;
}
.bootstrap-slider .slider-selection { background: #2175b0; }


              
            
!

JS

              
                // External js: jquery, isotope.pkgd.js, bootstrap.min.js, bootstrap-slider.js
$(document).ready( function() {

  // Create object to store filter for each group
  var buttonFilters = {};
  var buttonFilter = '*';
  // Create new object for the range filters and set default values,
  // The default values should correspond to the default values from the slider
  var rangeFilters = {
      'height': {'min':150, 'max': 185},
      'weight': {'min':50, 'max': 90}
    };

  // Initialise Isotope
  // Set the item selector
  var $grid = $('.grid').isotope({
    itemSelector: '.item',
    layout: 'masonry',
    // use filter function
    filter: function() {
      var $this = $(this);
      var height = $this.attr('data-height');
      var weight = $this.attr('data-weight');
      var isInHeightRange = (rangeFilters['height'].min <= height && rangeFilters['height'].max >= height);
      var isInWeightRange = (rangeFilters['weight'].min <= weight && rangeFilters['weight'].max >= weight);
      //console.log(rangeFilters['height']);
      //console.log(rangeFilters['weight']);
      // Debug to check whether an item is within the height weight range
      //console.log('isInHeightRange:' +isInHeightRange + '\nisInWeightRange: ' + isInWeightRange );
      return $this.is( buttonFilter ) && (isInHeightRange && isInWeightRange);
    }
  });


  // Initialise Sliders
  // Set min/max range on sliders as well as default values
  var $heightSlider = $('#filter-height').slider({ tooltip_split: true, min: 130,  max: 220, range: true, value: [150, 180] });
  var $weightSlider = $('#filter-weight').slider({ tooltip_split: true, min: 40,  max: 150, range: true, value: [50, 90] });


  function updateRangeSlider(slider, slideEvt) {
    console.log('Current slider:' + slider);
    var sldmin = +slideEvt.value[0],
        sldmax = +slideEvt.value[1],
        // Find which filter group this slider is in (in this case it will be either height or weight)
        // This can be changed by modifying the data-filter-group="age" attribute on the slider HTML
        filterGroup = slider.attr('data-filter-group'),
        // Set current selection in variable that can be pass to the label
        currentSelection = sldmin + ' - ' + sldmax;

      // Update filter label with new range selection
      slider.siblings('.filter-label').find('.filter-selection').text(currentSelection);

      // Set min and max values for current selection to current selection
      // If no values are found set min to 0 and max to 100000
      // Store min/max values in rangeFilters array in the relevant filter group
      // E.g. rangeFilters['height'].min and rangeFilters['height'].max
      console.log('Filtergroup: '+ filterGroup);
      rangeFilters[filterGroup] = {
        min: sldmin || 0,
        max: sldmax || 100000
      };
      // Trigger isotope again to refresh layout
      $grid.isotope();

  }

  // Trigger Isotope Filter when slider drag has stopped
  $heightSlider.on('slideStop', function(slideEvt){
    var $this =$(this);
    updateRangeSlider($this, slideEvt);
  });
  $weightSlider.on('slideStop', function(slideEvt){
    var $this =$(this);
    updateRangeSlider($this, slideEvt);
  });


  // Look inside element with .filters class for any clicks on elements with .btn
  $('.filters').on( 'click', '.btn', function() {
    var $this = $(this);
    // Get group key from parent btn-group (e.g. data-filter-group="color")
    var $buttonGroup = $this.parents('.btn-group');
    var filterGroup = $buttonGroup.attr('data-filter-group');
    // set filter for group
    buttonFilters[ filterGroup ] = $this.attr('data-filter');
    // Combine filters or set the value to * if buttonFilters
    buttonFilter = concatValues( buttonFilters ) || '*';
    // Log out current filter to check that it's working when clicked
    console.log( buttonFilter )
    // Trigger isotope again to refresh layout
    $grid.isotope();
  });


  // change is-checked class on btn-filter to toggle which one is active
  $('.btn-group').each( function( i, buttonGroup ) {
      var $buttonGroup = $( buttonGroup );
      $buttonGroup.on( 'click', '.btn-filter', function() {
          $buttonGroup.find('.is-checked').removeClass('is-checked');
          $(this).addClass('is-checked');
      });
  });

});

// Flatten object by concatting values
function concatValues( obj ) {
  var value = '';
  for ( var prop in obj ) {
    value += obj[ prop ];
  }
  return value;
}

              
            
!
999px

Console