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.