Traversing the DOM is pretty easy with jQuery selectors and methods. A simple nested menu can be also traversed with a custom jQuery walker object which associates a particular action to every list items that, in turn, contains a sublist. The animation will simply hide or show the submenu.
We start with the following nested HTML structure:
<ul id="tree">
<li>
<a href="#">Item</a>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</li>
<li>
<a href="#">Item</a>
<ul>
<li>
<a href="#">Item</a>
<ul>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</li>
<li>Item</li>
<li>Item</li>
</ul>
</li>
</ul>
As you can see, the only elements we're interested in are the hyperlinks and the sublists. You can notice that some of these links are followed by a nested list in the DOM tree. So we can say that we're only interested in those links followed by an unordered list.
We can hide these sublists with a simple CSS declaration. Then we need to iterate over all links and trigger a click event only when a link has a list as its next sibling in the DOM tree:
var MenuTree = {
collapse: function(element) {
element.slideToggle(600);
},
walk: function() {
$('a', '#tree').each(function() {
var $a = $(this);
var $li = $a.parent();
if ($a.next().is('ul')) {
var $ul = $a.next();
$a.click(function(e) {
e.preventDefault();
MenuTree.collapse($ul);
$a.toggleClass('active');
});
}
});
}
};
MenuTree.walk();
Our check is as the following:
if ($a.next().is('ul')) {
}
The is() method checks whether an element matches a given jQuery selector. In this case we make sure that the next sibling of a link is an unordered list. In that case, then, we associate an action to the targeted link.
You can see the above code in action on this page.