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

wp_nav_menu() walker function needed

  • SOLVED

Hi,

I am wanting the solution similar to the top question posted here: [[LINK href="http://wordpress.stackexchange.com/questions/2802/display-a-portion-branch-of-the-menu-tree-using-wp-nav-menu"]]http://wordpress.stackexchange.com/questions/2802/display-a-portion-branch-of-the-menu-tree-using-wp-nav-menu [[/LINK]]

I am using Wordpress 3.2.1

I have tried all the posted solutions and none of them work. Any ‘walker’ solutions do not seem to work, the menu displays incorrectly, and when trying to create the solution via css ‘display: none;’ when a Sub Page is clicked, the children of all the Sub Pages are shown, I am unable to hide specific child pages and only show the children relating to the current page.
You can see my website (in development) here: [[LINK href="http://www.alexanderb.org/championslifeacademy/internship/"]]http://www.alexanderb.org/championslifeacademy/internship/[[/LINK]]

You will see there is a top navigation with the following:

• Internship
• About Us
• How To Apply
• Contact Us

This is set as a menu (appearance / menu) with ‘automatically add new top-level pages’ selected.
I then have individual menus created for each ‘top-level’ page. Using the plugin ‘Add Descendants As Submenu Items’ I manually add the top-level page into each menu and select the ‘Automatically add all descendants as submenu items’ on this item.

I will use an IF statement to show the correct menu dependant on which page ID or page Parent ID the page equals to.

The ‘Internship’ menu is as follows (and can be seen on the page currently – ignore the styling as this is being created at the moment):

• Internship
- Charities
- Progression
- Junior Manager
- A Day In The Life of a JM
- CV of a JM
- Training
- Sales School
- Pay Structure and Living Arrangements

Each item refers to a page that has the parent or ancestor of ‘Internship’.

These pages are created by the user and so the solution must be dynamic, i.e. taking new pages into account and including them or excluding them in the menu.

I want to be able to display the child links of the current page (if it has any) as well as the ancestor tree reaching the top-level. I do not, however, want to show any other children of other pages on the same level. For examples please see the following (I have commented what pages should be hidden in brackets as well as what page the example relates to):

• Internship (on this page)
- Charities
- Progression
- Junior Manager (hidden)
- A Day In The Life of a JM (hidden)
- CV of a JM (hidden)
- Training
- Sales School (hidden)
- Pay Structure and Living Arrangements

• Internship
- Charities(on this page)
- Progression
- Junior Manager (hidden)
- A Day In The Life of a JM (hidden)
- CV of a JM (hidden)
- Training
- Sales School (hidden)
- Pay Structure and Living Arrangements

• Internship
- Charities
- Progression (on this page)
- Junior Manager
- A Day In The Life of a JM (hidden)
- CV of a JM (hidden)
- Training
- Sales School (hidden)
- Pay Structure and Living Arrangements

• Internship
- Charities
- Progression
- Junior Manager (on this page)
- A Day In The Life of a JM
- CV of a JM
- Training
- Sales School (hidden)
- Pay Structure and Living Arrangements

• Internship
- Charities
- Progression
- Junior Manager (hidden)
- A Day In The Life of a JM (hidden)
- CV of a JM (hidden)
- Training (on this page)
- Sales School
- Pay Structure and Living Arrangements

From my reading I think I need a ‘walker’ creating to resolve this. Any help would be very much appreciated!

Thanks in advance!

Answers (4)

2011-12-29

Hai Bui answers:

Hi,

I think the easiest solution is using css. Please try this:


#left_nav_main .menu > li > .sub-menu li li {
display:none;
}
#left_nav_main .menu > li > .sub-menu li.current_page_item, .menu > li > .sub-menu li.current_page_item > ul > li {

display:block;
}
#left_nav_main .menu > li > .sub-menu li.current-page-parent, .menu > li > .sub-menu li.current-page-parent > ul > li {
display:block;
}


AlexanderBell comments:

Hi,

I have added this and uploaded (http://www.alexanderb.org/championslifeacademy/internship/) but as you can see, only the top-level 'internship' and its children are displayed.

Have you any further ideas?

Thanks.


Hai Bui comments:

I think the css is overriden by some other rule. Try adding !important to the css rules:

#left_nav_main .menu > li > .sub-menu li li {
display:none;
}

#left_nav_main .menu > li > .sub-menu li.current_page_item, .menu > li > .sub-menu li.current_page_item > ul > li {
display:block !important;
}

#left_nav_main .menu > li > .sub-menu li.current-page-parent, .menu > li > .sub-menu li.current-page-parent > ul > li {
display:block !important;
}


Hai Bui comments:

I'm sorry, I made some typos in the last answer, please try this:

#left_nav_main .menu > li > .sub-menu li li {
display:none;
}

#left_nav_main .menu > li > .sub-menu li.current_page_item,#left_nav_main .menu > li > .sub-menu li.current_page_item > ul > li {
display:block;
}

#left_nav_main .menu > li > .sub-menu li.current-page-parent, #left_nav_main .menu > li > .sub-menu li.current-page-parent > ul > li {
display:block;
}


AlexanderBell comments:

Works perfectly with '!important'

Thank you so much, you don't know how long I've been trying to resolve this!!!

Thanks!

2011-12-29

Francisco Javier Carazo Gil answers:

Hi Alexander,

There are some options. The first one, the most primitive is create more than one menu. You create a menu for each case.

The second one is not using wp_nav_menu() and if you want to show only pages, use an adapted version of wp_list_pages() with his own conditional:


if(is_page(100)) {
wp_list_pages('title_li=&sort_column=menu_order&exclude='20,21');
} else {
wp_list_pages('title_li=&sort_column=menu_order&exclude='30');
}


Hope it helps! You can also do a function making your own queries into DB but this solution is not simple and you can have the same result with this two.


AlexanderBell comments:

Thank you for your answer, using wp_list_pages is ok and I have briefly looked into this but I need the menus to be dynamic, hence the use of the plugin 'Add Descendants As Submenu Items', so that when the user creates a new page and thus adding it to one of the menu's, it is excluded or displayed as per my requirements.

Thanks.


Francisco Javier Carazo Gil comments:

Alexander,

Then, the perfect solution is doing it from zero with your own queries. We will have to study which data "Add Descendants As Submenu Items" save and then use wp_list_pages() or a new function to create what you want.


AlexanderBell comments:

Thank you for your response. Could you expand upon how I might do this?

Thanks again.


Francisco Javier Carazo Gil comments:

Hi,

Use WPDB to do SELECT queries with wp_post and wp_post_meta. The data is placed in:

wp_post:
* post_type: should be nav_menu_item
* menu_order: his menu order

wp_post_meta:
* for a nav_menu_item with a post_id you have a wp_post_meta row with his parent: _menu_item_menu_item_parent

If you know where are you place, you can know which nav_menu_item is the current one and only show the ones you want depends on this with the hierarchy.

2011-12-29

She Codes answers:

Hi Alexander!

I think it could be solved using only css. I have done it before, with only 3 levels of pages though.

Please, try adding the following to your css:

#menu-internship li { display:none; }

#menu-internship .current_page_ancestor,
#menu-internship .current_page_item { display:block; }


She Codes comments:

Also you should change this style

.icon_displace { ... }

to

left:-1000px;

Something bigger than -500px, because I am on 23" monitor and I can see the texts of the icon links on the left of my screen.


AlexanderBell comments:

Hi,

Thanks for your response. Unfortunately the css you provided only shows the very top-level 'Internship' link.

I played around with adding 'li' or 'li li' into your css suggestion but nothing worked.

Thanks.

2011-12-29

victor answers:

try it

#left_nav_main .menu > li > .sub-menu li ul li {

display:none;

}



#left_nav_main .menu > li > .sub-menu li.current_menu_item,#left_nav_main .menu > li > .sub-menu li.menu_page_item > ul > li {

display:block;

}



#left_nav_main .menu > li > .sub-menu li.current-menu-parent, #left_nav_main .menu > li > .sub-menu li.current-menu-parent > ul > li {

display:block;

}