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.

Im working with a project where i want the wp_nav_menu to output other css classes for current_page, current_ancestor and remove other stuff like page-id and menu-id.

I have get some stuff working like remove the unessesary classes and id:s using a custom Walker. But i cant get the current_ancestor to change to another class.

here is what i have come up with until now:

class Clean_Walker extends Walker_Nav_Menu 
{

    /**
     * @see Walker::start_el()
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Menu item data object.
     * @param int $depth Depth of menu item. Used for padding.
     * @param int $current_page Menu item ID.
     * @param object $args
     */

    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) 
    {
        global $wp_query;

        $class_names = $value = '';

        $classes[] = ( $item->current ) ? 'sel' : '';


        // $current_classes = array(
        //     'current-menu-item',
        //     'current-menu-parent',
        //     'current-menu-ancestor',
        //     'current_page_item',
        //     'current_page_parent',
        //     'current_page_ancestor'
        // );

        // foreach ($current_classes as $current_class )
        //  {
        //     if ( in_array( $current_class, $classes ) ) 
        //     {
        //         $classes[] = "active";
        //         break;
        //     }
        // }


        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );

        $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';


        $output .= '<li'. $class_names .'>';

        $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->title .' '. $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        ) .'"' : '';


        $attribute  = ! empty( $item->attr_title ) ? '<span>' . esc_attr( $item->attr_title ) . '</span>' : '';

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

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

I also needed the attribute-field to be inside a span for some styling. So the poblem is that i need to change "current_ancestor" to the class sel.

The class sel are working on a "single-page" so the only problem comes when im one lvl deeper.

I have search WPSE but no luck. Thanks!

share|improve this question
    
Do you mean current_item_ancestor? –  toscho Feb 3 '13 at 17:43
add comment

2 Answers

up vote 2 down vote accepted

I believe the current-ancestor etc. classes are not added by the walker itself, but rather by wp_nav_menu which is calling _wp_menu_item_classes_by_context. Thus, your best bet is probably to add a filter to nav_menu_css_class and remove/replace current-* classes as needed. In its most basic form, something like:

function my_navigation_class($classes, $item){
    foreach ($classes as $idx => $class) {
        if ($class == 'current_ancestor') {
            $classes[$idx] = 'sel';
        }
    }
    return $classes;
}
add_filter('nav_menu_css_class' , 'my_navigation_class' , 10 , 2);
share|improve this answer
    
This worked for me now :)! Thanks! –  Pontus Abrahamsson Feb 6 '13 at 1:06
add comment

Removes ids and classes except those from $current_indicators array. You can easily add/remove classes there. Then apply @Simon's filter.

// based on http://snipplr.com/view/58549/
class Clnr_Walker_Nav_Menu extends Walker_Nav_Menu {
    function start_el(&$output, $item, $depth, $args) {
        //~ pre($item);
        global $wp_query;
        $indent = ($depth) ? str_repeat('\t',$depth) : '';
        $class_names = '';
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        $current_indicators = array(
            'current-menu-item',
            'current-menu-parent',
            'current-menu-ancestor',
            'current_page_item',
            'current_page_parent',
            'current-page-ancestor' // see Feb 20 update below
        );
        $newClasses = array();
        foreach($classes as $el) {
            if( in_array($el, $current_indicators) ) {
                array_push($newClasses, $el);
            }
        }
        $class_names = join( ' ', apply_filters('nav_menu_css_class', array_filter($newClasses), $item) );

        $output .= $indent . '<li class="' . $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($depth != 0) {
            //children stuff, maybe you'd like to store the submenu's somewhere?
        }

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

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

Updated (February 20):

There seems to be a bug in Wordpress 3.5.1 (at least). There is no such class as current_page_ancestor (underscore-separated) any more, it's current-page-ancestor (dash-separated) instead. I don't have the time right now to figure out the cause of this, but looks like it is in _wp_menu_item_classes_by_context() inside /wp-includes/nav-menu-template.php.

share|improve this answer
    
Thank you @Max, this helped alot! –  Pontus Abrahamsson Feb 6 '13 at 1:06
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.