Creating an animated, filterable grid of items using Shuffle.js (a free alternative to Isotope, Masonry and Quicksand)

30 July 2013, Danny Connell

For a recent project, I had to create an animated, filterable grid of staff member's photo profiles (in the style of Isotope, Masonry and Quicksand).

I wanted a free solution. Masonry and Quicksand are free, and I spent a lot of time with these but had trouble setting them up. After some Googling and experimenting I found a very simple solution using the amazing jQuery plugin shuffle.js.

Check out the demo page below then I'll explain how I built it.

View demo page | Download demo page

HTML

The only dependencies we need to include are jQuery and shuffle.js:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="jquery.shuffle.min.js"></script>

Next we need some markup for the filters (that the user clicks to rearrange the grid) and the grid of items:

<ul id="filter">
<li><a class="active" href="#" data-group="all">All</a></li>
<li><a href="#" data-group="red">Red</a></li>
<li><a href="#" data-group="green">Green</a></li>
<li><a href="#" data-group="blue">Blue</a></li>
<li><a href="#" data-group="numbers">Numbers</a></li>
<li><a href="#" data-group="letters">Letters</a></li>
<li><a href="#" data-group="square">Squares</a></li>
<li><a href="#" data-group="circle">Circles</a></li>
</ul>

<div id="grid">
<div class="item blue"  data-groups='["all", "numbers", "blue", "square"]'>3</div>
<div class="item green" data-groups='["all", "numbers", "green", "square"]'>5</div>
<div class="item blue"  data-groups='["all", "letters", "blue", "square"]'>D</div>
<div class="item red"   data-groups='["all", "numbers", "red", "square"]'>1</div>
<div class="item red circle"   data-groups='["all", "numbers", "red", "circle"]'>4</div>
<div class="item red"   data-groups='["all", "numbers", "red", "square"]'>7</div>
<div class="item green circle" data-groups='["all", "numbers", "green", "circle"]'>8</div>
<div class="item red"   data-groups='["all", "letters", "red", "square"]'>B</div>
<div class="item green" data-groups='["all", "numbers", "green", "square"]'>2</div>
<div class="item green circle" data-groups='["all", "letters", "green", "circle"]'>C</div>
<div class="item blue"  data-groups='["all", "numbers", "blue", "square"]'>9</div>
<div class="item red"   data-groups='["all", "letters", "red", "square"]'>E</div>
<div class="item blue circle"  data-groups='["all", "letters", "blue", "circle"]'>G</div>
<div class="item blue"  data-groups='["all", "letters", "blue", "square"]'>A</div>
<div class="item blue"  data-groups='["all", "numbers", "blue", "square"]'>6</div>
<div class="item green" data-groups='["all", "letters", "green", "square"]'>F</div>
</div>

Note the data-group attribute on each filter link. This states which group of items should be shown when the user clicks that filter (e.g. red, green, square, circle).

The data-groups attribute on each grid item tells us which groups each item belongs to.

CSS

Next I add some CSS to style up the filters and grid items:

#container {width: 960px; margin: 0 auto;}

#filter {list-style-type: none; margin: 0; padding: 0}
#filter li, #filter a {display: block; float: left; margin: 0}
#filter a { background: #ddd; border: 1px solid #666; text-decoration: none; padding: 5px 10px;}
#filter a.active {background: yellow;}

#grid {clear: both; position: relative}
.item {width: 230px; height: 230px; background: grey; float: left; margin-right: 10px; margin-bottom: 10px; color: #fff; font-size: 60px; text-align: center; line-height: 230px; cursor: default;}
.red {background: red;}
.green {background: green;}
.blue {background: blue;}
.circle {border-radius: 230px;}

JavaScript

The JavaScript begins by initializing the shuffle plugin:

$(document).ready(function() {

/* initialize shuffle plugin */
var $grid = $('#grid');

$grid.shuffle({
itemSelector: '.item' // the selector for the items in the grid
});

});

The itemSelector option tells the plugin which elements are the grid items.

Now to make the grid rearrange when the user clicks on a filter item:

$('#filter a').click(function (e) {
e.preventDefault();

// set active class
$('#filter a').removeClass('active');
$(this).addClass('active');

// get group name from clicked item
var groupName = $(this).attr('data-group');

// reshuffle grid
$grid.shuffle('shuffle', groupName );
});

When the filter item is clicked, first we set the active class so the user can see which filter is currenly active (lines 5 and 6).

Next we grab the group name from the aforementioned data-group attribute.

Finally we reshuffle the grid by passing the plugin the group name (line 12).

Simples!

View demo page | Download demo page

Read more

Create a "Give me directions" button using jQuery and HTML5 Geolocation

17 May 2013, Danny Connell

An upcoming mobile website required the inclusion of a "Give me directions" button. I.E. a button that the mobile user can click to see directions from their current location to a given destination.

Here is my simple custom solution.

View demo page | Download demo page

HTML

Firstly, I added a button to the page for the user to click:

<a href="#" class="get-directions">Give me directions to Reading Room Manchester</a>

JavaScript

I included jQuery, and began by creating variables for the starting location and destination:

$(document).ready(function() {

var startingLocation;
var destination = "reading+room+manchester"; // replace this with any destination

});

Next I attach a click event to my button:

$('a.get-directions').click(function (e) {

});

Within this click function, I use HTML5 geolocation to calculate the user's latitude and longitude, combine these two values into a string, and send the starting location and destination to a function:

// check if browser supports geolocation
if (navigator.geolocation) {

// get user's current position
navigator.geolocation.getCurrentPosition(function (position) {

// get latitude and longitude
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
startingLocation = latitude + "," + longitude;

// send starting location and destination to goToGoogleMaps function
goToGoogleMaps(startingLocation, destination);

});

}

Finally, within the goToGoogleMaps function, I send the user to Google Maps, along with the query needed to get the directions:

// go to Google Maps function - takes a starting location and destination and sends the query to Google Maps
function goToGoogleMaps(startingLocation, destination) {
window.location = "https://maps.google.co.uk/maps?saddr=" + startingLocation + "&daddr=" + destination;
}

Fallback for browsers without Geolocation

What if the user's browser doesn't support Geolocation? Or they selected 'no' to the prompt asking to use their location? I wanted it to still work. Upon clicking the button, the user would be presented with a warning, along with a text input. The user could then manually enter their postcode, click the button and still get directions.

Here is the HTML for the warning and input (this is hidden by default in the CSS):

<div class="no-geolocation">
<p class="warning">Your browser does not support Geolocation. Please enter your postcode and click the button again.</p>
<input type="text" placeholder="Enter postcode or address" class="manual-location">
</div>

And here is the JavaScript for the fallback:

// get manually entered postcode
startingLocation = $('.manual-location').val();

// if user has entered a starting location, send starting location and destination to goToGoogleMaps function
if (startingLocation != '') {
goToGoogleMaps(startingLocation, destination);
}
// else fade in the manual postcode field
else {
$('.no-geolocation').fadeIn();
}

View demo page | Download demo page

Read more