Skip to content

Instantly share code, notes, and snippets.

@awshout
Last active May 5, 2020 20:46
Show Gist options
  • Save awshout/5375157 to your computer and use it in GitHub Desktop.
Save awshout/5375157 to your computer and use it in GitHub Desktop.
WordPress Menu & Walker for ZURB's Foundation 4 Sections
Adding a Foundation Horizontal or Vertical Section to WordPress as a menu
---
foundation-section-menu.php and foundation-section-walker.php should be included in the WordPress functions.php file.
The code in foundation-sectionr.php should be added to a template (ie. header.php)
Note: replace horizontal with vertical for the vertical section
Setup a menu in WordPress admin under Appearance > Menus
Foundation Top Bar Doc: http://foundation.zurb.com/docs/components/section.html
<?php
add_theme_support('menus');
/**
* http://codex.wordpress.org/Function_Reference/register_nav_menus#Examples
*/
register_nav_menus(array(
'main-menu' => 'Main Menu',
));
/**
* http://codex.wordpress.org/Function_Reference/wp_nav_menu
*/
function foundation_section_menu() {
$defaults = array(
'theme_location' => 'main-menu',
'menu' => '',
'container' => false,
'container_class' => '',
'container_id' => '',
'menu_class' => 'nav-bar',
'menu_id' => '',
'echo' => true,
'fallback_cb' => false,
'before' => '',
'after' => '',
'link_before' => '',
'link_after' => '',
'items_wrap' => '%3$s',
'depth' => 2,
'walker' => new Section_Nav_Walker()
);
wp_nav_menu( $defaults );
}
?>
<?php
/**
* Section Nav Walker
* used for accordion side menu and horizontal main menu
*/
class Section_Nav_Walker extends Walker_Nav_Menu {
/**
* @see Walker_Nav_Menu::start_lvl()
*
* @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() ) {
$output .= '<div class="content" data-section-content><ul class="side-nav">';
}
/**
* @see Walker::end_lvl()
*
* @param string $output Passed by reference. Used to append additional content.
* @param int $depth Depth of page. Used for padding.
*/
function end_lvl( &$output, $depth = 0, $args = array() ) {
// close .side-nav .content and .section
$output .= '</ul></div></div>';
}
/**
* @see Walker_Nav_Menu::start_el()
*
* @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 object $args
*/
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
$class_names = $value = '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
$classes[] = ( $depth == 0 ) ? 'title' : '';
$classes[] = ( $args->has_children ) ? 'has-dropdown' : '';
$classes[] = ( in_array('current-menu-item', $classes) && !in_array('active', $classes) ) ? 'active' : '';
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$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 ) . '"' : '';
// create sections
//$section_class = ( $depth == 0 && in_array('active', $classes) ) ? 'section active' : 'section';
$section_class = 'section';
$output .= ( $depth == 0 ) ? '<div class="' . $section_class . '">' : '';
// if top level use p.title else use li in dropdown
$output .= ( $depth == 0 ) ? '<p data-section-title' . $id . $value . $class_names .'>' : '<li' . $id . $value . $class_names .'>';
$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 ) . '"' : '';
// if top level and has dropdown do not use url
if ( $depth == 0 && $args->has_children ) {
$attributes .= ' href="#"';
}
// else use url
elseif ( !empty( $item->url ) ) {
$attributes .= ' href="' . esc_attr( $item->url ) . '"';
}
$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;
// close .section if there is no dropdown
$item_output .= ( $depth == 0 && !$args->has_children ) ? '</div>' : '';
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
/**
* @see Walker::end_el()
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Page data object. Not used.
* @param int $depth Depth of page. Not Used.
*/
function end_el( &$output, $item, $depth = 0, $args = array() ) {
if ( $depth > 0 ) {
$output .= "</li>";
}
}
function display_element($element, &$children_elements, $max_depth, $depth=0, $args, &$output) {
$id_field = $this->db_fields['id'];
if (is_object($args[0])) {
$args[0]->has_children = !empty($children_elements[$element->$id_field]);
}
$element->classes[] = ($element->current || $element->current_item_ancestor) ? 'active' : '';
parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
}
}
?>
<nav id="menu">
<div class="section-container horizontal-nav" data-section="horizontal-nav">
<?php foundation_section_menu(); ?>
</div>
</nav>
@kelicia
Copy link

kelicia commented Apr 21, 2013

double awesome! It is working splendidly.

@themarcthomas
Copy link

This is so useful – how can I also include grandchildren of the parent item? Currently, it breaks (closes the list too early) the menu when there is more than one set of grandchildren.

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