Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Extended Walker class for use with the Twitter Bootstrap toolkit Dropdown menus in Wordpress.
<?php
add_action( 'after_setup_theme', 'bootstrap_setup' );
if ( ! function_exists( 'bootstrap_setup' ) ):
function bootstrap_setup(){
add_action( 'init', 'register_menu' );
function register_menu(){
register_nav_menu( 'top-bar', 'Bootstrap Top Menu' );
}
class Bootstrap_Walker_Nav_Menu extends Walker_Nav_Menu {
function start_lvl( &$output, $depth ) {
$indent = str_repeat( "\t", $depth );
$output .= "\n$indent<ul class=\"dropdown-menu\">\n";
}
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
$li_attributes = '';
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = ($args->has_children) ? 'dropdown' : '';
$classes[] = ($item->current || $item->current_item_ancestor) ? 'active' : '';
$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 ) . '"' : '';
$output .= $indent . '<li' . $id . $value . $class_names . $li_attributes . '>';
$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 .= ($args->has_children) ? ' class="dropdown-toggle" data-toggle="dropdown"' : '';
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
$item_output .= ($args->has_children) ? ' <b class="caret"></b></a>' : '</a>';
$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 ) {
if ( !$element )
return;
$id_field = $this->db_fields['id'];
//display this element
if ( is_array( $args[0] ) )
$args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] );
else if ( is_object( $args[0] ) )
$args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
$cb_args = array_merge( array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'start_el'), $cb_args);
$id = $element->$id_field;
// descend only when the depth is right and there are childrens for this element
if ( ($max_depth == 0 || $max_depth > $depth+1 ) && isset( $children_elements[$id]) ) {
foreach( $children_elements[ $id ] as $child ){
if ( !isset($newlevel) ) {
$newlevel = true;
//start the child delimiter
$cb_args = array_merge( array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'start_lvl'), $cb_args);
}
$this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
}
unset( $children_elements[ $id ] );
}
if ( isset($newlevel) && $newlevel ){
//end the child delimiter
$cb_args = array_merge( array(&$output, $depth), $args);
call_user_func_array(array(&$this, 'end_lvl'), $cb_args);
}
//end this element
$cb_args = array_merge( array(&$output, $element, $depth), $args);
call_user_func_array(array(&$this, 'end_el'), $cb_args);
}
}
}
endif;
?>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<?php
$args = array(
'theme_location' => 'top-bar',
'depth' => 2,
'container' => false,
'menu_class' => 'nav',
'walker' => new Bootstrap_Walker_Nav_Menu()
);
wp_nav_menu($args);
?>
</div>
</div>
</div>
@jimmyrosen

This comment has been minimized.

Copy link

commented Jun 1, 2012

sweet!

@martajohnsson

This comment has been minimized.

Copy link

commented Sep 3, 2012

Hello, I can't get it work:-(

@hellquist

This comment has been minimized.

Copy link

commented Sep 24, 2012

Cheers for this. :)

@ivanfgautama

This comment has been minimized.

Copy link

commented Sep 24, 2012

it works for 2 level of dropdown, but more than 2 level it doesnt seem to work,

@yourdesigncoza

This comment has been minimized.

Copy link

commented Oct 20, 2012

THX, saved me couple of hours coding

@Alipio123

This comment has been minimized.

Copy link

commented Oct 31, 2012

can we make this to unlimited level of dropdown menu?

because currently @ ivanfgautama "it works for 2 level of dropdown "

@AdamKyle

This comment has been minimized.

Copy link

commented Nov 26, 2012

@Alipio123 set the depth in the args array to 0 and there ya fo

@tszming

This comment has been minimized.

Copy link

commented Dec 1, 2012

One of the minor issue is the menu is not fully responsive, e.g. still presenting a layer on dropdown items on mobile devices (as compared to http://320press.com/wpbs/), but anyway, it is really a nice snippet and get the job done.

Thanks!

@shprink

This comment has been minimized.

Copy link

commented Jan 8, 2013

Good job dude!

@seomezshiva

This comment has been minimized.

Copy link

commented Jan 18, 2013

awesome job bro I like to implement this tutorial in SEOmez.com within few days...!!!

@larsemil

This comment has been minimized.

Copy link

commented Feb 2, 2013

Awesome! Saved me alot of work.

Allthough i dont get it to expand beyond second level('when having another dropdown in the first').
Any hints on what to do?

Here is my wp_nav_code:

               $args = array(
                    'theme_location' => 'top-bar',
                    'depth'      => 0,
                    'container'  => false,
                    'menu_class'     => 'nav',
                    'walker'     => new Bootstrap_Walker_Nav_Menu()
                );  

                wp_nav_menu($args);
@maronl

This comment has been minimized.

Copy link

commented Feb 7, 2013

uhm ... I'm doing my first work on Wordpress and so I'm still learning. I cannot make the extends Walker_Nav_Menu working as described above. if I try the code (but also all the other codes I found extending Wlaker_Nav_Menu) the result is an empty bullet list without any text/reference and also without sub-levels. something like

<div class="nav">
<ul>
<li class="menu-item-10" id="menu-item-10"><a></a></li>
<li class="menu-item-2" id="menu-item-2"><a></a></li>
<li class="menu-item-4" id="menu-item-4"><a></a></li>
</ul>
</div>

some tip to sort this out?

@thepauleh

This comment has been minimized.

Copy link

commented Feb 7, 2013

Are you setting the menu in the Wordpress Admin? When you only create the menu Wordpress falls back to a different menu function - you just need to tell it where to put each menu.

I can't figure out how to do this markdown stuff but basically for responsive:
button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"
span class="icon-bar">/span
span class="icon-bar">/span
span class="icon-bar">/span
/button
div class='nav-collapse collapse'
wp_nav_menu....
/div

@chrispaynter

This comment has been minimized.

Copy link

commented Feb 14, 2013

Great job man, this really saved me some time. Thanks.

@cynthusia

This comment has been minimized.

Copy link

commented Feb 15, 2013

I am having the same issue as lukennon. I switched from my custom theme to an untouched install of the "wordpress-bootstrap" theme to test and it still happens. I have tried:

'theme_location' => 'primary',

as well as the menu ID# and menu name and slug. But I still just get an empty bulleted list as described in lukennon's comment.

Just to confirm, I am supposed to replace what's in my functions.php from this comment // Menu output mods, to just before the line that says add_editor_style('editor-style.css'); ?

@borisgw

This comment has been minimized.

Copy link

commented Mar 5, 2013

Wow this is great, would buy you a beer if have international visa :P

@jyoseph

This comment has been minimized.

Copy link

commented Apr 2, 2013

Kick ass, thanks so much for this.

@MobsterGit

This comment has been minimized.

Copy link

commented May 1, 2013

I'm having issues with https. Any suggestions to remove the http:// from the menu? Thanks!

@richardmax

This comment has been minimized.

Copy link

commented May 23, 2013

Had the same issue as cynthusia and lukennon (+ hundreds of similar devs in other forums) - it was Appearance > Menu wasn't set! Duurrgggh but good to know....

@lwensveen

This comment has been minimized.

Copy link

commented Jun 26, 2013

Does anybody have a version that works with bootstrap 3 rc?

@joelalejandro

This comment has been minimized.

Copy link

commented Aug 25, 2013

I've made this work perfectly with Bootstrap 3.0.0. Thanks John!

@tommusrhodus

This comment has been minimized.

Copy link

commented Aug 26, 2013

Cheers John! Saved me a couple of hours, much appreciated!

@sebastienb

This comment has been minimized.

Copy link

commented Oct 11, 2013

Is there a way to make it work on mouse over to retain the function of the top level link ?

@apsolut

This comment has been minimized.

Copy link

commented Oct 22, 2013

3level - i got it working like this

//use Johns code and plus this jquery..

jQuery(".dropdown-menu li.dropdown-toggle").on("mouseenter", function () {

 jQuery(this).find( ".dropdown-menu").css({ "display": "block" }, "slow" );

}).on("mouseleave", function () {

jQuery(this).find( ".dropdown-menu").css({ "display": "none" }, "slow" );

});
@rbfuertes

This comment has been minimized.

Copy link

commented May 2, 2014

Good day Sir. my problem is notactive menu on 2 page the Home, and blog but the rest is active the about-us contact etc. The home is front-page.php and blog is index,php Thanks in advance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.