How to Dynamically Add a Selected Class to a Sub-menu

Published  December 18th, 2010

I haven't created any blog-worthy code contributions in Rails yet (hopefully soon), but I have something that I think is pretty cool to help people who have multi-level, navigation menu user interfaces...say that tens time fast. It's common UX practice to inform the user what page they are on through some sort of visual mechanism - i.e. you're on the 'Contact Us' page and the 'Contact Us' link is underlined or styled in a way that differentiates itself from other navigational items. This is simple to accomplish in Rails. You can set a variable in your controller and pass it down to your view to discern the current page. Then it's as simple as attaching a {:class => selected_class} on your anchor tag where selected_class is the variable set in your controller. Simple enough. What about when you have sub-menus that contain individual links there as well? Well, you can keep passing down the current page from your controller to your view, but at a certain point your navigation menu code becomes scattered with duplicative logic. I believe I've found a simple solution to this.

The first image is part of our in-house metrics navigation menu. The second image is an expanded view of the sub-menu that lies within each top-level menu item. Each top-level menu item has its own controller, which passes down the variable selected_class to layout view, where the navigation lives. I do a simple check above each top-level menu item to determine which controller I'm currently working with.
It looks like this:

The class 'active' is a style set in the CSS to differentiate your top-level item from the others. Now to set an additional style to whichever sub-menu item is currently also selected (as shown with the green background of 'Avg Star'), I wrote a simple jQuery function to scrape the current page's URL and check it against all the sub-menu anchor tags and their href attribute values. Once it finds the sub-menu item with the same href value as the current URL, I add a class onto the element.
The code looks like this:

There are three blocks of code that run on DOM ready. The first is a .click() handler that reveals the sub-menu hiding below each top-level navigation item. The second is a command that does what the first handler does for the currently selected top-level navigation item (that was set by selected_class). The last finds the currently selected top-level item and looks through it's sub-menu to place the additional .active class for the specific page we're on.
For some context, here is what the source HAML code looks like:

Hopefully that was straightforward enough to understand. I know it's pretty dry, but maybe you can think of another use for the code or be inspired to create something better. If you have questions or can think of a more efficient way, shoot me an email (dan@thredup.com).

Also, if you're a Ruby on Rails developer or an ambitious programmer looking to learn Rails, check out our jobs page or drop us a note at jobs@thredup.com. I've been working here for a little over 3 months now and I can honestly say that the grass over here is at green as it looks.