Ask your WordPress questions! Pay money and get answers fast! (more info)

How do I create a multi-tiered wp_nav_menu? WordPress

  • SOLVED

I'm in the middle of making my own theme, but I have run into some trouble. I'm using the new wp_nav_menu function, and I'm running WP 3.0.1.

As you might already know, wp_nav_menu is nesting the sub-menus into the parent ul. This seems to be the main problem. If I could find out how to write a custom walker that would output ONLY the active menu's sub-menu (if any), and output it below the parent menu, I could get this to work.

Here's how I want it to look:
http://www.alekstef.com/rot/Skjermbilde%202010-09-18%20kl.%2015.53.55.png

The menu you can see in the screenshot is achieved with alot of dirty CSS tweaking. As you can see, the page title is not affected by the sub-menu due to the position, which is set to absolute. That's the only way I get it to look the way I want. However, this does not work satisfactory in IE, and, like I mentioned, other items don't move according to it.

SO - to summarise: I need someone to (help me) write a custom wp_nav_menu walker that removes the nesting, puts every sub menu in its own div below the main menu, and shows only the active page's subpages in the menu.

I think that was all.. Be sure to ask if something is unclear, or if you have a question. Thanks in advance!

Best regards,
Aleksander Steffensen

Answers (10)

2010-09-18

Khanh Cao answers:

Not sure how are you going to deal with the CSS and jQuery but here is a quick and dirty walker to use with a 2-level menu:


class My_Walker extends Walker_Nav_Menu {

function walk( $elements, $max_depth) {

$tops = array(); // top level menu items
$subs = array(); // sub menu items

foreach ($elements as $element) {
if (0 == $element->menu_item_parent)
$tops[] = $element;
else
$subs[] = $element;
}

// group sub items by their parents
$real_subs = array();
foreach ($subs as $item) {
$real_subs[$item->menu_item_parent][] = $item;
}

// show top level elements
$s = '<ul id="tops">';
foreach ($tops as $item) {
$classes = join(' ', $item->classes);
$s .= "<li id='menu-{$item->db_id}' class='$classes'>{$item->title}</li>";
}
$s .= "</ul>";

// show sub menu items
foreach ($real_subs as $k => $items) {
$s .= "<ul class='hidden menu-$k'>";
foreach ($items as $item) {
$classes = join(' ', $item->classes);
$s .= "<li id='menu-{$item->db_id}' class='$classes'>{$item->title}</li>";
}
$s .= '</ul>';
}

return $s;
}
}


The output is:


<ul id="tops">
<li id="menu-527" class=" menu-item menu-item-type-">Parent 1</li>
<li id="menu-741" class=" menu-item menu-item-type-post_type">Parent 2</li>
<li id="menu-742" class=" menu-item menu-item-type-post_type">Parent 3</li>
<li id="menu-743" class=" menu-item menu-item-type-post_type">Parent 4</li>
</ul>

<ul class="hidden menu-527">
<li id="menu-738" class=" menu-item menu-item-type-post_type">Child 1-1</li>
<li id="menu-739" class=" menu-item menu-item-type-post_type">Child 1-2</li>
<li id="menu-740" class=" menu-item menu-item-type-post_type">Child 1-3</li>
</ul>

<ul class="hidden menu-741">
<li id="menu-786" class=" menu-item menu-item-type-post_type">Child 2-1</li>
<li id="menu-791" class=" menu-item menu-item-type-post_type">Child 2-2</li>
<li id="menu-793" class=" menu-item menu-item-type-post_type">Child 2-3</li>
</ul>



This gets the sub menu items of a top level item:

var menu_id = $('#top li:first-child').id(); // first item's id
var sub = $('.hidden').hasClass(id);


But it's up to you to arrange the menu items, this only shows how create a simple walker.


Aleksander Steffensen comments:

Thanks.

This is actually quite close. I would need it to output links, not only the names of the menu items... And it should only output the sub menu related to the currently active top-level page. Please note that I only want to list the sub-items that are added to the nav menu admin panel. Even if the parent page has sub-pages, I don't want them to show unless they are added as sub pages in the admin panel. This also means that if the current active menu item is a top level menu item with no sub-level items, the sub menu should not show at all.

If you can manage to do this, I'd be happy to select you as winner.

Just out of curiosity, when I look in the source when using this walker... The menu HTML is a total mess, but the WP standard actually looks quite good in the source when browsing. Don't take this the wrong way, it doesn't really mean that much, but.. Would have been nice if it was a bit more organised when looking at it in the source code. Quite a lot easier to do debugging...


Khanh Cao comments:

My bad, I thought you wanted to show all sub menu items and manipulate them with jQuery, here is a js-less version, it shows the top level menu items as a UL then another UL as the sub menu items of the current menu item:


class My_Walker extends Walker_Nav_Menu {

function walk( $elements, $max_depth) {

global $wp_query;
$current_page = (int) $wp_query->queried_object_id;

$tops = array(); // top level menu items
$subs = array(); // sub menu items
_wp_menu_item_classes_by_context($elements);

foreach ($elements as $element) {
if (0 == $element->menu_item_parent) {
$tops[] = $element;
if ($element->object_id == $current_page)
{
$current_parent = $element;
}
}
else
$subs[] = $element;
}

if ($current_parent) {
$real_subs = array();
foreach ($subs as $item) {
if ($item->menu_item_parent == $current_parent->db_id)
$real_subs[] = $item;
}
}

// show top level elements
$s = '<ul id="tops">';
foreach ($tops as $item) {
$s .= $this->display_item($item, $current_page);
}
$s .= "</ul>";

// show sub menu items
if (sizeof($real_subs) > 0) {
$s .= "<ul id='subs'>";
foreach ($real_subs as $item) {
$s .= $this->display_item($item, $current_page);
}
$s .= '</ul>';
}
return $s;
}

function display_item($item, $current_page) {
$classes = join(' ', $item->classes);
$item_url = strpos( $item->url, '#' ) ? substr( $item->url, 0, strpos( $menu_item->url, '#' ) ) : $item->url;
if (!$item_url)
$item_url = home_url();

$link = "<a href='$item_url'>{$item->title}</a>";
return "<li id='menu-{$item->db_id}' class='$classes'>$link</li>";
}
}


Aleksander Steffensen comments:

Thank you! We're closing in on it now, this is very close. There's just a few small things.

- When clicking on a sub-page, I want the sub-menu for the parent item to still show... It disappears now because the current item (sub-page item) does not have any sub-pages itself.

- Does the links have all the flexibility they need to, according to what you can do in the nav menu admin panel? Like alt, target etc?

- I don't know if you have seen the output, but there is being output one ul, in which the other two ul's are output. Like this:


<ul id="primary-navigation" class="horizontalnav">
<ul id="tops">
<!-- MENU ITEMS -->
</ul>
<ul id="subs">
<!-- SUBMENU ITEMS -->
</ul>


How do I get rid of the wrapping ul that Wordpress adds?


Khanh Cao comments:

This one should include menu attributes from the menu editor and show the sub menu items when a sub menu item is the current page. I don't know any good way to remove the default UL tag so I think it's best to either make the two menus into DIVs or wrap each of them with a LI:



class My_Walker extends Walker_Nav_Menu {

function walk( $elements, $max_depth) {

global $wp_query;
$current_page = (int) $wp_query->queried_object_id;

$tops = array(); // top level menu items
$subs = array(); // sub menu items
_wp_menu_item_classes_by_context($elements);

foreach ($elements as $element) {
if (0 == $element->menu_item_parent) {
$tops[] = $element;
if ($element->object_id == $current_page) {
$current_parent = $element;
}
}
else
{
$subs[] = $element;
if ($element->object_id == $current_page) {
$current_child = $element;
}
}
}

if (!$current_parent)
$current_parent = $this->get_current_parent_from_sub($elements, $current_child);

if ($current_parent) {
$real_subs = array();
foreach ($subs as $item) {
if ($item->menu_item_parent == $current_parent->db_id)
$real_subs[] = $item;
}
}

// show top level elements
$s = '<li><ul id="tops">';
foreach ($tops as $item) {
$s .= $this->display_item($item);
}
$s .= "</ul></li>";

// show sub menu items
if (sizeof($real_subs) > 0) {
$s .= "<li><ul id='subs'>";
foreach ($real_subs as $item) {
$s .= $this->display_item($item);
}
$s .= '</ul></li>';
}
return $s;
}

// get the parent page when a sub page is the current page
function get_current_parent_from_sub($elements, $current_child) {
foreach ($elements as $element) {
if ($element->db_id == $current_child->menu_item_parent) {
return $element;
}
}
return false;
}

function display_item($item) {
$i = '';
$this->start_el( $i, $item, 0, array() );
$this->end_el( $i, $item, 0, array() );
return $i;
}



Aleksander Steffensen comments:

Could you check the code once more? I get this syntax error:
<blockquote>
Parse error: syntax error, unexpected ';', expecting T_FUNCTION in /home/stmm/www-0012/wp-content/themes/koloyshytteutleie/functions.php on line 137</blockquote>

Line 137 is the last line, and contains "?>"


Aleksander Steffensen comments:

Nevermind. It was just missing a } closing the class at the end. Thanks you so much, it works fantastic! :)

2010-09-18

Baki Goxhaj answers:

I can achieve that through CSS, making IE happy too - would you like to hire me?


Aleksander Steffensen comments:

Hello.

I'm sorry, but I want a non-CSS solution for this :) Thanks anyway!


Baki Goxhaj comments:

Thanks and good luck with it :)

2010-09-18

Pau answers:

I think you don't need a custom walker for wp_nav_menu to achieve that. just css and javascript will do the trick. let me know if your interested


Aleksander Steffensen comments:

Thanks for your answer. You might be right, it might be possible with CSS and JavaScript, however I want a solution that is as "clean" as possible. It's possible that I'm too fixed on this, but.. yeah, that's my request :)


Pau comments:

if you want to hands-on with it, the easiest way is to follow this tutorial

[[LINK href="http://www.alistapart.com/articles/hybrid"]]http://www.alistapart.com/articles/hybrid[[/LINK]]

to form the menu and then, add a javascript to complete it:

ex. using jquery
jQuery(document).ready(function(){
jQuery('#access li ul').mouseover(function(){
if(! jQuery(this).parent().hasClass('on')){
jQuery(this).parent().addClass('on');
}
});
jQuery('#access li ul').mouseleave(function(){
if(jQuery(this).parent().hasClass('on')){
jQuery(this).parent().removeClass('on');
}
});
jQuery('#access ul > li > ul').each(function(){

jQuery(this).parent('li').addClass('off');

});

jQuery('#access ul > li > ul > li > ul').each(function(){

jQuery(this).parent('li').addClass('off');

});

jQuery('#access li.current_page_item, #access li.current_page_ancestor').each(function(){
jQuery(this).addClass('active');
});
});


hope this will give you a good start :)



Pau comments:

oh my bad. change the #access to #nav


Pau comments:

oh i forgot. it should be declared like this

<div id="nav">
<?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary' ) ); ?>
</div>

and just copy the css from

[[LINK href="http://www.alistapart.com/articles/hybrid"]]http://www.alistapart.com/articles/hybrid[[/LINK]]

then add the javascript code posted above


Pau comments:

Hello Aleksander,

This can't be done using CSS only. Possibly yes but will not look good in all major browsers especially on IE. You need a custom walker if you want DIV not UL for submenu but still you need CSS and JAVASCRIPT ( i prefer JQUERY ) to fully achieve a horizonal menu with horizontal submenu


Aleksander Steffensen comments:

Hello again!

Thank you for acknowledging that. That has been my opinion all along, although I am not quite sure if javascript/jQuery is necessary? Do you have a complete or partial solution?


Pau comments:

Yes i believe its necessary to keep it clean and make it compatible in all other browsers rather than using pure css which i doubt it will have a good looking menu in all major browsers.

i have coded a sample using CSS/JQUERY but submenu is not on DIV but in UL so you wont have to waste some time creating a walker

here have a look: [[LINK href="http://wpcrunchy.com/demo/?preview=1&template=testla&stylesheet=testla&"]]http://wpcrunchy.com/demo/?preview=1&template=testla&stylesheet=testla&[[/LINK]]

not yet complete though (active or selected page not yet coded)


Pau comments:

my bad again. here's the right link:

[[LINK href="http://wpcrunchy.com/demo/?wptheme=testla"]]http://wpcrunchy.com/demo/?wptheme=testla[[/LINK]]


Aleksander Steffensen comments:

Ok. In your example, the submenu doesn't hide as standard.. I suppose that's easy to achieve? Also, did you look at the attachment in my first post, just for reference?


Pau comments:

Yes i did. i just create a quick sample how you can achieve it using jquery and css. anyways, i just push the updates on the demo which i think this is what you want.

DEMO HERE: [[LINK href="http://wpcrunchy.com/demo/?wptheme=testla"]]http://wpcrunchy.com/demo/?wptheme=testla[[/LINK]]


Aleksander Steffensen comments:

Well, it's getting better... Now if you get the sub menu to show up on click, not hover...? And if there is content just beneath the menu, how will the content, for instance a page title, behave when the sub menu appears? Ideally it would be pushed down to maintain the space between menu and content.


Pau comments:

patch the javascript so it activate when click not hover. well, since submenu it set to absolute then it will just cover the content below and no space will be added

DEMO: [[LINK href="http://wpcrunchy.com/demo/?wptheme=testla"]]http://wpcrunchy.com/demo/?wptheme=testla[[/LINK]]

2010-09-18

Denzel Chia answers:

Hi,

I had taken a look at your attachment.

Are you trying to achieve the navigation as shown in this link?
http://users.tpg.com.au/j_birch/plugins/superfish/#sample4
click on the examples tab and nav-bar style tab to see the example.

If yes, you can use this superfish to style your menu, it works with wp_nav_menu()

If not I will try to write you a walker class.

Thanks.


Aleksander Steffensen comments:

Hello, and thank you for your answer!

The superfish-thing is close to what I want.. I want no drop-down menus, though. It might work ok like a backup-solution in case nothing else works out.

You're the only one who has actually offered to solve the problem the way I want to, so I'll take that. If you manage to write a walker that does what I want, that would've been awesome! :) Please ask if something is unclear regarding the functionality I requested.


Denzel Chia comments:

Hi,

If you want to use the superfish menu that I recommend,
There is no need to write a new walker for this.
As long as you tag only sub menu item to a parent item and no sub sub menu item,
The dropdown list will not appear.
What I mean is you tag only second level menu item in wordpress menu and the drop down will not appear.

<em><strong>If you want me to set up for you the whole menu in your theme, you can email a zip copy of your theme to me. I can setup it up the menu system for you.</strong></em>

You can find my website and contact in my profile page.
http://www.wpquestions.com/user/profile/id/1709

Members are not allow to post their contact email here.

Hope you understand.

Thanks.


Denzel Chia comments:

By the way,

You don't need to pay me if it don't work.

Let me code it into your theme, if it works, then you select my answer and pay me,
If it don't, you get someone else to help. :)

Thanks.


Aleksander Steffensen comments:

Hi.

Like I said to the others, I'm not really interested in a jQuery/CSS solution. It would have to be a last resort. Thank you, though.


Denzel Chia comments:

What I told you is to use wp_nav_menu(),
So that you can set up your theme menu in wordpress admin easily.
wp_nav_menu will print out a list of your menu on you theme,

Then you use jQuery superfish, including its CSS to style it to the menu you want.

There is no walker that can style your menu without the help of at least CSS!
PHP is server side, javascript, css, html is client side. You use javascript or css to style elements.

Maybe you can write a walker with inline css to style the menu, but you still need inline css!

I doubt you know anything about programming.

Thanks and I would not waste my time here anymore.


Aleksander Steffensen comments:

Denzel,

I did not mean to upset you. I know a thing or two about programming, and of course I will need to style the menu using CSS. I will not, however, use dirty CSS solutions that is posted here by some, to make it look good.

What I need is for someone to change the way the menu is output. No nesting of ul's! Only one sub-menu should be shown at a time, and it would have to be in an own div beneath the main menu.

I do not want to use the superfish-thing, as I'd prefer staying away from plugins and stuff like that, AND I don't want jQuery-stuff on this website.


Aleksander Steffensen comments:

What I meant to say is, I will not use dirty CSS fixes to help place the menus correctly when this can and should be done by changing the HTML-output.


Denzel Chia comments:


<blockquote>I do not want to use the superfish-thing, as I'd prefer staying away from plugins and stuff like that, AND I don't want jQuery-stuff on this website.</blockquote>

You rejected my proposal on using jQuery Superfish, but you accepted akosipau's demo?
Oh come on, view the source! Its what I am offering to do for you! wp_nav_menu styled by jQuery superfish!

Well thought you said you know programming and insist on not using jQuery stuff!
Come on, you should be fair!


Aleksander Steffensen comments:

Yes, I almost gave in, but I'm not going to. I'm sorry if I was being unfair, there's just so many proposals and so few of them actually is what I want. Looks like someone's finally getting there, though. Thanks for your efforts!

2010-09-18

Nilesh shiragave answers:

Hi

Yes possible with some css and jquery.
just send me design colors which you want i will create code using wp_nav_menu compatible with IE,mozilla,chrome,safari.

Give me some time i will give you all the code..

Thanks
:)


Aleksander Steffensen comments:

Thanks for your answer. I've decided to go for a non-css/jQuery solution if this is possible. :)


Nilesh shiragave comments:

Yes but how you can show sub pages hide show without jquery or any javascript library or CSS. I have a code which works perfect using jquery and CSS.


Nilesh shiragave comments:

In one answer you are saying you dont want CSS/jquery and in other answer you are looking to use jquery superfish code.


Nilesh shiragave comments:

Final output will be similar to this..

http://css-trends.com/demo/horizontal_menu/


Aleksander Steffensen comments:

Not really. I said it <em>might</em> be an acceptable backup solution. I'm not looking to use jQuery superfish code.


Aleksander Steffensen comments:

In the example you posted, the sub-menu disappears when trying to hover over the sub-menu items...


Nilesh shiragave comments:

Sorry, yes you was right there was some CSS issues. as this is still not final code..

Just clarify. you want to use wp_nav_menu() and in second div you want to show all the subpages added to the current page in menu or you want to display all the child pages for that current page.

as you can display all the child pages of current page using wp_list_pages()

just add this code in second div

<?php
wp_list_pages("title_li=&child_of=".$post->ID."&echo=0$sort_column=menu_order");
?>


Aleksander Steffensen comments:

Thanks. I'm aware of this solution, but I want a wp_nav_menu-only solution, if you understand?

The sub-menu (/second div) is supposed to show the sub pages / child pages of the current page.

2010-09-18

Pippin Williamson answers:

It seems as though Sushicodeur, over in the WordPress forms has already done this:

[[LINK href="http://wordpress.org/support/topic/wp_nav_menu-list-only-2nd-level-separate-submenu?replies=23"]]http://wordpress.org/support/topic/wp_nav_menu-list-only-2nd-level-separate-submenu?replies=23[[/LINK]]

His code might take a little bit of modification, which I'd be happy to help you with, but it's a really good start.


Pippin Williamson comments:

Make sure you read all the way through that forum post as there are a lot of little tweaks throughout.


Aleksander Steffensen comments:

Thank you.

I've actually seen that thread in the WP forums, but like the PHP-novice I am, I did not know what to do with it.

I feel like it would be unfair if I didn't give Mr. Chia a chance first, so I will definitely come back to you if it doesn't work out.


Pippin Williamson comments:

Sounds great. Let me know and I'll work with you to get it all setup.


Aleksander Steffensen comments:

Hello again. I'd appreciate your help. Before we start, is anything vague, or do you understand exactly what I want?


Pippin Williamson comments:

I'm a little iffy on the exact structure you need. Could you outline it? Is the sub menu suppose to be inside of its own div within the main menu ul?


Aleksander Steffensen comments:


<div id="nav-container">
<div class="main-menu">
<ul class="horizontalnav primarynav strong">
<li><a href="#">Hjem</a></li>
<li><a href="#">Hytter</a></li>
<li><a href="#">Bilder</a></li>
<li><a href="#">Priser</a></li>
<li><a href="#">Booking</a></li>
<li><a href="#">Informasjon</a></li>
<li><a href="#">Ofte stilte spørsmål</a></li>
<li><a href="#">Kontakt</a></li>
</ul>
</div>

<div class="sub-menu">
<ul class="horizontalnav secondarynav">
<li><a href="#">Panorama</a></li>
<li><a href="#">Irenes</a></li>
<li><a href="#">Kapteinens</a></li>
</ul>
</div>
</div>


Something like this is the ideal output :) Unlike the standard walker, which outputs everything (and uses CSS and/or jQuery to hide the other sub-pages), I want this to only output one sub-menu at a time. I hope that covers your questions.


Aleksander Steffensen comments:

So basically, in the code I just posted, the sub-menu div contains the sub-pages of the "Hytter"-page, which is linked to in the main menu.


Pippin Williamson comments:

I'm not really sure why you don't do it with CSS? I know you've said you don't want to, but there is no reason not to. I can give you a solution that is perfectly clean and works great.


Pippin Williamson comments:

The site that Ryan Riatno gave is done purely with CSS and the regular menu structure.


Aleksander Steffensen comments:

Well, I've tried for days to do it with CSS without getting it to work satisfactory in IE. I'd really prefer the custom walker solution.. I realise I'm being extremely picky, but the "job" description is pretty clear to me. And I'm not sure if I want to spend $70 on some CSS fix...

How about this, if you manage to do it, if it looks good, and everything works like it's supposed to, you have me convinced.


Aleksander Steffensen comments:

Oh, and one more thing.. The sub-menu is not supposed to be shown when there is no sub pages. It needs to disappear, and the content will have to move upwards accordingly.


Pippin Williamson comments:

So unlike the WooTheme's link, you do not want the sub menu container present at all times. Correct?


Aleksander Steffensen comments:

That is correct :)


Pippin Williamson comments:

I've made everything work except the "move the content down", which I"m sure could be accomplished with jQuery, but I'm no jQuery guru;)

Would you like the code or are you going with a different solution?


Aleksander Steffensen comments:

I appreciate your efforts, that goes for all of you.

You're about as far as I got, except you got it looking good in IE... I still need the content to move according to the menu, or the title will be partly hidden. I can accept a CSS solution that works in all major browser, but I really want to stay away from jQuery on this website, for several reasons.

Thanks for understanding, and let me know if you find a solution.

2010-09-18

Utkarsh Kukreti answers:

Add this code to functions.php

function my_custom_nav($items) {
global $wp_query;
$queried_id = $wp_query->queried_object_id;
$child_items = array();
$parents = array();
foreach( $items as $key => $item )
{
if( $item->object_id == $queried_id )
$parents[] = $item->ID;
if( in_array($item->menu_item_parent, $parents) )
$child_items [] = $item;
}
return $child_items;

}

function enable_custom_nav() { add_filter('wp_get_nav_menu_items', 'my_custom_nav'); }
function disable_custom_nav() { remove_filter('wp_get_nav_menu_items', 'my_custom_nav'); }



This to your theme header

<?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'depth' => 1 ) ); ?>
<br/>
<?php enable_custom_nav() ?>
<?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary' ) ); ?>
<?php disable_custom_nav() ?>


It'll output one Top Level menu, and if a menu item is selected, all its child menu items in a separate div.

2010-09-18

Tobias Nyholm answers:

No problem. I can do it with some regex.

Send me the theme source code and I can write a regex that works for you.


Aleksander Steffensen comments:

Would you care to elaborate what your solution is all about? :)


Tobias Nyholm comments:

sure, sorry.

I'll get the menu content from the wp_nav_menu. Then I "search" with regex to extract the submenu.
Then I echo/return the menu with a wrapper and later the submenu with an other wrapper.

As far as I know, you don't what the submenu to show when you hover a top menu item, right? You what the submenu to show when you are at a particular page?

If not, I'm afraid that superfish or some other nasty jQuery/CSS is your solution...


Aleksander Steffensen comments:

Thank you.

There's kind of a "line" of people waiting their turn to help, lol.. So I'd have to get back to you if the other "candidates" fail. :)

2010-09-18

Ryan Riatno answers:

The output should be like this[[LINK href=" http://www.woothemes.com/demo/?name=crisp "]] http://www.woothemes.com/demo/?name=crisp [[/LINK]]?


Aleksander Steffensen comments:

Yes - without the jQuery-thingy :) How is this made? CSS/jQuery only, or via a custom walker?


Ryan Riatno comments:

Well, unfortunately this is only use the simple wp_nav_menu and jQuery.
Here's the code:
Functions:
if ( function_exists('wp_nav_menu') ) {
add_theme_support( 'nav-menus' );
register_nav_menus( array( 'primary-menu' => __( 'Primary Menu' ) ) );
}

The Output:
wp_nav_menu( array( 'depth' => 6, 'sort_column' => 'menu_order', 'container' => 'ul', 'menu_id' => 'main-nav', 'menu_class' => 'nav fl', 'theme_location' => 'primary-menu' ) );
jQuery :

jQuery(document).ready(function(){

//NAVIGATION - Keep parent item highlighted while hovering dropdown

jQuery('.nav li ul').mouseover(function(){

if(! jQuery(this).parent().hasClass('fake')){
jQuery(this).parent().addClass('fake');
}

});
jQuery('.nav li ul').mouseleave(function(){

if(jQuery(this).parent().hasClass('fake')){
jQuery(this).parent().removeClass('fake');
}
});

//NAVIGATION - Display second level menu for current page

jQuery('.nav > li.current_page_item > ul, .nav > li.current_page_ancestor > ul').css('left', '75px');

jQuery('.nav > li:not(.current_page_item,.current_page_ancestor)').mouseover(function(){
//alert('what');
jQuery('.nav > li.current_page_item > ul, .nav > li.current_page_ancestor > ul').css('left', '-9999px');
});


jQuery('.nav > li:not(.current_page_item,.current_page_ancestor)').mouseout(function(){
//alert('what');
jQuery('.nav > li.current_page_item > ul, .nav > li.current_page_ancestor > ul').css('left', '75px');
});

//NAVIGATION - Sub-nav indicator

jQuery('.nav > li > ul').each(function(){

jQuery(this).parent('li').addClass('has-dropdown');

});

jQuery('.nav > li > ul > li > ul').each(function(){

jQuery(this).parent('li').addClass('has-sub-dropdown');

});

});


I know it's not what you want to achieve, but at least you don't need the complex custom walker to make this thing work :)

2010-09-18

Duncan O'Neill answers:

Why not just make your current theme a child theme of the default Twenty-Ten theme? Then you have all the functionality you need already built in for the multi-tiered menu.

Creating a child theme is fairly easy;

http://codex.wordpress.org/Child_Themes

You should be able to make some simple alterations to your current styles.css to call in Twenty-Ten as the default theme, and over-ride Twenty-Ten's css with your own.

Then it's just a matter of adding some css rules to show the current menu item's children, rather than hide them and show them on hover;

For example, this in your style.css will show the current menu item's children;

#access ul li.current_page_item ul {
display:block;
}

Then it's just a matter of stopping the hover over other menu items showing their child lists. This should be fairly easily achieved, using either css, or by turning off the relevant javascript.

Let me know if you want to further explore this route.

regards,

Duncan