10 Feb, 2009
Show subnavigation for just the main nav/section you're in (WordPress)
Posted by: Jennifer In: WordPress|WordPress Hacks
When you use wp_list_pages() – you get a full dump of everything. If you restrict the depth, then you might not be showing the child / subpages under each page.
The code I have below will first list only the "main nav" (parent) pages. If you click on one of the main nav / (parent) pages and it has children pages – then it will list ALL subpages under that parent page (including if there are multiple parent/child pages under it – it will list all of them). So for example…
If this is your page structure:
- Home
- About Us
- Who we are
- What we do
- Why you want to hire us
- Our prices
- Our people
- Our philosopy
- Contact Us
- Map to our offices
- Phone Numbers
- Contact Form
So this would first list just the main nav items – Home, About Us, and Contact us. Like this:
- MAIN NAV (you can change/remove this – just put it here for explanatory purposes)
- Home
- About Us
- Contact Us
Once you click on About us – all the subnav under about us is revealed in a separate list below the main nav items – and will stick around for as long as you're in an "about us" page. Kind of like this:
- MAIN NAV (you can change/remove this – just put it here for explanatory purposes)
- Home
- About Us
- Contact Us
- SUB NAV FOR: About Us
- Who we are
- What we do
- Why you want to hire us
- Our prices
- Our people
- Our philosopy
<ul>
<?php wp_list_pages('title_li=<h2>MAIN NAV</h2>&depth=1' ); ?>
</ul>
<?php
if ($post->post_parent == 0) {
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
$parentpage = $wpdb->get_row("SELECT ID, post_title, post_name FROM $wpdb->posts WHERE ID = '".$post->ID."'");
}
if ($post->post_parent != 0) {
$next_post_parent = $post->post_parent;
while ($next_post_parent != 0) {
$children = wp_list_pages("title_li=&child_of=".$next_post_parent."&echo=0");
$parentpage = $wpdb->get_row("SELECT ID, post_title, post_parent, post_name FROM $wpdb->posts WHERE ID = '".$next_post_parent."'");
$next_post_parent = $parentpage->post_parent;
}
}
?>
<?php if ($children) { ?>
<ul>
<li><h2>SUBNAV FOR: <a href="<?php echo get_permalink($parentpage->ID); ?>"><?php echo $parentpage->post_title; ?></a></h2>
<ul>
<?php echo $children; ?>
</ul>
</li>
</ul>
<?php } ?>
If someone knows of an easier/better way than this – please let me know. I've looked and couldn't find anything (and was happy to have figured something out that worked!)
You can put this anywhere in your template file really. This code would be used OUTSIDE of the WordPress loop…
Update: So just a bit more advanced "features" here. On my installment of this – I wanted only the first level of subnav pages visible, and then if you clicked on a subnav page that had child pages – then that list became visible. And if one of those pages had child pages – then that 3rd level of pages would be shown also (all the while keeping all the other sub nav for this section visible. When I get more time, I'll include screenshots to demonstrate what I'm talking about. In the meantime , I'm dumping the code here before I lose it again! LOL! Oh, also – I wanted to add some kind of indicator on the subnav links that showed there was navigation below it – like an + sign or something…
<script type="text/javascript" src="/js/jquery-1.3.1.min.js"></script>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready( function() {
jQuery('ul').parent('li').addClass("parentul");
});
</script>
That will find any unordered list that is WITHIN a list item – and apply the class "parentul" to the PARENT li item.
Then I used the following styles to hide the blocks that needed to be hidden, and show the "+" sign next to the linkts that had more subnav items below them:
#sidebar .current_page_ancestor ul,
#sidebar .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent ul {
display: block;
}
#sidebar .current_page_item ul ul,
#sidebar .current_page_ancestor.current_page_parent ul ul,
#sidebar ul ul ul {
display: none;
}
#sidebar ul li,
#sidebar ul li ul li,
#sidebar ul li ul li ul li {
padding-left: 8px;
}
#sidebar ul li.parentul {
background:url(images/more.gif) 0 3px no-repeat;
}
The "more.gif" was my + sign.
Just to clarify more… Here are the screenshots:
This is the default view of wp_list_pages:
Here is what the code above will do:
If there is no subnav pages under the section we're in – no subnav is displayed…
In this view, we're in the "about" section – on the "What we do" page… notice that you're seeing only the subnav pages under "about", and the pages under "why you want to hire us" are collapsed with the + sign (my "more.gif" in front of the link…
Now we're on the "why you want to hire us" page – so the subnav under that page are revealed.
Now we're on a subnav of a subnav … the "our prices" page under "why you want to hire us" (in the About section)
I tweaked the stylesheets a bit for these screenshots. You'll have to play with it to suit your needs. For the screenshots, I wanted to bold the section we're in in the main nav, and the subnav page, as well as the subnav page, and subnav "parent" page… Here's the styles I used to do that:
#sidebar .current_page_ancestor ul,
#sidebar .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent ul {
display: block;
}
#sidebar .current_page_item ul ul,
#sidebar .current_page_ancestor.current_page_parent ul ul,
#sidebar ul ul ul {
display: none;
}
#sidebar ul li,
#sidebar ul li ul li,
#sidebar ul li ul li ul li {
padding-left: 8px;
}
#sidebar ul li.parentul {
background: none;
}
#sidebar ul ul li.parentul {
background:url(images/more.gif) 0 3px no-repeat;
}
#sidebar .current_page_parent li,
#sidebar .current_page_item li {
font-weight: normal;
}
#sidebar li.current_page_ancestor,
#sidebar li.current_page_item {
font-weight: bold;
}