Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Custom Walker WP_NAV_MENU WordPress

  • SOLVED

Hello,

I am trying to create a dynamic menu using the "appearance > menu" from WP Dashboard.

My issue is as follows;

assume i have a layout a site structure as follows;

Parent
Parent
Child
Child
Child
Parent
Parent
Child


So this is what i want to achieve, i would like all the Parents with Children to have a different class than parents without a child.

The reason i am trying to do this is to add a small graphic to indicate that the parent has children.

I would also like to preserve wordpress's classes (i.e. current_page_item) etc.

I would like to achieve this without the use of a plugin.

Thanks;

Answers (3)

2011-02-20

Peter Michael answers:

[[LINK href="http://goldenapplesdesign.com/2010/10/05/dropdown-menus-walker_nav_menu/"]]http://goldenapplesdesign.com/2010/10/05/dropdown-menus-walker_nav_menu/[[/LINK]]


xavier comments:

Hello Peter,

With the second set of code on that site, how would i hook that in, using the first example it seemed to work fine but with the second snippet of code it doesn't append the classes.


Peter Michael comments:

Use it like this:

<?php wp_nav_menu( 'walker' => new dropdown_walker() ); ?>


xavier comments:

Parse error: syntax error, unexpected T_DOUBLE_ARROW


Peter Michael comments:

Oops:

<?php wp_nav_menu( array( 'walker' => new dropdown_walker() ) ); ?>


xavier comments:

Still is not adding a class to the parent, only to the sub-menu ul


xavier comments:

let me paste in the code im using then;

class dropdown_walker extends Walker_Nav_Menu
{
var $link_counter=0;

function start_lvl(&$output, $depth) {
global $link_counter;
$class = 'scriptaculously';
$indent = str_repeat("\t",$depth);
$output .= "\n$indent<ul class=\"$class\" id=\"sub-".$link_counter."\" style=\"display:none;\">\n";
}

function start_el(&$output, $item, $depth, $args)
{
global $wp_query;
global $link_counter;
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

$class_names = $value = '';

$classes = empty( $item->classes ) ? array() : (array) $item->classes;

$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
$class_names = ' class="'. esc_attr( $class_names ) . '"';
if (in_array('has_children',$classes)) $counter++;

$output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $class_names .'>';

$attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : '';
$attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : '';
$attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : '';
$attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : '';

if (strpos($class_names,'has_children')) {
$link_counter++;
$attributes .= ' class="drops" id="link-'.$link_counter.'"';
}

$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before .apply_filters( 'the_title', $item->title, $item->ID );
$item_output .= $description.$args->link_after;
$item_output .= '</a>';
$item_output .= $args->after;

$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

}
}


and to call the menu;


<?php wp_nav_menu( array( 'walker' => new dropdown_walker() ) ); ?>


Peter Michael comments:

It's actually the filter function 'check_for_submenu' which adds the classes (has_children) for the parent items, the walker 'dropdown_walker' just extends the whole thing so it can be used with the droplicious menu script.

In your case, the filter function does the job very well, you don't need a custom walker.

2011-02-20

Andrzej answers:

Hi Xavier,

Writing a custom walker with this budget might be problematic, however, you can use this trick to get around it:

[[LINK href="http://nbm.im/20110220-10p-109kb.jpg"]]view screenshot[[/LINK]]

This way you can manually add any classes you want. Not dynamic, but does the job pretty well.


xavier comments:

Hello Andrzej,

This is for a clients site, i will end up hiding all these additional facilities such as CSS Classes,

i want to make it as streamline as possible, so this solution would not be acceptable.

Thanks

2011-02-20

Darrin Boutote answers:

If all you're wanting to do is add a class, why not use jQuery?

Asuming your structure is something along these lines:
<div id="site-nav">
<ul id="primary-nav">
<li class="top-level"><a href="#" title="">Parent</a>
<ul>
<li><a href="#">Child</a></li>
<li><a href="#">Child</a></li>
</ul>
</li>
<li class="top-level"><a href="#" title="">Non Parent</a></li>
<li class="top-level"><a href="#" title="">Parent</a>
<ul>
<li><a href="#">Child</a></li>
<li><a href="#">Child</a></li>
</ul>
</li>
</ul>
</div>


You could try:

jQuery(document).ready(function($){
// find the first link in the parent element and add a class of "parent" to it
$("#site-nav ul ul").parent().find("a:eq(0)").addClass('parent');
});