Skip to content

Instantly share code, notes, and snippets.

@awshout
Last active September 5, 2024 01:34
Show Gist options
  • Save awshout/3943026 to your computer and use it in GitHub Desktop.
Save awshout/3943026 to your computer and use it in GitHub Desktop.
WordPress Menu & Walker for ZURB's Foundation 4 Top Bar

Adding a Foundation Top Bar to WordPress

foundation-topbar-menu.php and foundation-topbar-walker.php should be required in the WordPress functions.php file.

The code in foundation-topbar.php should be added below the body tag in header.php

Setup a menu in WordPress admin under Appearance > Menus

Use the 'label' class on a menu item to create a menu section title

Foundation Top Bar Doc: http://foundation.zurb.com/docs/components/top-bar.html

<?php
add_theme_support('menus');
/**
* Register Menus
* http://codex.wordpress.org/Function_Reference/register_nav_menus#Examples
*/
register_nav_menus(array(
'top-bar-l' => 'Left Top Bar', // registers the menu in the WordPress admin menu editor
'top-bar-r' => 'Right Top Bar'
));
/**
* Left top bar
* http://codex.wordpress.org/Function_Reference/wp_nav_menu
*/
function foundation_top_bar_l() {
wp_nav_menu(array(
'container' => false, // remove nav container
'container_class' => '', // class of container
'menu' => '', // menu name
'menu_class' => 'top-bar-menu left', // adding custom nav class
'theme_location' => 'top-bar-l', // where it's located in the theme
'before' => '', // before each link <a>
'after' => '', // after each link </a>
'link_before' => '', // before each link text
'link_after' => '', // after each link text
'depth' => 5, // limit the depth of the nav
'fallback_cb' => false, // fallback function (see below)
'walker' => new top_bar_walker()
));
}
/**
* Right top bar
*/
function foundation_top_bar_r() {
wp_nav_menu(array(
'container' => false, // remove nav container
'container_class' => '', // class of container
'menu' => '', // menu name
'menu_class' => 'top-bar-menu right', // adding custom nav class
'theme_location' => 'top-bar-r', // where it's located in the theme
'before' => '', // before each link <a>
'after' => '', // after each link </a>
'link_before' => '', // before each link text
'link_after' => '', // after each link text
'depth' => 5, // limit the depth of the nav
'fallback_cb' => false, // fallback function (see below)
'walker' => new top_bar_walker()
));
}
?>
<?php
/**
* Customize the output of menus for Foundation top bar
*/
class top_bar_walker extends Walker_Nav_Menu {
function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
$element->has_children = !empty( $children_elements[$element->ID] );
$element->classes[] = ( $element->current || $element->current_item_ancestor ) ? 'active' : '';
$element->classes[] = ( $element->has_children ) ? 'has-dropdown' : '';
parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
}
function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
$item_html = '';
parent::start_el( $item_html, $object, $depth, $args );
$output .= ( $depth == 0 ) ? '<li class="divider"></li>' : '';
$classes = empty( $object->classes ) ? array() : (array) $object->classes;
if( in_array('label', $classes) ) {
$output .= '<li class="divider"></li>';
$item_html = preg_replace( '/<a[^>]*>(.*)<\/a>/iU', '<label>$1</label>', $item_html );
}
if ( in_array('divider', $classes) ) {
$item_html = preg_replace( '/<a[^>]*>( .* )<\/a>/iU', '', $item_html );
}
$output .= $item_html;
}
function start_lvl( &$output, $depth = 0, $args = array() ) {
$output .= "\n<ul class=\"sub-menu dropdown\">\n";
}
}
?>
<div class="top-bar-container fixed contain-to-grid">
<nav class="top-bar">
<ul class="title-area">
<li class="name">
<h1><a href="<?php echo home_url(); ?>"><?php bloginfo('name'); ?></a></h1>
</li>
<li class="toggle-topbar menu-icon"><a href="#"><span>Menu</span></a></li>
</ul>
<section class="top-bar-section">
<?php foundation_top_bar_l(); ?>
<?php foundation_top_bar_r(); ?>
</section>
</nav>
</div>
@captaincoffee
Copy link

Can anyone point to a functioning starter theme that incorporates this? It would be very helpful to see exactly how this is implemented within the various files. Especially for us beginners. Thanks.

@patrick-wc
Copy link

Excellent!

For the search form, or anything at the end of the menu I used this code:

add_filter( 'wp_nav_menu_items', 'your_custom_menu_item', 10, 2 );
function your_custom_menu_item ( $items, $args ) {
    if ($args->theme_location == 'top-bar-r') {
        $items .= '<li class="has-form">';
        $items .= '    <form role="search" class="searchform" method="get" action="' . home_url() . '">';
        $items .= '        <div>';
        $items .= '            <input id="sf-s" name="s" value="' . get_search_query() . '" type="text" onkeyup="buttonUp()" placeholder="Search..." />';
        $items .= '            <input id="sf-searchsubmit" type="submit" value="" />';
        $items .= '            <span class="search-icon-toggle" title="Click to Search"></span>';
        $items .= '        </div>';
        $items .= '    </form>';
        $items .= '</li>';
    }
    return $items;
}

(Obviously use whatever HTML you need)

@sabotawsh
Copy link

I'm trying to add the description

if ( !empty( $item->description ) ) {
    $item_html .= '<span class="description">' . esc_attr( $item->description ) . '</span>';
}

But I'm unsure of where to place it amongst all this:

/ CUSTOMIZE THE OUTPUT OF MENUS FOR FOUNDATION TOP BAR 
class top_bar_walker extends Walker_Nav_Menu {

    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $element->has_children = !empty( $children_elements[$element->ID] );
        $element->classes[] = ( $element->current || $element->current_item_ancestor ) ? 'active' : '';
        $element->classes[] = ( $element->has_children ) ? 'has-dropdown' : '';

        parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {
        $item_html = '';
        parent::start_el( $item_html, $object, $depth, $args ); 

        // $output .= ( $depth == 0 ) ? '<li class="divider"></li>' : '';

        $classes = empty( $object->classes ) ? array() : (array) $object->classes;  

        if( in_array('label', $classes) ) {
            $output .= '<li class="divider"></li>';
            $item_html = preg_replace( '/<a[^>]*>(.*)<\/a>/iU', '<label>$1</label>', $item_html );
        }

    if ( in_array('divider', $classes) ) {
        $item_html = preg_replace( '/<a[^>]*>( .* )<\/a>/iU', '', $item_html );
    }

        $output .= $item_html;
    }

    function start_lvl( &$output, $depth = 0, $args = array() ) {
        $output .= "\n<ul class=\"sub-menu dropdown\">\n";
    }

}

And also don't I have to add it to call it out in my arguments with something like this?

'walker' => new description_walker()

So far everywhere I've tested adding it, has failed.

@Warkman
Copy link

Warkman commented Nov 27, 2014

The fix to have the dropdown work in foundation 5 (WP 4.1) is change in foundation4-topbar.php file, line 2:

from
<nav class="top-bar">
to
<nav class="top-bar" data-topbar>

Copy link

ghost commented Dec 30, 2014

thank you for this awshout, it helped a lot!

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