Skip to content

Instantly share code, notes, and snippets.

@setola
Forked from johnmegahan/functions.php
Last active September 25, 2020 18:29
Show Gist options
  • Select an option

  • Save setola/3765640 to your computer and use it in GitHub Desktop.

Select an option

Save setola/3765640 to your computer and use it in GitHub Desktop.
Extended Walker class for use with the Twitter Bootstrap toolkit Dropdown n-levels menus in Wordpress.
<?php
/**
* Extended Walker class for use with the
* Twitter Bootstrap toolkit Dropdown menus in Wordpress.
* Edited to support n-levels submenu.
* @author johnmegahan https://gist.github.com/1597994, Emanuele 'Tex' Tessore https://gist.github.com/3765640
* @license CC BY 4.0 https://creativecommons.org/licenses/by/4.0/
*/
class BootstrapNavMenuWalker extends Walker_Nav_Menu {
function start_lvl( &$output, $depth ) {
$indent = str_repeat( "\t", $depth );
$submenu = ($depth > 0) ? ' sub-menu' : '';
$output .= "\n$indent<ul class=\"dropdown-menu$submenu depth_$depth\">\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;
// managing divider: add divider class to an element to get a divider before it.
$divider_class_position = array_search('divider', $classes);
if($divider_class_position !== false){
$output .= "<li class=\"divider\"></li>\n";
unset($classes[$divider_class_position]);
}
$classes[] = ($args->has_children) ? 'dropdown' : '';
$classes[] = ($item->current || $item->current_item_ancestor) ? 'active' : '';
$classes[] = 'menu-item-' . $item->ID;
if($depth && $args->has_children){
$classes[] = 'dropdown-submenu';
}
$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 .= ($depth == 0 && $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 ) {
//v($element);
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);
}
}
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<?php
$args = array(
'theme_location' => 'top-bar',
'depth' => 0,
'container' => false,
'menu_class' => 'nav',
'walker' => new BootstrapNavMenuWalker()
);
wp_nav_menu($args);
?>
</div>
</div>
</div>
/**
* This code changes the default behavior of the navbar:
* now the submenu pops in when the user rolls his mouse
* over the parent level menu entry.
* Many tanks to Hanzi for this idea and code!
*/
jQuery(document).ready(function($) {
$('ul.nav li.dropdown, ul.nav li.dropdown-submenu').hover(function() {
$(this).find(' > .dropdown-menu').stop(true, true).delay(200).fadeIn();
}, function() {
$(this).find(' > .dropdown-menu').stop(true, true).delay(200).fadeOut();
});
});
@ivanfgautama
Copy link
Copy Markdown

ahh this one works great, shouldve check it before dropping a comment. shame on me :(

@Danimal713
Copy link
Copy Markdown

I have tried this several times and it just doesn't work.

@tyl3r
Copy link
Copy Markdown

tyl3r commented Jun 13, 2013

It works perfect, thank you for sharing!

@setola
Copy link
Copy Markdown
Author

setola commented Jun 27, 2013

@Danimal713 can you provide some information on what doesn't work for you?

@royalcreed1
Copy link
Copy Markdown

im having trouble implementing the open-on-mouseover. i saved the contents in open-on-mouseover.js and called it under the bootstrap.js script in the footer.php and it doesnt work.

@LachlanArthur
Copy link
Copy Markdown

Line 9 of the Javascript should be

        $(this).find(' > .dropdown-menu').stop(true, true).delay(200).fadeIn();

not

        $(this).find(' > .dropdown-menu, ').stop(true, true).delay(200).fadeIn();

@webwebby
Copy link
Copy Markdown

How to manually assign "active" class to some page tabs added from Menus in admin panel? So when you are on child page of a menu nav item, Its should be highlighted all the way as well.

@setola
Copy link
Copy Markdown
Author

setola commented Apr 9, 2014

@LachlanArthur Thank you for your bughunting :)

@Vbonelli
Copy link
Copy Markdown

Vbonelli commented Jul 7, 2016

Hi, It works but when I try below 768px resolution, it needs to be on click otherwise it does not work. How should I do it? Best regards,

@vladutilie
Copy link
Copy Markdown

Thank you so much! You are my save :)

@jaycbrf4
Copy link
Copy Markdown

WP 4.9 beta breaks the nav and shows empty a tags.
Also have to change container from false to ul.
No more menu id

@mohitupadhaya
Copy link
Copy Markdown

Thank You so much for sharing this code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment