A Continuation of the Isotope Tutorial: Highlight the currently active link
May 20, 2012 | In jQuery, Tutorials |In web design, the navigation bar is crucial in telling the user where he is located. Usually, the user is further helped out by highlighting the currently active menu item. For example, if the user is on the “About Us” page, the “About Us” link in the navigation bar will be styled to look different. Unfortunately, if the site uses Isotope.js, the user won’t know what is currently being displayed. In this post, I’ll show how that can be fixed so that the user can have an excellent experience even on a site using Isotope.
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 we’ll use is identical to the code from the isotope tutorial you just downloaded, except for one small thing.
Add data-current=""
to the #content
div, so that the result looks like this:
<div id="content" data-current="">
We’ll be using this attribute to store the category that is currently being shown.
CSS
The CSS is exactly the same as from the isotope tutorial previously. No need to change anything here.
Javascript
We’ll rewrite the javascript code from the previous tutorial, as it has changed considerably.
First of all, make a nice $(document).ready
function:
$(document).ready(function(){ });
Now, we need to write the code that will “isotope” the boxes on the page.
var $container = $('#content'); var toFilter = '*'; $container.isotope({ filter: toFilter, animationOptions: { duration: 750, easing: 'linear', queue: false, } });
Here, the variable $container
is whatever container you want to isotope. The variable toFilter
is what the $container
is filtered by. The reason we have a variable for this is because later on in the code, we have to know what what $container
is filtered by. The rest of the code is isotope-specific, and is completely self-explanatory.
Remember that “data-current” attribute on the $container
? We’ll start to use it now.
$container.attr('data-current',toFilter);
This code sets teh “data-current” attribute to what the $container
was originally filtered by. This way, we can highlight the currently active navigation as soon as the page loads. More on that later.
We can now write the function that will determine what the $container
is currently being filtered by, which we’ll call “checkActive”.
function checkActive(){ $('#nav a').each(function(){ }); }
Inside the “checkActive” function, we have a .each function. This basically iterates over each element that matches the selector. In this case, the code inside the “each” function repeats itself for each #nav a
.
Now, take a look at the title of each nav link. Notice the fact that it doesn’t have a “.” at the beginning of it. This needs to be fixed before we can accurately compare the “data-current” attribute with the title of each nav link.
function checkActive(){ $('#nav a').each(function(){ var title = $(this).attr('title'); title = '.'+title; }); }
This takes the title attribute of the nav link the each function is currently iterating over, and adds a “.” to the beginnnig of it.
But wait! What if the title attribute is “*”, like in the link that says “All”?
function checkActive(){ $('#nav a').each(function(){ var title = $(this).attr('title'); title = '.'+title; if(title=='.*'){ title = '*'; } }); }
That fixes it.
In order to find out which link to highlight, we need to find out which category is currently being displayed.
function checkActive(){ $('#nav a').each(function(){ var title = $(this).attr('title'); title = '.'+title; if(title=='.*'){ title = '*'; } var currentCat = $container.attr('data-current'); }); }
Now, we can compare the two to find out whether the link the each function is currently on is the right one or not.
if(title==currentCat){ $(this).css({ color: '#00ff00' }); }
Here’s what we have so far:
function checkActive(){ $('#nav a').each(function(){ var title = $(this).attr('title'); title = '.'+title; if(title=='.*'){ title = '*'; } var currentCat = $container.attr('data-current'); if(title==currentCat){ $(this).css({ color: '#00ff00' }); } }); }
However, there’s a slight problem with this code: the links won’t return to their previous states if the active category changes. We can fix this by making a type of “reset” that will make all links the way they were originally, and then changing whichever one needs to be changed.
function checkActive(){ $('#nav a').each(function(){ $(this).css({ color: '#595959' }); var title = $(this).attr('title'); title = '.'+title; if(title=='.*'){ title = '*'; } var currentCat = $container.attr('data-current'); if(title==currentCat){ $(this).css({ color: '#00ff00' }); } }); }
We can now create the rest of the javascript code.
Here’s where we left off:
var $container = $('#content'); var toFilter = '*'; $container.isotope({ filter: toFilter, animationOptions: { duration: 750, easing: 'linear', queue: false, } }); $container.attr('data-current',toFilter); checkActive();
With this code, the “checkActive” function will fire right after the $container
is isotoped, and will highlight the “All” link.
Now, we need to make the nav links actually work.
$('#nav a').click(function(){ return false; });
This way, when a nav link is clicked, it won’t actually redirect the user to a different page.
In order to filter the $container
, we need to define a few variables.
$('#nav a').click(function(){ var title = $(this).attr('title'); var text = $(this).text(); return false; });
Now, we have to check with or not the link that was just clicked is the “All” link or not.
$('#nav a').click(function(){ var title = $(this).attr('title'); var text = $(this).text(); if(text == "All"){ var selector = title; } else { var selector = "." + title; } return false; });
Next, we need to set the “data-current” attribute of the $container
to reflect what it is being filtered by.
$('#nav a').click(function(){ var title = $(this).attr('title'); var text = $(this).text(); if(text == "All"){ var selector = title; } else { var selector = "." + title; } $container.attr('data-current',selector); return false; });
Now that we’ve defined what the $container
is currently being filtered by, we need to actually filter the $container
.
$('#nav a').click(function(){ var title = $(this).attr('title'); var text = $(this).text(); if(text == "All"){ var selector = title; } else { var selector = "." + title; } $container.attr('data-current',selector); $container.isotope({ filter: selector, animationOptions: { duration: 750, easing: 'linear', queue: false, } }); return false; });
After the $container
has been filtered, we have to run the “checkActive” function to highlight the currently active link.
$('#nav a').click(function(){ var title = $(this).attr('title'); var text = $(this).text(); if(text == "All"){ var selector = title; } else { var selector = "." + title; } $container.attr('data-current',selector); $container.isotope({ filter: selector, animationOptions: { duration: 750, easing: 'linear', queue: false, } }); checkActive(); return false; });
And there you have it: upon clicking a link in the navigation, it becomes different-looking so that the user knows what is currently being displayed. Now, you may wonder why we didn’t just make the link change color upon being clicked without worrying about the “data-current” attribute and all that. The reason is that this code works much more flexibly and with many other situations. For example, what if there’s a link inside the content of the page? All you need to do is modify the $('#nav a')
selector to include links inside the post, and when a link in the post is clicked that filters the content, the navigation changes to reflect that. Or, what if there’s another piece of code that needs to know what category is currently being displayed? You don’t even have to modify anthing! Just find out the “data-current” attribute of the $container
, and you’re done.
In other words, this code is highly flexible and adaptible, and not just this situation specific. I hope you learned something from this tutorial. If you have any questions or comments, feel free to use the comment form below.
Pingback: Anonymous