1

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!

1
  • Do you mean current_item_ancestor?
    – fuxia
    Commented Feb 3, 2013 at 17:43

2 Answers 2

3

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);
0
2

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.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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