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.

Is there anyway, using the custom menu css classes that are turned on in the option, to apply those via a walker function to the span instead of the li's?

My custom walker:

class ik_walker extends Walker_Nav_Menu {

    function start_lvl(&$output, $depth) {
        $GLOBALS['ik_walker_counter'] = 0;
        $output .= '<nav class="site-navigation" role="navigation">'.
            '<ul>';
    }

    function end_lvl(&$output, $depth) {
        $output .= '</ul>'.
            '<button id="menu" class="menu-button" type="button" role="button" aria-label="Menu Toggle">'.
            '<span class="icon-menu"></span>'.
            '</button>'.
            '</div>';
    }

    function start_el(&$output, $item, $depth, $args) {
        global $wp_query;
        $GLOBALS['ik_walker_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 ) . '"';
        $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        ) .'"' : '';
        $attributes .= ' class="c'.$GLOBALS['ik_walker_counter'].'"';
        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        if(strlen($item->description)>2){ $item_output .= '<br /><span class="sub">' . $item->description . '</span>'; }
        $item_output .= '<span class="'. $item->classes .'"></span>';
        $item_output .= '</a>';
        $item_output .= $args->after;
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

I was trying this:

$item_output .= '<span class="'. $item->classes .'"></span>';

But i just get:

<span class="Array"></span>

This would enable me to control the class via the menu css option so that each can have a unique class.

Any help would be much appreciated.

share|improve this question
1  
I don't see the need to add the same classes to the span. Can't you just style each span as li.menu-class1 span, li.menu-class2 span, etc? –  helgatheviking Jan 11 at 14:04
add comment

1 Answer

up vote 1 down vote accepted

Joining all class names:

Please try:

$item_output .= sprintf( '<span class="%s"></span>', join( ' ', $item->classes ) );

instead of

$item_output .= '<span class="'. $item->classes .'"></span>';

to join the array elements of $item->classes into a string.

If you add for example aaa bbb ccc to an item's class text field, it will show up like this:

 Array
                (
                    [0] => aaa
                    [1] => bbb
                    [2] => ccc
                    [3] => menu-item
                    [4] => menu-item-type-post_type
                    [5] => menu-item-object-post
                )

Filter out class names:

If you want to eliminate all class names containing item you can use:

$item_output .= sprintf( '<span class="%s"></span>', 
                          join( ' ', array_filter( $item->classes, 'custom_filter' ) ) 
                );

where the array filter callback is

/**
 * Only keep items not containing the string 'item'
 *
 * @param string $var
 * @return string $var | '' Empty if contains 'item'
 */

function custom_filter( $var )
{
    return ( FALSE === strpos( $var, 'item' ) ) ? $var : ''; 
}

ps: I think we are save with eliminating class names containg item, else you can modify it to your needs

share|improve this answer
    
This works thanks, however it does include not just the custom one i set in the admin, but also things like: menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-home - is there a way to just include only the custom class i set? –  Mat-visual Jan 11 at 15:18
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.