Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm trying to implement a responsive jQuery navigation but I need to extend the default output of the WP menu. I believe I need to use a custom walker but honestly, I don't know how to get it to work for me; I just don't know how to get the output I need from it.

I need to wrap any pages that have children with a span and remove the link (Friends and Family in the example below). For example:

<nav id="menu-right">
            <ul>
                <li>
                    <span>Friends</span>
                    <ul>
                        <li><a href="#">Alexa</a></li>
                        <li><a href="#">Alexander</a></li>
                        <li><a href="#">Fred</a></li>
                        <li><a href="#">James</a></li>
                        <li><a href="#">Jefferson</a></li>
                        <li><a href="#">Jordan</a></li>
                        <li><a href="#">Kim</a></li>
                        <li><a href="#">Meagan</a></li>
                        <li><a href="#">Melissa</a></li>
                        <li><a href="#">Nicole</a></li>
                        <li><a href="#">Samantha</a></li>
                        <li><a href="#">Scott</a></li>
                    </ul>
                </li>

                <li>
                    <span>Family</span>
                    <ul>
                        <li><a href="#">Adam</a></li>
                        <li><a href="#">Ben</a></li>
                        <li><a href="#">Bruce</a></li>
                        <li><a href="#">Eddie</a></li>
                        <li><a href="#">Jack</a></li>
                        <li><a href="#">John</a></li>
                        <li><a href="#">Martina</a></li>
                        <li><a href="#">Matthew</a></li>
                        <li><a href="#">Olivia</a></li>
                        <li><a href="#">Owen</a></li>
                    </ul>
                </li>

                <li>
                    <span>Work colleagues</span>
                    <ul>
                        <li><a href="#">David</a></li>
                        <li><a href="#">Dennis</a></li>
                        <li><a href="#">Eliza</a></li>
                        <li><a href="#">Larry</a></li>
                        <li><a href="#">Lisa</a></li>
                        <li><a href="#">Michael</a></li>
                        <li><a href="#">Rachelle</a></li>
                        <li><a href="#">Rick</a></li>
                    </ul>
                </li>
            </ul>
        </nav>
share|improve this question
add comment

1 Answer 1

up vote 0 down vote accepted

This should do it for you.. (UNTESTED)

Create a file in your theme folder called nav-menu-walker.php and include this file in your theme functions.php file.

nav-menu-walker.php

class My_Nav_Menu_Walker extends Walker_Nav_Menu {

    function start_el( &$output, $item, $depth = 0, $args, $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 ) . '"' : '';

        $item_output = $args->before;

        $output .= $indent . '<li' . $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 ( $args->has_children ) {

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

        } else {

            $item_output .= '<span>';
            $item_output .= apply_filters( 'the_title', $item->title, $item->ID );
            $item_output .= '</span>';         

        }

        $item_output .= $args->after;

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

    }

    function display_element($element, &$children_elements, $max_depth, $depth=0, $args, &$output) {
        $id_field = $this->db_fields['id'];
        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
        }
        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }    

}

Then call your wp_nav_menu() function with the walker.. e.g.

        <?php 
            wp_nav_menu(
                array(
                    'theme_location'    =>  'primary-menu',
                    'walker'            =>  new My_Nav_Menu_Walker()
                )
            ); 
        ?>

You may have to tweak the arguments to work with your theme obviously..

give that a go!

share|improve this answer
    
Great! Thank you so much! I'll test it later today and report back. Also, would you advise including the custom walker code by including a separate php file rather than including the code directly into functions.php file to keep it cleaner? Or is there a technical reason for this? –  user1001657 Aug 21 '13 at 11:32
    
No worries, hopefully it should work, I had butchered it from another project I worked on before ... Erm.. Entirely up to you really about the file, Me, personally I would keep it separate but it is entirely up to you.. –  Nathan Fitzgerald Aug 21 '13 at 11:54
    
OK, just dropped it in and had some issues but gave your code a run down and saw that it was the wrong way around, it was wrapping the everything that DIDN'T have a child in the span tags. I changed that around and all good! Got a couple of styling bugs but I don't think they're related to the walker in anyway. Again, massive thanks! –  user1001657 Aug 21 '13 at 14:02
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.