how to display part of a menu tree? - wordpress

I'm trying to deal with Wordpress 3.0. It's rather cool thing but I can't get on with one problem. For example, I have such menu tree. Menu tree is constructed from pages.
Home
news
video
audio
Blog
About author
Favourite colors
red
blue
green
My car
wheels
tires
The Idea is:
main menu consists of root elements: home, blog, my car
On the left side I would like to display children elements of current active root element.
For exammple if person is on the "home" page, on the left part he should see:
news
video
audio
If user is on the "Blog" page, he should see:
About author
Favourite colors
red
blue
green
I can't find an API to do that. Can you sugest me please where can I find it?
UPD:
#Jason McCreary
I've seen I've seen wp_list_pages() and tried it. I din't get how can I use it:
Please, see my template for a page:
<?php
/*
Template Name: page_news
* #package WordPress
* #subpackage Twenty_Ten
* #since Twenty Ten 1.0
*/
get_header(); ?>
<h1>page_news</h1>
<h1>Children menu:</h1>
<?php wp_list_pages('echo=0&child_of=8&title_li='); ?>
<div id="container">
<div id="content" role="main">
<?php
/** Get category id by name*/
//$catId = get_category_by_slug('news')->term_id;
query_posts('category_name=news');
get_template_part( 'loop', 'page' );
?>
</div><!-- #content -->
</div><!-- #container -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
See this line of code:
<?php wp_list_pages('echo=0&child_of=8&title_li='); ?>
I do have the page with id=8 (I see it in URL). Page with id=8 has several children.
I want to print them, but they are not printed. The output of the function wp_list_pages() is nothing.
I don't know why... :(

You can write a filter_hook to accomplish this.
My method: create an additional start_in argument for wp_nav_menu using my custom hook:
# in functions.php add hook & hook function
add_filter("wp_nav_menu_objects",'my_wp_nav_menu_objects_start_in',10,2);
# filter_hook function to react on start_in argument
function my_wp_nav_menu_objects_start_in( $sorted_menu_items, $args ) {
if(isset($args->start_in)) {
$menu_item_parents = array();
foreach( $sorted_menu_items as $key => $item ) {
// init menu_item_parents
if( $item->object_id == (int)$args->start_in ) $menu_item_parents[] = $item->ID;
if( in_array($item->menu_item_parent, $menu_item_parents) ) {
// part of sub-tree: keep!
$menu_item_parents[] = $item->ID;
} else {
// not part of sub-tree: away with it!
unset($sorted_menu_items[$key]);
}
}
return $sorted_menu_items;
} else {
return $sorted_menu_items;
}
}
Next, in your template you just call wp_nav_menu with the additional start_in argument containing the ID of the page you want the children off:
wp_nav_menu( array(
'theme_location' => '<name of your menu>',
'start_in' => $ID_of_page,
'container' => false,
'items_wrap' => '%3$s'
) );

I wrote this to print sub-navs of the pages you may be on. If you want to print out the sub-navigation for each of the pages, get the page parent instead of getting the ID. There would be more involved than that, but it's a start.
$menu = wp_get_nav_menu_items( 'Primary Menu' );
$post_ID = get_the_ID();
echo "<ul id='sub-nav'>";
foreach ($menu as $item) {
if ($post_ID == $item->object_id) { $menu_parent = $item->ID; }
if (isset($menu_parent) && $item->menu_item_parent == $menu_parent) {
echo "<li><a href='" . $item->url . "'>". $item->title . "</a></li>";
}
}
echo "</ul>";`

Check out wp_list_pages(). It is useful for providing child navigation in the sidebar.

mac joost's answer is great, but I would add that if you want the parent item to print, then you shouldn't unset the parent, so line 18 needs to be adjusted accordingly:
if($item->object_id != (int)$args->start_in) { unset($sorted_menu_items[$key]); }

have you seen wp_list_pages?
http://codex.wordpress.org/Function_Reference/wp_list_pages
look closer on child_of attribute

You can use Breadcrumb navxt plugin. It does exactly what you are looking for and its really great.
Breadcrumb NavXT Pugin

I've stopped to explore how to output custom part of worpress site taxonomy on the server-side. I just use jquery to copy active taxonomy branch from main menu and paste it to the page container I need.

Related

How to display a list of random tags in wordpress?

I have used the following code to try and display a list of random tags:
<?php wp_tag_cloud('smallest=10&largest=10&number=5&format=list&order=rand&orderby=count'); ?>
This does display a list of 5 tags, but the order isn't random, and doesn't change when I reload the page.
Any help of how to achieve this?
Many thanks.
I was looking for an answer to this myself tonight and I thought I would post a solution.
My requirements were for random tags displayed each page refresh and the ability to exclude certain tags. For my purposes I put it in functions.php because I hate cluttering up my template files with functions.
The Function - insert this in your functions.php file
function jr_get_tags_but_exclude() {
$args = array('exclude' => '36 17'); // see notes below
$alltags = get_tags( $args );
shuffle($alltags);
$count=0;
if ($alltags) {
foreach($alltags as $tag) {
$count++;
echo ''.$tag->name.'';
if( $count >19 ) break;
}
}
}
The Call - insert this in your template page
<?php jr_get_tags_but_exclude(); ?>
Notes
To exclude tags you will need the tag ID . The simplest way to get the ID is to go to posts -> tags and hover over the tag you want to exclude. The ID # will be given in the url bar on the bottom of your browser when hovered on, &tag_ID=9, for example.
The Wordpress codex for get_tags says to put only a blank space seperating each tag ID, no commas required.
Regarding randomizing the results, randis not an available option or $arg for get_tags, unfortunately.
To change the number of tags shown adjust if ( $count >19 ) 19 = 20 tags, 29 = 30, etc.
shuffle($alltags); is what does the randomization
$count=0; starts the counter, $count++; counts each tag posted, if( $count >19 ) break; ends the loop, in this case after 20 tags are posted.
Credits and References
mostly based on these gent's solutions
wordpress random tag issue
https://wordpress.stackexchange.com/questions/26112/how-to-limit-and-display-tag
http://wordpress.org/support/topic/php-exclude-tag
wordpress codex for get_tags
http://codex.wordpress.org/Function_Reference/get_tags
In Your Template File - no function needed
<?php
$args = array('exclude' => '36 17'); // see notes below
$alltags = get_tags( $args );
shuffle($alltags);
$count=0;
if ($alltags) {
foreach($alltags as $tag) {
$count++;
echo ''.$tag->name.'';
if( $count >19 ) break;
}
}
?>
Please reply with any mistakes noticed so I can edit them.

WordPress how to pull category specific sidebars into theme

I'm trying to have our WP theme call in a specific sidebar when the user lands on a dedicated article/permalink page. The post category will determine which sidebar is pulled in.
Example: If the user arrives on a permalink/dedicated article page for a post categorized as "red", then the theme would look for the post category, acknowledged that the category is red, and then find and pull in the sidebar that I have defined as "red".
Just getting started with this project and would appreciate any thoughts on what I describe below.
This is what I think the code should look like to achieve that:
<?php
if (is_category()){
$current_cat = intval( get_query_var('cat') );
get_sidebar($current_cat); //for category red get sidebar-red.php
}
?>
One more piece to the puzzle:
I want to add in an addition argument so that if the post is uncategorized (i.e. we did not categorize the post for whatever reason) that it will pull in a default sidebar. I think that code should like something like this, but I don't know how to define "non-existent category". Basically I want to tell wordpress to look for the post category. If it finds that one does not exist, then I want it to pull in sidebar-default.php
<?php
if (is_category()){
$current_cat = intval( get_query_var('cat') );
get_sidebar($current_cat); }
elseif (is_category(**argument for nonexistent category**))
$current_cat = intval( get_query_var('cat') );
get_sidebar-default.php; }
?>
You should be using in_category not is.
For example:
<?php
if ( in_category('fruit') ) {
get_sidebar('1');
} elseif ( in_category('vegetables') ) {
get_sidebar('2');
} else {
// do nothing or something
// ...
}
?>
http://codex.wordpress.org/Function_Reference/in_category
<?php in_category( $category, $_post ) ?>
$category
(mixed) (required) One or more categories specified by ID
(integer), name or slug (string), or an array of these
Default: None
You can have the different sidebar classes defined in your CSS.
Give the category that you want to match up with the style the same name as that category's slug. In your template, define the sidebar div's class using the post's category-slug.
Here's a bit on how to get the slug:
<?php
if (is_category( )) {
$cat = get_query_var('cat');
$yourcat = get_category ($cat);
echo 'the slug is '. $yourcat->slug;
}
?>
So your sidebar div would be something like:
<div class="<?php echo yourcat->slug; ?> sidebar"></div>
So you've given your sidebar two classes, one called sidebar and one to be determined by whatever the category is!
Hopefully this made sense.
You can even use Category Templates, so you create category-red.php and category-blue.php files

Trouble highlighting correct menu parent with wp_nav_menu classes while viewing “single posts”

I just updated a menu on a site of mine to utilize wp_nav_menu. Setting this up with WP was fairly straight forward however I've run into one small snag with the the way wordpress is outputting its parent/ancestor classes for use in highlighting the current page that the content belongs to, particularly with single post pages...
Highlighting the current page with .current_page_item a and .current_page_parent a works perfect as long as its just on a normal page with children, however as soon as you visit a post from events or media, the blog link in the menu is highlighted instead which is incorrect obviously.
*One thing noticeably wrong when looking at Wordpress' output is that the current page classes are not even being generated on the correct li tag that the post belongs to which seems to be the root of the problem.
For future reference, the Events, Media, & Blog pages all use a special query I've written to only grab the respective category for that page, ie.
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
query_posts("category_name=media&paged=$paged");
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div class="post">
</div>
<?php
endwhile;
else:
endif;
Hope thats enough info, if not let me know.
Best,
SB
EDIT - August 3, 2011
Below is a screen shot of what Im referring to when I say that wp_nav_menu is generating the current classes on the wrong li tag. Highlighted in Blue is the menu item that the post actually belongs to. Hightlighted in Grey is the incorrect li tag that wordpress has decided to add the current classes to instead.
http://img688.imageshack.us/img688/4180/picture2zo.png
EDIT - August 4, 2011
Maybe this will help demonstrate how I have the menu setup thus far a little better w/ Hadvig's assistance?
In my functions.php template I have -
<?php
// Add Custom Menu Support
if ( function_exists( 'register_nav_menu' ) ) {
register_nav_menu( 'epr_menu', 'EPR Main Menu' );
}
function my_menu_items_hook($items, $menu, $args) {
if ( 'epr_menu' == $menu->slug ) { // check if it is process your top menu
if ( is_single() ) { // check if single post loaded
if ( in_category('events') || in_category('media') ) {
foreach ( $items as $key => $value ) {
if ( 'blog' == $value->ID ) {
$items[$key]->classes[] = array(); //unset classes for blog item
}
// add class if post from event category
if ( in_category('events') && 'events' == $value->ID ) {
$items[$key]->classes[] = 'current-menu-item';
}
// add class if post from media category
if ( in_category('media') && 'media' == $value->ID ) {
$items[$key]->classes[] = 'current-menu-item';
}
}
}
}
}
return $items;
}
add_action('wp_get_nav_menu_items', 'my_menu_items_hook', 10, 3);
?>
In my header.php template I'm calling the menu like so -
<div id="nav_wrapper">
<ul id="nav">
<?php wp_nav_menu( array( 'container' => '', 'items_wrap' => '%3$s' ) ); ?>
</ul>
</div>
I suppose problem because you set post page as Blog and wordpress set it as parent(in your menu) for all post. You can try to change this behaviour with wp_get_nav_menu_items hook. Example:
function my_menu_items_hook($items, $menu, $args) {
if ( 'my-menu-slug' == $menu->slug ) { // check if it is process your top menu
if ( is_single() ) { // check if single post loaded
if ( in_category(EVENT_CATEGORY_ID) || in_category(MEDIA_CATEGORY_ID) ) {
foreach ( $items as $key => $value ) {
if ( BLOG_PAGE_ID == $value->object_id ) {
$items[$key]->classes[] = array(); //unset classes for blog item
}
// add class if post from event category
if ( in_category(EVENT_CATEGORY_ID) && EVENT_PAGE_ID == $value->object_id ) {
$items[$key]->classes[] = 'current-menu-item';
}
// add class if post from media category
if ( in_category(MEDIA_CATEGORY_ID) && MEDIA_PAGE_ID == $value->object_id ) {
$items[$key]->classes[] = 'current-menu-item';
}
}
}
}
}
return $items;
}
add_action('wp_get_nav_menu_items', 'my_menu_items_hook', 10, 3);
You should replace EVENT_CATEGORY_ID and MEDIA_CATEGORY_ID with your category ids(or names). Also replace EVENT_PAGE_ID and MEDIA_PAGE_ID with your page ids. Replace 'my-menu-slug' with your menu slug.
Of course this would work only if you attach post to only one category from Events, Media or Blog.
Updated.

How do I sort by a custom field without manually creating a new page?

Having a bit of an issue with Wordpress here. In all honesty I've always designed my sites from scratch and "coded" from the ground up. Lately I've been trying to work with WP as I've heard good things about it.
It would appear that WP gives you many things for free (e.g. dynamic "pages" based on CATEGORIES). However, I would like to know how to manipulate these freebies without reinventing the wheel. For example, I would like to have my SUB-MENU display a list of post categories. But I would like to sort those categories by a CUSTOM FIELD.
Now, I could reinvent the wheel and manually create (and link to) a new page for each sort, so on and so forth, (which I don't fundamentally mind doing) however, I'm hoping there is a way around this via plugins or otherwise. I've seen several tutorials on custom queries, but they stop short of implementation -- they simply give the query without telling exactly whether to create a new page or plug it into a function somewhere.
Any input would be most appreciated.
Best.
At the top of category.php template in your theme's root directory, add the following to add your custom sort field to the query:
<?php
function is_valid_custom_sort_field($field)
{
// implementation left as an exercise for the questioner
return true;
}
if ($_REQUEST['sort_custom_field'] && is_valid_custom_sort_field($_REQUEST['sort_custom_field'])) {
query_posts($query_string . '&orderby='.$_REQUEST['sort_custom_field']);
}
See:
http://codex.wordpress.org/Function_Reference/query_posts
If your theme doesn't have a category.php, here is a simple default template to base it on (copied from the included twentyten theme):
<?php
/**
* The template for displaying Category Archive pages.
*/
get_header(); ?>
<div id="container">
<div id="content" role="main">
<h1 class="page-title"><?php
printf( __( 'Category Archives: %s', 'twentyten' ), '<span>' . single_cat_title( '', false ) . '</span>' );
?></h1>
<?php
$category_description = category_description();
if ( ! empty( $category_description ) )
echo '<div class="archive-meta">' . $category_description . '</div>';
/* Run the loop for the category page to output the posts.
* If you want to overload this in a child theme then include a file
* called loop-category.php and that will be used instead.
*/
get_template_part( 'loop', 'category' );
?>
</div><!-- #content -->
</div><!-- #container -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>

WordPress - list multi-level parent pages when on a 3rd level child page

I'm working on a website at the moment, and the navigation works as follows (by client specification).
Underneath the header there is a horizontal navigation listing the top level pages, clicking on one of these takes you to page.php, which has a vertical navigation in the sidebar listing the sub-pages of that particular page like this:
2nd level
- 3rd level
- 3rd level
- 3rd level
2nd level
- 3rd level
- 3rd level
- 3rd level
and so on, and so on.
This is the code I am currently using in the vertical navigation:
$children = wp_list_pages('title_li=&child_of='.$post->ID.'&echo=0');
if ($children)
{
<ul>
echo $children;
</ul>
}
What I would like to be able to do is continue to have the same vertical navigation, regardless of the current page level. I'm finding it hard to list the sub-pages of a 1st level page when you're on a 3rd level page.
Any suggestions greatly appreciated.
Try using get_post_ancestors. This approach seemed to work for me in a similar situation:
<?php
global $wp_query;
$post = $wp_query->post;
$ancestors = get_post_ancestors($post);
if( empty($post->post_parent) ) {
$parent = $post->ID;
} else {
$parent = end($ancestors);
}
if(wp_list_pages("title_li=&child_of=$parent&echo=0" )) { ?>
<ul id="secondary-nav">
<?php wp_list_pages("title_li=&child_of=$parent&depth=1" ); ?>
</ul><!-- #secondary-nav -->
<?php } ?>
Then I used this to target the current nav states with CSS:
#secondary-nav li a:hover,
#secondary-nav li.current_page_item a,
#secondary-nav li.current_page_ancestor a {
background:#fcb701;
}
You'll probably need to remove the depth parameters to show you're 3rd level pages.
I hope this helps!
I think this can be of your help. I had same issue. I had to show up parent page's layout stuffs (everything) in child page.
add_action('wp_head', 'init_stuffs');
function init_stuffs(){
if( is_page() ){
$parents = get_ancestors(get_the_id(), 'page');
if( count( (array) $parents ) >= 2 ){
//now you can use $parents[1] as parent
registry()->setParentPageId($parents[1]);
}
}
}
In my case I had to load blurbs of parents. I used Wordpress Registry plugin to store $parents[1] id. Then I fetched the blurbs of parents by simply passing parent page id in the function where blurbs data are fetched.
function fetchBlurbs($parentId = null){
if(is_null($parentId)){
//fetch blurb for the page
}else{
//fetch blurb of parent page
}
}
Once you're inside The Loop, it's very easy to pull up a reverse history of all page ancestors.
<?php
// It's not necessary to globalize $post if you're doing this inside your page.php
// but if you're in, say, sidebar.php, then you need to declare the global variable
global $post;
// We have to reverse the array so the top link is the topmost ancestor
$history = array_reverse( array_map( 'get_post', get_post_ancestors( $post ) ) );
// And if you want to add this page to the list as well, push it onto the end
$history[] = $post;
?>
<ol>
<?php
// Now, loop through each page in the list
foreach( $history as $page ){
echo "<li><a href='" . get_permalink( $page->ID ) . "' />" . get_the_title( $page ) . '</a>';
}
?>
</ol>
The key line of course is $history = array_reverse( array_map( 'get_post', get_post_ancestors( $post ) ) ); This does two things:
It maps the IDs returned by get_post_ancestors() to actual WP_Post objects (which, isn't strictly necessary, since all we really need are IDs to pass to get_permalink() and get_the_title())
It reverses the array order, since get_post_ancestors() puts the immediate parent at the top of the list, and we probably want it at the bottom.

Resources