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

Altering the wp_nav_menu WordPress

  • SOLVED

Hello,

Currently I'm using this tiny snippet

add_filter ( 'nav_menu_css_class', 'pagenamed_class', 10, 2 );

function pagenamed_class($css_class, $post) {
$css_class = array ();
if ($post->post_type == 'nav_menu_item') {
$content_page_id = get_post_meta ( $post->ID, '_menu_item_object_id', true );
$content_page = get_post ( $content_page_id );
$css_class [] = $content_page->post_name;
}
return $css_class;
}


to alter my wp_nav_menu from this

<nav role="navigation">
<ul>
<li id="menu-item-123" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-123"><a href="http://mysite.com/">Voorpagina</a></li>
<li id="menu-item-60" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-60"><a href="http://mysite.com/sample-page">Sample Page</a></li>
</ul>
</nav>


to this (note the slug is the class)

<nav role="navigation">
<ul>
<li id="menu-item-123" class="voorpagina"><a href="http://mysite.com/">Voorpagina</a></li>
<li id="menu-item-60" class="sample-page"><a href="http://mysite.com/sample-page">Sample Page</a></li>
</ul>
</nav>


If possible I'd like to have it changed slightly to match this

<nav role="navigation">
<ul>
<li id="voorpagina" class="current-menu-item"><a href="http://mysite.com/">Voorpagina</a></li>
<li id="sample-page"><a href="http://mysite.com/sample-page">Sample Page</a></li>
</ul>
</nav>


Note the slug is now the id instead of class, and .current-menu-item is again included into the nav menu

Would something like this be possible? (using php instead of javascript)

Answers (4)

2012-01-15

Ivaylo Draganov answers:

Hello,

yes it is possible - there's a filter for the ID attribute, use something like this:

// set the ID attribute of nav menu items
add_filter( 'nav_menu_item_id', 'pagenamed_id', 10, 2 );

function pagenamed_id( $id, $item ) {

$content_page_id = get_post_meta ( $item->ID, '_menu_item_object_id', true );
$content_page = get_post ( $content_page_id );
$id = $content_page->post_name;

return $id;

}


And to clear* the class use this:

// set nav item classes to an empty array
add_filter( 'nav_menu_css_class', 'filter_nav_menu_classes' );

function filter_nav_menu_classes( $classes ) {

$classes = array();

// return the new array with classes
return $classes;

}


* It doesn't remove the class attribute. If you want to remove it, a custom menu walker has to be used.


Cor comments:

Hi Ivaylo,

Looks promising.

I don't mind if a class would be empty, but would it be possible to include .current-menu-item when needed?


Ivaylo Draganov comments:

Try this then:
[[LINK href="http://pastebin.com/uSVfufik"]]http://pastebin.com/uSVfufik[[/LINK]]

I've copied the part of the core funciton that prints these classes.


Cor comments:

Hi Ivaylo,

It's currently giving me this error: Undefined variable: key


Ivaylo Draganov comments:

Try the updated code:
[[LINK href="http://pastebin.com/uSVfufik"]]http://pastebin.com/uSVfufik[[/LINK]]


Cor comments:

Hi Ivaylo,

Looks even more promising :)

It seems there's just one error remaining: Notice: Undefined variable: front_page_url


Ivaylo Draganov comments:

Updated. At the same URL.


Cor comments:

Thanks Ivaylo, That would be the one :)

Also, I was a bit overwhelmed by the numerous amount of replies on such a short notice :) Thanks everyone :)

2012-01-15

Francisco Javier Carazo Gil answers:

Hi Cor,

Try this:

function pagenamed_class($css_class, $post) {
$css_class = array ();

if ($post->post_type == 'nav_menu_item') {
$content_page_id = $content_page->post_name;
$content_page = get_post ( $content_page_id );
if(is_page($post->ID))
array_push($css_class, "current-menu-item");
}

return $css_class;
}


Cor comments:

Hello Francisco,

It's currently giving me an “Undefined variable” and “Trying to get property of non-object” notice on this line:
$content_page_id = $content_page->post_name;


Francisco Javier Carazo Gil comments:

Sorry Cor,

Try this:

<?php
function pagenamed_class($css_class, $post) {
$css_class = array ();

if ($post->post_type == 'nav_menu_item') {
$content_page_id = get_post_meta ( $post->ID, '_menu_item_object_id', true );
$content_page = get_post ( $content_page_id );
$content_page_id = $content_page->post_name;

if(is_page($post->ID))
array_push($css_class, "current-menu-item");
}

return $css_class;
}
?>


Cor comments:

Hi Francisco,

It seems it's currently removing all class atributes, but isn't changing the id, or the class atribute to .current-menu-item if active


Francisco Javier Carazo Gil comments:

Hi Cor,

You have to use the code provided by Jurre Hanema to include the id and also this code to include the CSS.


function pagenamed_class($css_class, $post) {
$css_class = array ();

if ($post->post_type == 'nav_menu_item' && is_page($post->ID))
array_push($css_class, "current-menu-item");

return $css_class;
}


Remember the filter: add_filter ( 'nav_menu_css_class', 'pagenamed_class', 10, 2 );

Regards.

2012-01-15

Jurre Hanema answers:

Something like this, perhaps?


add_filter('nav_menu_item_id', 'pagenamed_id', 10, 2);


function pagenamed_id($the_id, $item, $args)
{
if($item->post_type == 'nav_menu_item')
{
$content_page_id = get_post_meta($item->ID, '_menu_item_object_id', true);
$content_page = get_post($content_page_id);

if($content_page && isset($content_page->post_type) && content_page->post_type == 'page')
{
$the_id = $content_page->post_name;
}
}

return $the_id;
}


Cor comments:

Hi Jurre,

It's cuurently giving me an “syntax error, unexpected T_OBJECT_OPERATOR” on this line:
if($content_page && isset($content_page->post_type) && content_page->post_type == 'page')


Jurre Hanema comments:

Sorry, little copy & paste-mistake:


add_filter('nav_menu_item_id', 'pagenamed_id', 10, 3);


function pagenamed_id($the_id, $item, $args)
{
if($item->post_type == 'nav_menu_item')
{
$content_page_id = get_post_meta($item->ID, '_menu_item_object_id', true);
$content_page = get_post($content_page_id);

if($content_page && isset($content_page->post_type) && $content_page->post_type == 'page')
{
$the_id = $content_page->post_name;
}
}

return $the_id;
}


Jurre Hanema comments:

Sorry, little copy & paste-mistake:


add_filter('nav_menu_item_id', 'pagenamed_id', 10, 3);


function pagenamed_id($the_id, $item, $args)
{
if($item->post_type == 'nav_menu_item')
{
$content_page_id = get_post_meta($item->ID, '_menu_item_object_id', true);
$content_page = get_post($content_page_id);

if($content_page && isset($content_page->post_type) && $content_page->post_type == 'page')
{
$the_id = $content_page->post_name;
}
}

return $the_id;
}


Cor comments:

Hello Jurre,

Weird would probably be my best reply :)

It's currently giving me this output:
<nav role="navigation">
<ul>
<li id="menu-item-123" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home menu-item-123"><a href="http://mysite.com/">Voorpagina</a></li>
<li id="sample-page" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-60"><a href="http://mysite.com/sample-page">Sample Page</a></li>
</ul>
</nav>


Jurre Hanema comments:

Yeah, I made it so that the id is only replaced if the menu item actually points to a page. Your first menu item is a custom menu item, so the on that one is not replaced.

2012-01-15

Hai Bui answers:

Please try this:
add_filter( 'nav_menu_item_id', 'modify_menu_item_id' );

function modify_menu_item_id( $menu_item_id, $post ) {

if ($post->post_type == 'nav_menu_item') {

$content_page_id = get_post_meta ( $post->ID, '_menu_item_object_id', true );

$content_page = get_post ( $content_page_id );

$menu_item_id = $content_page->post_name;

}
return $menu_item_id;
}



Cor comments:

Hello Hai,

Several notices, but mostly it's missing a second argument for for modify_menu_item_id


Hai Bui comments:

Please try this:
add_filter( 'nav_menu_item_id', 'modify_menu_item_id', 10, 2 );
function modify_menu_item_id( $menu_item_id, $post ) {
if ($post->post_type == 'nav_menu_item') {
$content_page_id = get_post_meta ( $post->ID, '_menu_item_object_id', true );
$content_page = get_post ( $content_page_id );
$menu_item_id = $content_page->post_name;
}
return $menu_item_id;
}


Cor comments:

Hello Hai,

Ehm. difficult :)
It's now the same answer as Ivaylo's, and his was working first :)
It all depends on the .current-menu-item class if active, or on what he or other contributors will come up with.


Hai Bui comments:

Really? I gave you the last answer at 1:33pm while his last edited is 1:40pm, I'm not sure what he edited though, I don't look at other answers. If his code is correct at first time and it's before my answer, just give him the prize.

And I think you don't need to do anything the classes, just delete your old code and replace with mine.