Customizing Walker_Nav_Menu

I’m looking for a solution to adjust the output of wp_nav_menu only on a specific navigation menu. I have my menu:

wp_nav_menu(
    array(
        "container"         => "nav",
        "container_class"   => "container",
        "container_id"      => "nav",
        "fallback_cb"       => false,
        "menu_class"        => "six columns omega main-nav sf-menu",
        "theme_location"    => "main-nav"
    )
);

The Problem

I need to find a way insert <span>[number]</span> inside of the anchor element. [number] represents the number of the item starting at 1. Here’s a visual:enter image description here

Read More

The structure of the the menu would be:

<li class="...">
    <a href="#"><span>01.</span>Home</a>
</li>
<li class="...">
    <a href="#"><span>02.</span>Services</a>
</li>
<li class="...">
    <a href="#"><span>03.</span>Portfolio</a>
</li>

Currently, I am using a jQuery hack. This works but there’s no guarantee that the user can merely disable JavaScript. I’ve looked at:

I have an idea that extending the walker class is necessary but my ultimate confusion lies with building the links manually and inserting dynamic information before link text is printed. The Stack Overflow question does it but does not explain how to get there.

Addendum

To get the precise result that I wanted see pastebin. $item->title needed to be modified in order to follow the HTML structure as listed above.

Related posts

1 comment

  1. You just need to create your own walker class and extend start_el method. This method builds a link and you will be able to add your span before it:

    class Wpse8170_Menu_Walker extends Walker_Nav_Menu {
    
        var $number = 1;
    
        function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
            $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';
    
            $class_names = $value = '';
    
            $classes = empty( $item->classes ) ? array() : (array) $item->classes;
            $classes[] = 'menu-item-' . $item->ID;
    
            $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
            $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
    
            $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
            $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
    
            $output .= $indent . '<li' . $id . $value . $class_names .'>';
    
            // add span with number here
            if ( $depth == 0 ) { // remove if statement if depth check is not required
                $output .= sprintf( '<span>%02s.</span>', $this->number++ );
            }
    
            $atts = array();
            $atts['title']  = ! empty( $item->attr_title ) ? $item->attr_title : '';
            $atts['target'] = ! empty( $item->target )     ? $item->target     : '';
            $atts['rel']    = ! empty( $item->xfn )        ? $item->xfn        : '';
            $atts['href']   = ! empty( $item->url )        ? $item->url        : '';
    
            $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
    
            $attributes = '';
            foreach ( $atts as $attr => $value ) {
                if ( ! empty( $value ) ) {
                    $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
                    $attributes .= ' ' . $attr . '="' . $value . '"';
                }
            }
    
            $item_output = $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
            $item_output .= '</a>';
            $item_output .= $args->after;
    
            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
        }
    
    }
    

    After it you will be able to use this class in your wp_nav_menu function call:

    wp_nav_menu(
        array(
            "container"         => "nav",
            "container_class"   => "container",
            "container_id"      => "nav",
            "fallback_cb"       => false,
            "menu_class"        => "six columns omega main-nav sf-menu",
            "theme_location"    => "main-nav",
            "walker"            => 'Wpse8170_Menu_Walker',
        )
    );
    

Comments are closed.