I want to create a menu that pulls only the sub-menu options for a particular page.
For example, if the menu option DASHBOARD has the sub-menus MESSAGE BOARD and CALENDAR, I want to be able to create a separate menu with just MESSAGE BOARD and CALENDAR.
I'd like to do this without the wp_list_pages function so that the menu options can be managed using the Appearances > Menus tab in WordPress.
Thanks!
If I understood you correctly, you want additional menu items for sub pages?
I.E. You have a menu that looks like this
HOME ABOUT DASHBOARD FAQ CONTACT
DASHBOARD has 2 sub-pages -> BOARD CALENDAR
When you are on the DASHBOARD page you want the BOARD and CALENDAR pagees to show like this:
HOME ABOUT DASHBOAR FAQ CONTACT
BOARD CALENDAR
You can add an aditional menu in functions.php like this
<?php if (function_exists('register_nav_menus'))
{
register_nav_menus
(
array
(
'main_nav'=>'main menu', // your main menu
'dash_nav'=>'dashboard menu', //your dashboard menu
)
);
}?>
And then create a page template for dashboard which will have this:
<?php wp_nav_menu(array('menu'=>'dashboard menu'));?>
EDIT:
Well you could edit the header.php and add something like this
<?php if (is_page_template('dashboard.php') :?>
<link href="csspath" rel="stylesheet" type="text/css" />
<?php endif;?>
That way you add another css file that overrides the submenu.
I think I had a similar desire as you to select and only show a sub menu being just the children menu items from an existing wordpress menu. This can be done by editing the functions.php and adding a shortcode that has it's own walker class to target and display a submenu.
PHP code for "menu" shortcode and customized menu walker class (all goes in functions.php):
//register menu shortcode
add_shortcode('menu', 'shortcode_menu');
function shortcode_menu($args ) {
//don't echo the ouput so we can return it
$args['echo']=false;
//in case menu isn't found display a message
$args['fallback_cb']='shortcode_menu_fallback';
//check if showing a submenu, if so make sure everything is setup to do so
if (isset($args['show_submenu']) && !empty($args['show_submenu'])) {
if (!isset($args['depth'])) {
$args['depth']=1;
}
$args['walker']=new Sub_Menu_Walker_Nav_Menu();
}
$menu=wp_nav_menu( $args );
return $menu;
}
//message to display if menu isn't found
function shortcode_menu_fallback($args ) {return 'No menu selected.';}
//special walker_nav_menu class to only display submenu
//depth must be greater than 0
//show_submenu specifies submenu to display
class Sub_Menu_Walker_Nav_Menu extends Walker_Nav_Menu {
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
if ( !$element )
return;
$id_field = $this->db_fields['id'];
$displaythiselement=$depth!=0;
if ($displaythiselement) {
//display this element
if ( is_array( $args[0] ) )
$args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] );
$cb_args = array_merge( array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'start_el'), $cb_args);
}
$id = $element->$id_field;
if ( is_array( $args[0] ) ){
$show_submenu=$args[0]['show_submenu'];
}else
$show_submenu=$args[0]->show_submenu;
// descend only when the depth is right and there are childrens for this element
if ( ($max_depth == 0 || $max_depth >= $depth+1 ) && isset( $children_elements[$id]) && $element->title==$show_submenu) {
foreach( $children_elements[ $id ] as $child ){
if ( !isset($newlevel) ) {
$newlevel = true;
//start the child delimiter
$cb_args = array_merge( array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'start_lvl'), $cb_args);
}
$this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
}
unset( $children_elements[ $id ] );
}
if ( isset($newlevel) && $newlevel ){
//end the child delimiter
$cb_args = array_merge( array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'end_lvl'), $cb_args);
}
if ($displaythiselement) {
//end this element
$cb_args = array_merge( array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'end_el'), $cb_args);
}
}
}
Display a submenu titled "About" from the "Main" menu (capitalization matters):
[menu menu='Main' show_submenu='About']
Display the full "Main" menu:
[menu menu='Main']
For further reading/reference see this wordpress question.
I am surprised that Wordpress doesn't have this option built into the wp_nav_menu function. It has always been a struggle to implement secondary or split menus in Wordpress. After trying a number of different solutions to accomplish this goal I finally decided to make my own plugin that lets you choose the start depth for your menu. So you can just set the start depth to '1' for a secondary menu.
you use the plugin like this:
wp_nav_plus(array('theme_location' => 'primary_navigation', 'start_depth' => 1));
The plugin is available on my site here for anyone interested: https://mattkeys.me/products/wp-nav-plus/
Related
I want to add an additional menu consisting only of the product category images. I'm using woocommerce. I would like it to be centered in the middle of the page and drop down. What kind of short code does this require? I've tried using Mega Menu plugin but it only alters my primary menu.
Thanks!
I don't think there is a direct way for that, You can use this code to get an array of the categories images URLs, You can use the "woocommerce_before_shop_loop" action then, loop over the array and put the images in the HTML form you like.
add_action( 'woocommerce_before_shop_loop', function() {
$categories = get_terms( 'product_cat' );
$categories_thumbnails_urls = [];
foreach ( $categories as $category ) {
$thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true );
$thumbnail_url = wp_get_attachment_url( $thumbnail_id );
if ( empty( $thumbnail_url ) ) {
continue;
}
$categories_thumbnails_urls[] = $thumbnail_url;
}
foreach ( $categories_thumbnails_urls as $cat_thumb_url ) {
// ...
}
});
Is their anyway using the code for wordpress tag list to show the active current tag that is selected ie if they select tag 3 should show it in an orange color the code I am using is as follows in a widget.
<?php wp_tag_cloud( 'format=list&orderby=count&order=DESC' ); ?>
But i not sure on how to do this with css.Also in my blog page the categorys below each post are sitting werid on every post how can i get it to align below Tovább olvasom for every post thanks
The url to check above is
http://kvalixhu.digitalthinkersni.co.uk/blog/
There is a way to style the current tag, but you need to add some code in your theme's functions.php take a look at this site, helped me when I needed that: http://georgebohnisch.com/extending-the-wordpress-tag-cloud/. Here is the code snipped from that site to protect against link rot:
add_filter ( 'wp_tag_cloud', 'tag_cloud_active_class' );
function tag_cloud_active_class( $taglinks ) {
if ( is_tag() ) {
$term_id = get_query_var('tag_id');
$taxonomy = 'post_tag';
$args ='include=' . $term_id;
$terms = get_terms( $taxonomy, $args );
$active_tag = $terms[0]->slug;
}
$tags = explode('', $taglinks);
$regex = "#(.*tag-link[-])(.*)(' title.*)#e";
foreach( $tags as $tag ) {
if (strpos($tag,$active_tag)) {
$tagn[] = preg_replace($regex, "('$1$2 '.'active-tag'.'$3')", $tag );
} else {
$tagn[] = preg_replace($regex, "('$1$2$3')", $tag );
}
}
$taglinks = implode('', $tagn);
return $taglinks;
}
To answer your category problem, what exactly is sitting weird?
I have used the code below to add menu items in the nav menu
'add_filter( 'wp_nav_menu_items', 'add_users_link', 10, 2 );
function add_users_link( $items, $args ) {
if (is_user_logged_in() && $args->theme_location == 'primary') {
$items .= '<li>Cadastro</li>';
}
elseif (!is_user_logged_in() && $args->theme_location == 'primary') {
$items .= '<li>Log In</li>';
}
return $items;
}
I need to display the above items to the second position in the above code.
I have used sort_column and menu_order, but it not working
Anyone helps. THanks in advance
I see three ways to do it:
With PHP
You can split your menu in two distinct menu then:
<?php
$args1 = array( 'menu' => 'header_menu_1' );
$args2 = array( 'menu' => 'header_menu_2' );
wp_nav_menu($args1);
?>
Your custom content here
<?php
wp_nav_menu($args2);
?>
With jQuery
$(document).ready(function() {
$('ul li').eq(2).after('Your html content here');
});
With Css
You can change order of items with css and display: flex property
See Flex order documentation here
I have made a menu item with this code.
The menu item shows up but the shortcode output is not there.
Is there something I can add or a different method that will do this.
I have added also in hopes this might help.
add_filter('wp_nav_items', 'do_shortcode', 7);
Or maybe someone knows this is not possible and can tell me.
/* Nav Menu */
function add_profile_link_to_nav(){
if ( is_user_logged_in() ) { ?>
<ul>
<li class="menu-item"id="one"> All Members
<ul class="sub-menu">
<li class="menu-item"><?php echo custom_execute_shortcode(); ?> </li>
</ul>
</li>
</ul> <!--end menu--->
<?php }
}
add_action( "wp_nav_items","add_profile_link_to_nav" );
function custom_execute_shortcode() {
$myfunction= '[my shortcode"]';
$myfunction_parsed = do_shortcode($myfunction);
return $myfunction_parsed;
}
Thanks
#Tim
This code will work
put it in functions.php file
add_filter('wp_nav_menu_items', 'do_shortcode');
You can't use shortcodes directly in the menu URL on the menu page, because the brackets get stripped out. But you can use placeholders like this: #profile_link#.
With the following code in functions.php, you can create a custom menu item with the URL #profile_link#, and it will replace that with your shortcode.
/**
* Filters all menu item URLs for a #placeholder#.
*
* #param WP_Post[] $menu_items All of the nave menu items, sorted for display.
*
* #return WP_Post[] The menu items with any placeholders properly filled in.
*/
function my_dynamic_menu_items( $menu_items ) {
// A list of placeholders to replace.
// You can add more placeholders to the list as needed.
$placeholders = array(
'#profile_link#' => array(
'shortcode' => 'my_shortcode',
'atts' => array(), // Shortcode attributes.
'content' => '', // Content for the shortcode.
),
);
foreach ( $menu_items as $menu_item ) {
if ( isset( $placeholders[ $menu_item->url ] ) ) {
global $shortcode_tags;
$placeholder = $placeholders[ $menu_item->url ];
if ( isset( $shortcode_tags[ $placeholder['shortcode'] ] ) ) {
$menu_item->url = call_user_func(
$shortcode_tags[ $placeholder['shortcode'] ]
, $placeholder['atts']
, $placeholder['content']
, $placeholder['shortcode']
);
}
}
}
return $menu_items;
}
add_filter( 'wp_nav_menu_objects', 'my_dynamic_menu_items' );
You just need to set 'shortcode' in the $placeholders array, and optionally 'atts' and 'content'.
For example, if your shortcode is like this:
[example id="5" other="test"]Shortcode content[/example]
You would update:
'#placeholder#' => array(
'shortcode' => 'example';
'atts' => array( 'id' => '5', 'other' => 'test' );
'content' => 'Shortcode content';
),
Note that I don't use do_shortcode() because it is a resource intensive function and isn't the right tool for the job in this case.
Enable description on the menu page, paste to the description textarea of the link your shortcode, in functions.php add next code:
add_filter('walker_nav_menu_start_el', function($item_output, $item) {
if (!is_object($item) || !isset($item->object)) {
return $item_output;
}
if ($item->ID === 829) {
$item_output = do_shortcode($item->description);
}
return $item_output;
}, 20, 2);
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.