Im using the following snippet to facilitate a live search on my Isotope implementation.
It works great, but im wondering if there is a way to limit the scope of what it searches for.
Our isotope returns HTML like the following:
<div class="item">
<span class="title"></span>
<span calss="description"></span>
Right now it searches everything, how can i limit it to filter in results from just the "title" field?
jQuery(document).ready(function($) {
$(document).ready(function(){
var $container = $('#portfolio'),
// create a clone that will be used for measuring container width
$containerProxy = $container.clone().empty().css({ visibility: 'hidden' });
$container.after( $containerProxy );
// get the first item to use for measuring columnWidth
var $item = $container.find('.portfolio-item').eq(0);
$container.imagesLoaded(function(){
$(window).smartresize( function() {
// calculate columnWidth
var colWidth = Math.floor( $containerProxy.width() / 5 ); // Change this number to your desired amount of columns
// set width of container based on columnWidth
$container.css({
width: colWidth * 5 // Change this number to your desired amount of columns
})
.isotope({
// disable automatic resizing when window is resized
resizable: false,
// set columnWidth option for masonry
masonry: {
columnWidth: '.grid-sizer',
gutter: '.gutter-sizer'
}
});
// trigger smartresize for first time
}).smartresize();
});
$( function() {
// quick search regex
var qsRegex;
// init Isotope
var $grid = $('#portfolio').isotope({
itemSelector: '.portfolio-item',
layoutMode: 'fitRows',
filter: function() {
return qsRegex ? $(this).text().match( qsRegex ) : true;
}
});
// use value of search field to filter
var $quicksearch = $('.quicksearch').keyup( debounce( function() {
qsRegex = new RegExp( $quicksearch.val(), 'gi' );
$grid.isotope();
}, 200 ) );
// bind filter on select change
$('#filter-select').on( 'change', function() {
// get filter value from option value
var filterValue = this.value;
$grid.isotope({ filter: filterValue });
});
});
// debounce so filtering doesn't happen every millisecond
function debounce( fn, threshold ) {
var timeout;
return function debounced() {
if ( timeout ) {
clearTimeout( timeout );
}
function delayed() {
fn();
timeout = null;
}
timeout = setTimeout( delayed, threshold || 100 );
}
}
// filter items when filter link is clicked
$('#filters a').click(function(){
$('#filters a.active').removeClass('active');
var selector = $(this).attr('data-filter');
$container.isotope({ filter: selector, animationEngine : "css" });
$(this).addClass('active');
return false;
});
});
});
I believe this is what you want in your init to match only against the title:
return qsRegex ? $(this).find('.title').text().match( qsRegex ) : true;
i.e. Find the .title
inside the current node, get its text()
, then run the regex against that.
For the followup question about handling multiple filters: Currently you're running separate $grid.isotope({ filter: ...})
functions with a different filter for each UI widget, which overwrites the filter settings from any previous selection.
One way to avoid that problem would be to write a single filter function that checks all your conditions. A working example of this is below; the interesting bits are commented.
$(function() {
var $grid = $('#container');
$grid.isotope({itemSelector: '.item'});
var filters = []; // A convenient bucket for all the filter options,
// just so we don't have to look them up in the DOM every time.
// (a global array is maybe sort of not the most elegant
// way you could deal with this but you get the idea.)
// Search event handlers
$('.quicksearch').on('keyup', function() {
// debounce removed for brevity, but you'd put it here
filters[0] = this.value;
runFilter();
});
$('#filter-select').on('change', function() {
filters[1] = this.value;
runFilter();
});
// and so on if more filters needed
// The filter itself
var runFilter = function() {
$grid.isotope({
filter: function() {
if (filters[0]) {
// at least some search text was entered:
var qsRegex = new RegExp(filters[0], 'gi');
// if the title doesn't match, eliminate it:
if (!$(this).find('.title').text().match(qsRegex)) {
return false;
}
}
if (filters[1]) {
// a category was selected; filter out others:
if (!($(this).hasClass(filters[1]))) {
return false;
}
}
// etcetera, for any other filters
// successfully passed all conditions, so:
return true;
}
});
}
});
.item {
width: 120px;
height: 70px;
margin: 3px; padding: 3px;
display: inline-block;
}
.red {background: red;}
.blue {background: blue;}
.green {background: green;}
.yellow {background: yellow;}
/* isotope css (animations etc) omitted */
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://isotope.metafizzy.co/v1/jquery.isotope.min.js"></script>
<div id="filters">
Color: <select id="filter-select">
<option value="">All</option>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select><br>
Title: <input type="text" class="quicksearch">
</div>
<div id="container">
<div class="red item"><div class="title">Title aaa</div><div class="description">Description xxx</div></div>
<div class="green item"><div class="title">Title bbb</div><div class="description">Description yyy</div></div>
<div class="blue item"><div class="title">Title ccc</div><div class="description">Description zzz</div></div>
<div class="yellow item"><div class="title">Title aaa</div><div class="description">Description xxx</div></div>
<div class="red item"><div class="title">Title bbb</div><div class="description">Description yyy</div></div>
<div class="green item"><div class="title">Title ccc</div><div class="description">Description zzz</div></div>
<div class="blue item"><div class="title">Title aaa</div><div class="description">Description xxx</div></div>
<div class="yellow item"><div class="title">Title bbb</div><div class="description">Description yyy</div></div>
<div class="red item"><div class="title">Title ccc</div><div class="description">Description zzz</div></div>
<div class="green item"><div class="title">Title aaa</div><div class="description">Description xxx</div></div>
<div class="blue item"><div class="title">Title bbb</div><div class="description">Description yyy</div></div>
<div class="yellow item"><div class="title">Title ccc</div><div class="description">Description zzz</div></div>
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With