Ask your WordPress questions! Pay money and get answers fast! (more info)

nav menu walker as select dropdown

  • SOLVED

this code nearly does what I want, but it indents subpages inside the parents <option> tag which causes html validation errors
I think I need to set $to_depth to -1, but can't figure it out.


function golden_mobile_menu_secondary(){
wp_nav_menu(array(
'theme_location' => 'secondary', // your theme location here
'walker' => new Walker_Nav_Menu_Dropdown(),
'items_wrap' => '<select id="sec-selector" name="sec-selector" onchange="location.href = document.getElementById(\'sec-selector\').value;">%3$s</select>',
'container_id' => 'mobile_menu_secondary'
));
}

class Walker_Nav_Menu_Dropdown extends Walker_Nav_Menu{
var $to_depth = -1;
function start_lvl(&$output, $depth){
$indent = str_repeat("\t", $depth); // don't output children opening tag (`<ul>`)
}

function end_lvl(&$output, $depth){
$indent = str_repeat("\t", $depth); // don't output children closing tag
}

function start_el(&$output, $item, $depth, $args){
// add spacing to the title based on the depth
$item->title = str_repeat("&nbsp;", $depth * 4).$item->title;

parent::start_el(&$output, $item, $depth, $args);

// no point redefining this method too, we just replace the li tag...
$output = str_replace('<li', '<option value="' . $item->url . '"', $output);
}

function end_el(&$output, $item, $depth){
$output .= "</option>\n"; // replace closing </li> with the option tag
}
}

Answers (2)

2011-10-04

Jurre Hanema answers:

Try this!


class Walker_Nav_Menu_Dropdown extends Walker_Nav_Menu{

var $to_depth = -1;

function start_lvl(&$output, $depth){

$output .= '</option>';

}



function end_lvl(&$output, $depth){

$indent = str_repeat("\t", $depth); // don't output children closing tag

}



function start_el(&$output, $item, $depth, $args){
$indent = ( $depth ) ? str_repeat( "&nbsp;", $depth * 4 ) : '';

$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="' . esc_attr( $class_names ) . '"';

$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

$value = ' value="'. $item->url .'"';

$output .= '<option'.$id.$value.$class_names.'>';

$item_output = $args->before;
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;

$output .= $indent.$item_output;
}



function end_el(&$output, $item, $depth){

if(substr($output, -9) != '</option>')
$output .= "</option>"; // replace closing </li> with the option tag

}

}


paul de wouters comments:

thanks that seems to work! good job

2011-10-04

John Cotton answers:

My guess is that this line needs changing:

$item->title = str_repeat("&nbsp;", $depth * 4).$item->title;

Try
$item->title = $item->title;

You might also want to remove the '\t' lines as these are just added unnecessary tabs.