Wordpress nav menu -- adding conditional span - php

Does anyone have a working example of a Wordpress menu outputted manually? The one on the Codex didn't seem to work, though my menu_name slug of "Footer" can't be that complicated..? I need to add offscreen spans within external menu links for accessibility purposes. I already have CSS classes; what I need is specific markup added via the functions.php file.
The basic code I'm looking for (see list items w/ 'external' class. Hrefs changed to # for code brevity, they link offsite in real life):
<ul id="menu-footer" class="menu">
<li class="menu-item">
About Us
</li>
<li class="external menu-item">
<a title="Link opens in a new window." target="_blank" href="#">Terms & Conditions <span class="offscreen">Opens in a new window</span></a>
</li>
<li class="menu-item">
Comments Policy
</li>
<li class="external menu-item">
<a title="Link opens in a new window." target="_blank" href="#">Privacy Statement<span class="offscreen">Opens in a new window</span></a>
</li>
<li class="menu-item">
Contact Us
</li>
</ul>

A custom "walker" class?
http://www.kriesi.at/archives/improve-your-wordpress-navigation-menu-output

Option 1:
Assuming you've created your menu by using Appearance -> Menus , you can try the following.
Navigate to Appearance -> Menus
Click the "Screen Options" (top right) of the screen, make sure "CSS Classes" is selected.
Once you've done the above steps, each of the menu items will now have a "CSS Classses" textbox showing where you can on an individual basis assign CSS Classes (have a look at the screen grab).
Option 2:
You could also try http://codex.wordpress.org/Function_Reference/wp_nav_menu#Adding_Conditional_Classes_to_Menu_Items
<?php
add_filter('nav_menu_css_class' , 'special_nav_class' , 10 , 2);
function special_nav_class($classes, $item){
if(is_single() && $item->title == "Blog"){ //Notice you can change the conditional from is_single() and $item->title
$classes[] = "special-class";
}
return $classes;
}
?>
Option 3:
Provided the above 2 options don't work you have the 3rd option of using jQuery.
HTH

Answer: the nav menu has to be registered & assigned to the theme for the Codex example to work. DUH!
in functions.php:
// default register any navigation menus
register_nav_menus(
array(
'footer' => 'Footer Menu',
'links' => 'Links Menu'
)
);
Assign menu(s) to your theme:
Back in functions.php:
function accessibleAnchors($menu_name, $link_after = NULL){
if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
$menu_list = '<ul id="menu-' . $menu_name . '" class="menu">';
foreach ( (array) $menu_items as $key => $menu_item ) {
// uncomment next line to see all array values
// print_r($menu_item);
$linkText = $menu_item->title;
$url = $menu_item->url;
$target = $menu_item->target;
$titleAttr = $menu_item->attr_title;
// hard-coding the first & only CSS class here, you could loop through others
$cssClass = $menu_item->classes[0];
if($target == '_blank'):
$titleAttr = " title=\"$titleAttr\"";
$span = "<span class=\"offscreen\"> Opens in a new window</span>";
else:
$span = "";
endif;
$menu_list .= '<li class="menu-item '.$cssClass.'"><a href="' . $url . '"'.$titleAttr. '>' . $linkText . $span . $link_after .'</a></li>';
}
$menu_list .= '</ul>';
}
return $menu_list;
}
Now call the function in your template:
<?php echo accessibleAnchors('footer'); ?>
Boom.

You'll have to start in wp-includes/nav-menu-template.php to Copy and paste the function to your theme's functions.php and change the name or use a filter in functions.php to change selected markup of the hook. And possibly take a look in wp-includes/nav-menu.php as well.
Sorry I can't provide more detail.

Related

Is there any way to have a menu with images and a custom navwalker?

I am trying to create a menu with an image, title and description.
So far, the decription and title are working great, so, I found this plugin
https://wordpress.org/plugins/menu-image/
works very good and shows the image + the title, but not the description.
So, I guess I need, somehow to show the description without losing the image.
I create a custom navwalk, but seems like I cannot just call the attached image. Looking at the code of the plugin couldnt find anything that helps.
Any idea? have anybody done this before?
My navwalker so far looks like this:
<?php
class Ext_Walker extends Walker {
var $tree_type = array('post_type', 'taxonomy', 'custom');
var $db_fields = array('parent' => 'menu_item_parent', 'id' => 'db_id');
function start_el(&$output, $object, $depth = 0, $args = array(), $current_object_id = 0) {
$classes = "";
foreach ($object->classes as $cl){
$classes.=" $cl";
}
$output .="<div class='col-lg-15 bottom-pad'>
<div class='vertical_item'>
<div class='col-lg-60'>
<div class='$classes'></div>
</div>
<div class='clear'></div>
<div class='desc_vertical'>
<h2 class='vertical_title'>{$object->title}</h2>";
if($object->post_content != ""){
$output .="<p class='item_description'>{$object->post_content}</p>";
}else{
}
$output .="</div>";
$output .="<button class='btn btn-link'>View More</button>";
}
function end_el(&$output, $object, $depth = 0, $args = array()) {
$output.='</div></div>';
}
}
?>
When WordPress is creating the menu, it is creating the menu items with links of the form
<a>Some Title</a>
The Walker runs the title through the "the_title" filter. The plugin you reference does the same thing.
So there are at least two possibilities for accomplishing you want without developing your own Walker extension:
1) Extend the plugin
Since the plugin is using the the_title filter, you could add a filter of that type to add the description (the plugin is already adding an image). So
function add_description( $title, $id ) {
if ( 'nav_menu_item' == get_post_type( $id ) ) {
$title = '<span class="title">' . $title . '</span>;
$title .= '<span class="desc">' . description from wherever you get it . '</span>;
}
return $title;
}
add_filter( 'the_title', 'add_description', 10, 2 );
This changes the text inside to link to be both title and description. You would want to check the post type, since the filter is called in other circumstances also.
2) Use just the filter
You could use a variant of the above filter to add both and image and the description, avoiding the need for the plugin. For example:
function add_img_and_desc( $title, $id ) {
if ( 'nav_menu_item' == get_post_type( $id ) ) {
// Get the image for the menu item (say in $img)
$title = $img . '<span class="title">' . $title . '</span>;
$title .= '<span class="desc">' . description from wherever you get it . '</span>;
}
return $title;
}
add_filter( 'the_title', 'add_img_and_desc', 10, 2 );
How you would get the image would depend on your approach. For example, it could be as simple as a switch statement that is based on the title.

How to create a menu from get_nav_menu_locations when it always returns an empty array?

In the wordpress dashboard I've created a menu under appearance -> menus and named it "my-menu".
Using example code from this page I'm trying to build the menu. In my /wp-content/themes/blankslate/header.php I add the following code:
$menu_name = 'my-menu';
$locations = get_nav_menu_locations();
print_r ($locations);
Basically on every page the $locations is an empty array even though I've created and saved the menu. Was hoping to create menus and having the name of it in a custom field so every page can have it's own menu (or nothing when left empty or default menu when custom field not provided).
Guess I'm not getting the way wordpress intends the user to use it, maybe it's just a checkbox somewhere. I did notice that when I check the box Main Menu under Appearance -> Menus the array returned isn't empty but $locations[ $menu_name ] is not set.
Using wordpress 3.6.1 with a modded blankslate theme.
[UPDATE]
The functions.php is hardly changed and the register_nav_menus is set with the following parameter:
array( 'main-menu' => __( 'Main Menu', 'blankslate' ) )
I guess that's where the Main Menu checkbox in Appearance -> Menus on the Dashboard comes from. Commenting out this line makes Menus disappear all together.
$locations = get_theme_mod( 'nav_menu_locations' );
print_r($locations);
try this
In /wp-content/themes/blankslate/functions.php
function getDefaultMenu(){
$loc=get_nav_menu_locations();
$menu = wp_get_nav_menu_object( $loc['main-menu'] );
return $menu;
}
function getMenu() {
global $post;
//set menuName to custom field called menu-name
$menuName = get_post_meta($post->ID, 'menu-name', true);
//menu to use
$useMenu = false;
//get available menus
$menus = wp_get_nav_menus();
//if no custom field was given use default-menu
// will fail if no menu is set to default
if (!$menuName) {
$useMenu=getDefaultMenu();
if(!$useMenu){
throw new Exception("Please make one of the menus".
" the main menu under Appearance => Menus");
}
return wp_get_nav_menu_items($useMenu->term_id);
}
//find the menu with the $menuName
// either default-menu or the custom field called menu-name
foreach ($menus as $menuItem) {
var_dump ($menuItem);
if ($menuItem->name === $menuName) {
$useMenu = $menuItem;
break;
}
}
//if no menu was found raise an error
//menu-name must be provided as a custom field
// or default menu must be set
if (!$useMenu) {
throw new Exception("Can't open menu named:" . $menuName .
" Make sure you set a custom field called menu-name" .
" with the name of one of the menus under Appearance => Menus".
" Or set one of the menus to Main Menu.");
}
return wp_get_nav_menu_items($useMenu->term_id);;
}
In /wp-content/themes/blankslate/page.php
$menu_items=getMenu();
var_dump($menu_items);
$menu_list = '<ul id="menuid">';
foreach ((array) $menu_items as $key => $menu_item) {
$title = $menu_item->title;
$url = $menu_item->url;
$menu_list .= '<li>' . $title . '</li>';
}
$menu_list .= '</ul>';
Example code doesn't show how to handle nested items but I'll update when I figure that one out.

Different Menus on Different Pages

Trying to have different navigation menus on different pages. My theme doesn't let me edit the functions page. I created a new header template and page template. I want to change the menu used in the new header template, but I don't understand what the code below means so I'm not exactly sure what to change.
I'm trying to learn so could someone help translate what this code means?
<ul id="menu-hosting-menu" class="curved">
<?php if ( is_page() ) $highlight = 'page_item'; else $highlight = 'page_item
current_page_item'; ?>
<li class="<?php echo $highlight; ?> menu-item menu-item-type-custom menu-item-object-custom">Home</li>
<?php wp_list_pages( 'sort_column=menu_order&depth=3&title_li=&exclude=' ); ?>
</ul><!-- /#nav -->
<?php } ?>
<select>
<option value="" selected="selected">Select</option>
<?php
$menu_name = 'primary-menu'; //same as theme_location
if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[
$menu_name ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
var_dump($menu_items);
foreach ( (array) $menu_items as $key => $menu_item ) {
$title = $menu_item->title;
$url = $menu_item->url;
if($menu_item->menu_item_parent){
$title = '-- '.$title;
}
$menu_list .= '<option value="' . $url . '">' . $title .
'</option>';
}} else {
$menu_list .= '<option value="">Menu "' . $menu_name . '" not
defined.</option>';
}
echo $menu_list;
?>
</select>
</nav>
Are you trying to load the menu on an entirely new template, or just a particular page?
I imagine one (simple) approach to this would be to create both a new page template, and a new header. You would simply then tell the new page template (selectable in your Admin panel in the CMS) to call the new (custom) header as well.
A great explanation on how this can be done is found here:
http://reflectingthedesigner.com/wordpress/2011/10/24/creating-a-new-wordpress-page-template/
Hope this helps.
Figured it out. I just deleted all of that code above and replaced it with
<?php wp_nav_menu( array('menu' => 'Hosting' )); ?>
Worked like a charm.

Wordpress - Add "active" class if current page is active

<?php
if($post->post_parent)
$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0");
else
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
if ($children) {
$parent_title = get_the_title($post->post_parent);?>
<li><?php echo $parent_title;?></li>
<?php echo $children; ?>
<?php } ?>
The code above lists the parent and all child pages in a list.
Parent Page
Child Page
Child Page class="active"
Child Page
Child Page
I would like to add a class of "active" to the currently active page. Any help is greatly appreciated. Thanks
To look for a specific page and add an active class to it, you can try using is_page and define the URL/slug of the page.
<a class="<?php if (is_page('name-of-page')) echo 'active'; ?>" href="#">Link</a>
You can easily add active and other classes by checking the $post->post_title against the $item->title
function addLinkClassesWithActive( $atts, $item, $args ) {
global $post;
// check if the item is in the primary menu
if( $args->theme_location == 'main-nav' ) {
// add the desired attributes:
$atts['class'] = $post->post_title === $item->title ? 'mdl-layout__tab is-active' : 'mdl-layout__tab';
}
return $atts;
}
add_filter( 'nav_menu_link_attributes', 'addLinkClassesWithActive', 10, 3 );
I am using this myself and stripping out the wrapping container, the ul, and the li tags so that I have just a link. See example below.
<nav role="navigation" class="mdl-navigation mdl-layout--large-screen-only" itemscope itemtype="http://schema.org/SiteNavigationElement">
<div class="mdl-tabs mdl-js-tabs mdl-js-ripple-effect">
<?php
$primaryMenu = array(
'container' => false,
'theme_location' => 'main-nav',
'items_wrap' => '%3$s',
'echo' => false,
);
echo strip_tags( wp_nav_menu( $primaryMenu ), '<a>' );
?>
</div>
</nav>

Wordpress custom field info in nav menu?

I'm trying to get custom field info from a page into the nav menu. I've had problems with this before... I just don't "get" the walker menu and how it works.
Basically, In addition to the title of the page, I want to have it output the URL of an image and image description from the custom fields and create a menu item linked to a normal WP page.
In the nav-menu-template.php file, I've tried modifying the start_el function by adding get_post_custom_keys() like this with no success:
$item_output .= '<a'. $attributes .'>';
$item_output .= get_post_custom_values("product_image", $item->ID);
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
I've also tried get_post_meta(); and others with limited success. The best I've been able to do is either get one of the images repeating in all the links by specifying a a hard integer value. Or, I've been able to get it to output the correct post/page value in text but without an image.
Anyone know of a solution.. what I'm doing wrong?
It would probably be easier to iterate through your nav menu and render it dynamically. The below code will let you iterate through a given nav menu assigned to a nav menu location you would have registered in your functions.php file:
<ul id="some-menu-id" class="my-fancy-menu">
<?php
$menu_name = 'primary';
if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
foreach ( (array) $menu_items as $key => $menu_item ) {
// at this point you can get the custom meta from the page
$image = get_post_meta($menu_item->object_id, '_custom_field_image_url', true);
$image_description = get_post_meta($menu_item->object_id, '_custom_field_image_description', true);
// here we are getting the title and URL to the page
$title = $menu_item->title;
$url = $menu_item->url;
$slug = basename($menu_item->url);
// this allows us to add a current class
if (basename($_SERVER['REQUEST_URI']) == $slug) { $current = ' current-menu-item'; } else { $current = ''; }
$menu_list .= '<li class="page-id-'.$menu_item->object_id.$current.'">' . $title . '<br /><p>'.$image_description.'<br />'.$image.'</p></li>';
}
}
echo $menu_list;
?>
</ul>

Categories