Skip to content

Instantly share code, notes, and snippets.

@PlanBrewski
Last active November 22, 2017 16:41
Show Gist options
  • Save PlanBrewski/6358588 to your computer and use it in GitHub Desktop.
Save PlanBrewski/6358588 to your computer and use it in GitHub Desktop.
wp_bootstrap_navwalker 1.4.4 for Twitter Bootstrap 2.3.2

wp-bootstrap-navwalker

A custom WordPress nav walker class to implement the Twitter Bootstrap 2.3.2 (https://github.com/twitter/bootstrap/) navigation style in a custom theme using the WordPress built in menu manager.

Extras

NOTE

This is a utility class that is intended to format your WordPress theme menu with the correct syntax and classes to utilize the Twitter Bootstrap dropdown navigation, and does not include the required Bootstrap JS files. You will have to include them manually.

Installation

Place wp_bootstrap_navwalker.php in your WordPress theme folder /wp-content/your-theme/

Open your WordPress themes functions.php file /wp-content/your-theme/functions.php and add the following code:

// Register Custom Navigation Walker
require_once('wp_bootstrap_navwalker.php');

Usage

Update your wp_nav_menu() function to use the new walker by adding a "walker" item to the wp_nav_menu array.

<?php 
  wp_nav_menu( array(
		'menu'		 => 'top_menu',
		'depth'		 => 2,
		'container'	 => false,
		'menu_class' => 'nav',
		'fallback_cb' => 'wp_page_menu',
		//Process nav menu using our custom nav walker
		'walker' => new wp_bootstrap_navwalker())
	);
?>

Your menu will now be formatted with the correct syntax and classes to implement Twitter Bootstrap dropdown navigation.

To change your menu style add Bootstrap nav class names to the menu_class declaration.

<?php 
	wp_nav_menu( array(
		'menu'		 => 'side_menu',
		'depth'		 => 1,
		'container'	 => false,
		'menu_class' => 'nav nav-tabs nav-stacked',
		'fallback_cb' => 'wp_page_menu',
		//Process nav menu using our custom nav walker
		'walker' => new wp_bootstrap_navwalker())
	);
?>

Review options in the Bootstrap docs for more information on nav classes http://twitter.github.com/bootstrap/components.html#navs

Extras

Extras

This script included the ability to add Bootstrap dividers and Nav Headers to your menus through the WordPress menu UI.

######Icons To add an Icon to your link simple place the full Glyphicon class name in the links Title Attribute field and the class will do the rest.

######Dividers Simply add a Link menu item with a URL of # and a Link Text of divider (case-insensitive so ‘divider’ or ‘Divider’ will both work ) and the class will do the rest.

Divider Example

You can also add a vertical divider by adding a Link menu item with a URL of # and a Link Text of divider-vertical

######Navigation Headers Adding a navigation header is very similar, add a new link with a URL of # and a Link Text of nav-header (it matches the Bootstrap CSS class so it's easy to remember). When the item is added use the Title Attribute field to set your header text and the class will do the rest.

Header Example

Changelog

1.4.4:

  • Updated Strict Standards Declarations

1.4.3:

  • Added support for vertical dividers (Thanks to @pattonwebz for the suggestion)

1.4.2:

  • Removed redundant code from display_element by using function from parent class (Thanks to @sebakerckhof for the suggestion)

1.4.1:

  • Updated class & file names from twitter_bootstrap_nav_walker to wp_bootstrap_navwalker match repository.
  • Licence now GPL-2.0+ to match WordPress.
  • Added a copy of the GPL-2.0+ Licence.
  • Added additional code comments to explain how the extras are processed.

1.4:

  • Added support Glyphicons

1.3:

  • Added support for nav-header's (Thanks to @nerdworker for the suggestion)

1.2.2:

  • Fixed double </li> issue on divider rows (thanks to @wzub for submitting the issue)

1.2.1:

  • Updated caret output logic for Bootstrap 2.2 CSS changes.

1.2:

  • Updated the class to work for all Bootstrap menu types. nav-tabs, nav-pills, nav-stacked, nav-list, navbar and dropdowns are all supported.
  • Added ability to add dividers to dropdown menus by adding a menu item with the label of “divider” (case-insensitive)
  • Added support for multiple dropdown levels (thanks to a Pull Requests from @jmz)
  • Moved dropdown-toggle class declaration from parent <li> to <a> to match Bootstraps official documentation

1.1:

  • Added WordPress Core refrence comments to help understand what functions are overridden
  • Fixed double class declaration on dropdown parents
  • Moved dropdown class declaration from a to parent li

1.0:

  • Initial Commit
<?php
/**
* Class Name: wp_bootstrap_navwalker
* GitHub URI: https://github.com/twittem/wp-bootstrap-navwalker
* Description: A custom WordPress nav walker class to implement the Twitter Bootstrap 2.3.2 navigation style in a custom theme using the WordPress built in menu manager.
* Version: 1.4.4
* Author: Edward McIntyre - @twittem
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
*/
class wp_bootstrap_navwalker extends Walker_Nav_Menu {
/**
* @see Walker::start_lvl()
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of page. Used for padding.
*/
function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "\n$indent<ul class=\" dropdown-menu\">\n";
}
/**
* @see Walker::start_el()
* @since 3.0.0
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. Used for padding.
* @param int $current_page Menu item ID.
* @param object $args
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
/**
* Dividers & Headers
* ==================
* Determine whether the item is a Divider, Header, or regular menu item.
* To prevent errors we use the strcasecmp() function to so a comparison
* that is not case sensitive. The strcasecmp() function returns a 0 if
* the strings are equal.
*/
if (strcasecmp($item->title, 'divider') == 0) {
// Item is a Divider
$output .= $indent . '<li class="divider">';
} else if (strcasecmp($item->title, 'divider-vertical') == 0) {
// Item is a Vertical Divider
$output .= $indent . '<li class="divider-vertical">';
} else if (strcasecmp($item->title, 'nav-header') == 0) {
// Item is a Header
$output .= $indent . '<li class="nav-header">' . esc_attr( $item->attr_title );
} else {
$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 ) );
//If item has_children add dropdown class to li
if($args->has_children) {
$class_names .= ' dropdown';
}
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $value . $class_names .'>';
$atts = array();
$atts['title'] = ! empty( $item->title ) ? $item->title : '';
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
$atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
//If item has_children add atts to a
if($args->has_children) {
$atts['href'] = '#';
$atts['class'] = 'dropdown-toggle';
} else {
$atts['href'] = ! empty( $item->url ) ? $item->url : '';
}
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
$item_output = $args->before;
/*
* Glyphicons
* ===========
* Since the the menu item is NOT a Divider or Header we check the see
* if there is a value in the attr_title property. If the attr_title
* property is NOT null we apply it as the class name for the glyphicon.
*/
if(! empty( $item->attr_title )){
$item_output .= '<a'. $attributes .'><i class="' . esc_attr( $item->attr_title ) . '"></i>&nbsp;';
} else {
$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) ? ' <span class="caret"></span></a>' : '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
/**
* Traverse elements to create list from elements.
*
* Display one element if the element doesn't have any children otherwise,
* display the element and its children. Will only traverse up to the max
* depth and no ignore elements under that depth.
*
* This method shouldn't be called directly, use the walk() method instead.
*
* @see Walker::start_el()
* @since 2.5.0
*
* @param object $element Data object
* @param array $children_elements List of elements to continue traversing.
* @param int $max_depth Max depth to traverse.
* @param int $depth Depth of current element.
* @param array $args
* @param string $output Passed by reference. Used to append additional content.
* @return null Null on failure with no changes to parameters.
*/
function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
if ( !$element ) {
return;
}
$id_field = $this->db_fields['id'];
//display this element
if ( is_object( $args[0] ) ) {
$args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
}
parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment