Update #1: Using Twitter Bootstrap Dropdown Menus with WordPress

 

02/17/12 – Updated! Click here for the latest code. After some testing, there were a few fixed to clean up the HTML.

02/13/12 – This code has been updated to work with Twitter Bootstrap 2.0. Click here to see the latest update.

01/12/12 – All fixed, see my new post: Update #2: Using Twitter Bootstrap Dropdown Menus with WordPress

 


01/11/12 – It seems that last_result didn’t work as I thought it did and won’t work in all situations, so I need to revisit this. I absentmindedly left my laptop power cable at work, so it may be a day or so.


In my first post, I wrote an extended walker class for using Twitter Bootstrap dropdown menus in WordPress without a bunch of hackarounds. Originally, I was using a ‘search and replace’ method for this, which worked, but it was pretty obvious to me that it wasn’t the best way to do it.

I replaced it now with a more true-to-WordPress way to do it, which I think will be more future-proof.

The reason that this is a bit tricky is that WordPress really doesn’t have a has_children type of property available inside of the start_el function. Instead of doing ‘search and replace’, inside of the start_el function, I pull the last_result, which will a cached copy of the menu query. I’ve seen others run a new query, but I didn’t want to run a new database query for every single menu item if I didn’t have to. I then run through this and check for any entry where the current menu item $item->ID is the parent. I set a has_children boolean so that once I have proof that it’s a daddy (or mommy), I don’t waste effort checking all of the other entries. I then make sure that if it’s the current page it get’s an active class, and apply the dropdown-toggle class to the appropriate link element.

Get the gist – https://gist.github.com/1597994

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 ) {
		global $wpdb;
		$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

		$li_attributes = '';
		$has_children = false;
		$class_names = $value = '';

		$classes = empty( $item->classes ) ? array() : (array) $item->classes;
		$classes[] = 'menu-item-' . $item->ID;
		$classes[] = ($item->current) ? 'active' : '';

		foreach($wpdb->last_result as $a) {
			if ( $a->meta_key == '_menu_item_menu_item_parent' && $a->meta_value == $item->ID && $has_children == false){
				$has_children = true;
				$classes[] = 'dropdown';
				$li_attributes .= 'data-dropdown="dropdown"';
				break;
			}
		}

		$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 .= ($has_children) 				? ' class="dropdown-toggle"' 					   : '';

		$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 .= '</a>';
		$item_output .= $args->after;

		$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
	}

}
Advertisements

2 responses

  1. […] I’ve since found a better way to handle these and posted a new post here. Bootstrap is a toolkit from Twitter designed to kickstart development of webapps and sites. It includes base CSS and HTML for typography, forms, buttons, tables, grids, navigation, and more. – twitter.github.com/bootstrap […]

  2. […] for the missing has_children parameter here, I’ve made some changes that get the previous extended walker class that I posted working in more (hopefully all) situations. In WordPress 3.4, this should be fixed […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: