Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Extended Walker class for use with the Twitter Bootstrap toolkit Dropdown menus in Wordpress.

View functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
<?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;
?>
View functions.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<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>

sweet!

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

Cheers for this. :)

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

THX, saved me couple of hours coding

can we make this to unlimited level of dropdown menu?

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

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

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!

Good job dude!

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

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

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?

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

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

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'); ?

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

Kick ass, thanks so much for this.

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

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....

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

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

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

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

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" );

});

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
Something went wrong with that request. Please try again.