metafizzy / isotope

:revolving_hearts: Filter & sort magical layouts
https://isotope.metafizzy.co
11.07k stars 1.41k forks source link

Adding Search function to Isotope's "hideReveal" plugin #1516

Open colonialboy opened 5 years ago

colonialboy commented 5 years ago

Hi all,

I've adapted some code from Desandro's "hideReveal" plugin for Isotope: https://codepen.io/desandro/pen/drpJK/

But I am trying to add a search functionality to it, and I am having some trouble. Could someone help me out?

Here's what I have!

Thanks

HTML:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.isotope/3.0.6/isotope.pkgd.min.js"></script>

<div id="filters" class="button-group">
  <button class="button is-checked" data-filter="*">show all</button>
  <button class="button" data-filter=".metal">metal</button>
  <button class="button" data-filter=".transition">transition</button>
</div>

 <input type="text" id="quicksearch" placeholder="Search" class="form-control"/>

<div class="isotope">
  <div class="element-item transition metal " data-category="transition">
    <h3 class="name">Mercury</h3>
  </div>
  <div class="element-item metalloid " data-category="metalloid">
    <h3 class="name">Tellurium</h3>
  </div>
  <div class="element-item post-transition metal " data-category="post-transition">
    <h3 class="name">Bismuth</h3>
  </div>
  <div class="element-item post-transition metal " data-category="post-transition">
    <h3 class="name">Lead</h3>
  </div>
  <div class="element-item transition metal " data-category="transition">
    <h3 class="name">Gold</h3>
  </div>
  </div>

JS:

$.fn.hideReveal = function( options ) {
  options = $.extend({
    filter: '*',
    hiddenStyle: { opacity: 0.0 },
    visibleStyle: { opacity: 1 },
  }, options );
  this.each( function() {
    var $items = $(this).children();
    var $visible = $items.filter( options.filter );
    var $hidden = $items.not( options.filter );
    // reveal visible
    $visible.animate( options.visibleStyle );
    // hide hidden
    $hidden.animate( options.hiddenStyle );
  });
};
$( function() {
  var $container = $('.isotope');
  // filter functions
  var filterFns = {};
  // bind filter button click
  $('#filters').on( 'click', 'button', function() {
    var filterValue = $( this ).attr('data-filter');
    // use filterFn if matches value
    filterValue = filterFns[ filterValue ] || filterValue;
    $container.hideReveal({ filter: filterValue });
  });
  // change is-checked class on buttons
  $('.button-group').each( function( i, buttonGroup ) {
    var $buttonGroup = $( buttonGroup );
    $buttonGroup.on( 'click', 'button', function() {
      $buttonGroup.find('.is-checked').removeClass('is-checked');
      $( this ).addClass('is-checked');
    });
  });
});

CSS:

.button { display: inline-block; cursor: pointer; }
.button:active, .button.is-checked { background-color: #28F; }
.button.is-checked { color: white; text-shadow: 0 -1px hsla(0, 0%, 0%, 0.8); }
.button-group:after { content: ''; display: block; clear: both; }
.button-group .button { float: left; border-radius: 0; margin-left: 0; margin-right: 1px; }
.isotope { border: 2px solid #333; }
/* clear fix */
.isotope:after { content: ''; display: block; clear: both; }
p{display: inline;}
h3{display: inline;}
.element-item { position: relative; float: left; margin: 5px; }
.element-item > * { margin: 0; padding: 0; }
colonialboy commented 5 years ago

found my own answer, just adding will do the trick:

// quick search regex
var qsRegex;

// init Isotope
var $grid = $('.isotope').isotope({
  itemSelector: '.element-item',
  layoutMode: 'fitRows',
  filter: function() {
    return qsRegex ? $(this).text().match( qsRegex ) : true;
  }
});

// use value of search field to filter
var $quicksearch = $('.form-control').keyup( debounce( function() {
  qsRegex = new RegExp( $quicksearch.val(), 'gi' );
  $grid.isotope();
}, 200 ) );

// debounce so filtering doesn't happen every millisecond
function debounce( fn, threshold ) {
  var timeout;
  threshold = threshold || 100;
  return function debounced() {
    clearTimeout( timeout );
    var args = arguments;
    var _this = this;
    function delayed() {
      fn.apply( _this, args );
    }
    timeout = setTimeout( delayed, threshold );
  };
}
colonialboy commented 5 years ago

the problem is that it really screws up the positioning of the page! does anyone have any ideas how to make it keep positioning?