Friday, March 4, 2011

Javascript Expandable Navagation Tree

A top level navigation menu is pretty common on the internet these days. You hover your mouse over a link and more pop down. These can be built entirely with CSS, because they aren't really dynamic. Yes, they do change when the mouse is hovered over, but both the hover and non-hover states are pre-built, and the browser displays them. Nothing in the page or code changes or is really affected by the user.

Javascript menus though, are more advanced. They can be affected by the user. This is why javascript is what I'm using to remake the section navigation menus on my website. I was inspired by the Blog Archive on Blogger. If you look at the trangles, you can click them, and it hides or shows more sub pages. What I didn't like though, is the fact that clicking the word beside the arrow also toggles the arrow. I want them to be separate. I looked for a while and found this method, which works very well. I adapted it for my website, changing the minor things like formatting. The only problem is that the posted script doesn't allow for control over the initial state.

Now, I don't really know much javascript. I'm good at interpreting code though, of any language. And it turns out, this is a pretty simple code, when you break it down. All it does is:

On the page load, it turns off the display of the submenus, setting menu to closed.
When you click, if menu is closed, it opens, and if menu is open, it closes.

$(document).ready(function()
{
$("#root ul").each(function(){ {$(this).css("display", "none");} });
$("#root .category").click(function()
{
var childid = "#" + $(this).attr("childid");
if ($(childid).css("display") == "none") {$(childid).css("display", "block");}
else {$(childid).css("display", "none");}
if ($(this).hasClass("cat_close")) {$(this).removeClass("cat_close").addClass("cat_open");}
else {$(this).removeClass("cat_open").addClass("cat_close");}
});
});

We don't want to mess with the clicking function. What we want to change is the begining part, that sets it all to closed when the page is loaded. Instead of setting all to closed, we want to set only some to closed. So, we add class="closed" to the sub menus we want closed, and then instead of $("#root ul").each(function(), we put in $("#root .closed").each(function(). root ul means all uls inside the root. But root .closed means, everything that we set the class="closed" to inside the root. IE, we control it instead of it doing everything. The new script becomes:

$(document).ready(function()
{
$("#root .closed").each(function(){ {$(this).css("display", "none");} });
$("#root .category").click(function()
{
var childid = "#" + $(this).attr("childid");
if ($(childid).css("display") == "none") {$(childid).css("display", "block");}
else {$(childid).css("display", "none");}
if ($(this).hasClass("cat_close")) {$(this).removeClass("cat_close").addClass("cat_open");}
else {$(this).removeClass("cat_open").addClass("cat_close");}
});
});

Success!
 

No comments:

Post a Comment