A Continuation of the Isotope Tutorial: Combination Filters
Jul 25, 2012 | In jQuery, Tutorials |Isotope.js is a powerful tool for creating dynamic webpages with interactive capabilities. It does this by using “filtering”, by which certain elements on the page are removed or added, depending on what the user requests. This by itself is incredibly useful, but it can be made even better, by using combination filters. This allows the user to select two criteria by which content is filtered. In this tutorial, I’ll show how to do just that.
This post will be based on the code from the isotope tutorial I wrote a while ago, so grab a copy of the code from there.
HTML
The HTML structure is the same as in the original isotope tutorial, but with minor differences in the class names and titles.
Here’s a sample content box:
<div class="box june y2010"> <h2 class="box-title">Lorem Ipsum - June, 2010</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Ut aliquet integer sed enim ac amet nunc? Tincidunt sit, cum ridiculus, placerat cum, vut magna ridiculus ut phasellus ridiculus? Eu hac, mattis adipiscing, montes adipiscing urna montes rhoncus! </div> </div>
We have a class called “june”, which is the month this post was published, and a class called “y2010″, which is the year. It’s not possible to have a class with just numbers, so the “y” is necessary. The same concept applies to every other post.
<div class="box june y2010"> <h2 class="box-title">Lorem Ipsum - June, 2010</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Ut aliquet integer sed enim ac amet nunc? Tincidunt sit, cum ridiculus, placerat cum, vut magna ridiculus ut phasellus ridiculus? Eu hac, mattis adipiscing, montes adipiscing urna montes rhoncus! </div> </div> <div class="box july y2010"> <h2 class="box-title">Lorem Ipsum - July, 2010</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Ut aliquet integer sed enim ac amet nunc? Tincidunt sit, cum ridiculus, placerat cum, vut magna ridiculus ut phasellus ridiculus? Eu hac, mattis adipiscing, montes adipiscing urna montes rhoncus! Odio placerat pellentesque risus urna elit, odio phasellus, rhoncus, est ridiculus purus etiam, penatibus integer! </div> </div> <div class="box august y2010"> <h2 class="box-title">Lorem Ipsum - August, 2010</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? </div> </div> <div class="box june y2011"> <h2 class="box-title">Lorem Ipsum - June, 2011</h2> <div class="box-text"> Amet dolor? Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies. </div> </div> <div class="box july y2011"> <h2 class="box-title">Lorem Ipsum - July, 2011</h2> <div class="box-text"> Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies. </div> </div> <div class="box august y2011"> <h2 class="box-title">Lorem Ipsum - August, 2011</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Nascetur? Vut amet, phasellus pulvinar et odio. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies. </div> </div> <div class="box june y2012"> <h2 class="box-title">Lorem Ipsum - June, 2012</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. </div> </div> <div class="box july y2012"> <h2 class="box-title">Lorem Ipsum - July, 2012</h2> <div class="box-text"> Amet dolor? Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies. </div> </div> <div class="box august y2012"> <h2 class="box-title">Lorem Ipsum - August, 2012</h2> <div class="box-text"> Urna vut, eros aliquet sagittis augue? Augue adipiscing duis? Et a placerat, magna enim? Lacus sit. Nunc montes tristique purus auctor. Amet dolor? Diam cras ac quis a ut, augue massa cursus natoque cursus in sociis rhoncus, scelerisque mus ac. Pellentesque odio rhoncus, aliquet tempor? Nisi cursus lorem tincidunt penatibus eu scelerisque! Scelerisque mid rhoncus turpis eros? Nunc rhoncus in turpis, mus, nec augue, odio, mid tempor aliquam, ultricies. </div> </div>
The navigation is also slightly different. Since we have two different ways by which to filter the content, we’ll need two separate menus.
<div id="nav"> <ul id="month"> <li><a href="#" data-filter="*">All</a></li> <li><a href="#" data-filter=".june">June</a></li> <li><a href="#" data-filter=".july">July</a></li> <li><a href="#" data-filter=".august">August</a></li> </ul> <ul id="year"> <li><a href="#" data-filter="*">All</a></li> <li><a href="#" data-filter=".y2010">2010</a></li> <li><a href="#" data-filter=".y2011">2011</a></li> <li><a href="#" data-filter=".y2012">2012</a></li> </ul> </div>
There’s the menu for filtering the month, and the one for filtering the year. The data-filter attributes contain the class name by which the elements should be filtered.
CSS
Nothing to do here, carry on. The CSS is unchanged from the original isotope tutorial.
Jquery
We’ll rewrite the javascript from scratch here. First off, we’ll isotope the main container.
$(document).ready(function(){ var $container = $('#content'); $container.isotope({ filter: '*', animationOptions: { duration: 750, easing: 'linear', queue: false, } }); });
Now, all the boxes are “isotoped”. Let’s get to work on the code powering the rearranging.
When the user clicks on a link, something needs to happen.
$('#month a').click(function(){ var month = $(this).attr('data-filter'); $('#month').attr('data-active', month); reorder(); return false; });
When a link inside the “#month” div is clicked, that means the user wants to filter the posts according to a single month. So, we need to withdraw the value of the “data-filter” attribute to find out how exactly we need to filter the content. Now, we’ll create a “data-active” attribute to hold what month the content should be filtered by. Lastly, we call the reorder function, which we’ll create in a moment.
Very similar code can be used for the “year” links.
$('#year a').click(function(){ var year = $(this).attr('data-filter'); $('#year').attr('data-active', year); reorder(); return false; });
Same logic as for the “month” links. When a link is clicked, store its “data-filter” attribute in the “data-active” attribute.
Lastly, we need to create the “reorder” function. When this function is called, it will check the values of the “#month” and “#year” divs, combine them, and filter the content with them. How is it possible to combine them? Simple: jQuery can use the following syntax in selecting elements:
$('.class1.class2')
This selects any elements with both classes. Isotope can also do this.
function reorder(){ var month = $('#month').attr('data-active'); var year = $('#year').attr('data-active'); var filterString = month+year; $container.isotope({ filter: filterString, animationOptions: { duration: 750, easing: 'linear', queue: false, } }); }
This works in some cases, but there are some things this is missing. First of all, what if the user has only clicked a “month” link, but not a “year” link? The variable “filterString” will look something like this: “.julyundefined”. The “undefined” is there because the year hasn’t actually been defined yet, since a “year” link hasn’t been clicked yet.
So, to fix this:
if (typeof month === 'undefined') { month = ""; } if (typeof year === 'undefined') { year = ""; } var filterString = month+year;
This checks to see if each variable has been defined yet, and if it hasn’t, changes the variable’s value to “”, so isotope can filter properly even with only one link clicked.
The resulting function works better, but there are still some issues. If both “All” links are clicked, the “filterString” looks like this: “**”. That doesn’t work…
var filterString = month+year; if(filterString=="**"){ filterString = "*"; }
…But this fixes it.
Lastly, we just need to tell the container to reorder its content:
$container.isotope({ filter: filterString, animationOptions: { duration: 750, easing: 'linear', queue: false, } });
So, the resulting function looks like this:
function reorder(){ var month = $('#month').attr('data-active'); var year = $('#year').attr('data-active'); if (typeof month === 'undefined') { month = ""; } if (typeof year === 'undefined') { year = ""; } var filterString = month+year; if(filterString=="**"){ filterString = "*"; } $container.isotope({ filter: filterString, animationOptions: { duration: 750, easing: 'linear', queue: false, } }); }
With this code, you should be able to create combination filters on your site as well. That concludes this tutorial; I hope this helped in some way.