Skip to content

Instantly share code, notes, and snippets.

@awshout
Last active August 19, 2023 02:44
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>
@chris-roerig
Copy link

To fix the drop down issue, add "not-click" class to the "has-dropdown" line.

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 not-click' : '';

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

....

@genuino2
Copy link

genuino2 commented Oct 2, 2013

This is the WALKER code with all fix


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 not-click' : '';
    
        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) ? '
  • ' : ''; $classes = empty($object->classes) ? array() : (array) $object->classes; if(in_array('label', $classes)) { $output .= '
  • '; $item_html = preg_replace('/]*>(.*)<\/a>/iU', '$1', $item_html); } if ( in_array('divider', $classes) ) { $item_html = preg_replace( '/]*>( .* )<\/a>/iU', '', $item_html ); } $output .= $item_html; } function start_lvl( &$output, $depth = 0, $args = array() ) { $output .= "\n
      \n"; } }

    @holisticnetworking
    Copy link

    "Notice: Indirect modification of overloaded property WP_Post::$classes has no effect in ../functions.php on line 566"
    "Notice: Trying to get property of non-object in .../wp-includes/nav-menu-template.php on line 88"

    Any guesses? WordPress 3.5.2

    @holisticnetworking
    Copy link

    This hack fixed the above problem for me, though for some reason, I still can't get the menus to display correctly:

    $element->has_children = !empty($children_elements[$element->ID]);
    $classes = $element->classes;
    $classes[] = ($element->current || $element->current_item_ancestor) ? 'active' : '';
    $classes[] = ($element->has_children) ? 'has-dropdown' : '';
    $element->classes = $classes;

    @ScottGrodberg
    Copy link

    The "not-click" class is added by foundation.topbar.js on-the-fly when the menu is in "hover" mode. If you're not seeing the "not-click" class applied to your parent li's at runtime, then maybe check for jQuery conflict like the author said or any other errors in your console. Might save more aggravation later..

    @daniel7912
    Copy link

    Thanks a lot for this, exactly what I was looking for. Saved me loads of time!

    @rffaguiar
    Copy link

    Just as I thought! I was trying to make it work and I thought "someone in the world must have solved this already".
    Put this star at your code.

    @fertchen
    Copy link

    Thanks a lot for sharing this. But...I just can't get this to work. Granted, I don't know a lot about these things. I have done as you advised, included the files, added the script as advised at http://foundation.zurb.com/docs/components/top-bar.html, added the CSS and the menu bar does indeed appear.
    It also turns into the mobile menu when I decrease the browser width (Chrome).

    But upon clicking on the menu, it does not drop down (I did use the code with the fixes by . How can I troubleshoot this?

    I am using this for a Wordpress installtion with a Twenty Twelve Child Theme.

    @sailorsamoor
    Copy link

    Thank you.

    @pulla
    Copy link

    pulla commented Nov 25, 2013

    is there any update for foundation 5? it's not working with foundation 5 now.
    Thanks :)

    @pulla
    Copy link

    pulla commented Nov 25, 2013

    oops just found data-topbar .. it works great

    @thanhrossi
    Copy link

    Not working with Foundation 5? hicc :?

    @PaoloVi
    Copy link

    PaoloVi commented Dec 6, 2013

    Works for me with foundation 5 and Wordpress 3.7.1.
    For drop down I added "not-click" like 808chris suggested. Works fine. Thank you

    @StefsterNYC
    Copy link

    Ah this is awesome. I'm so close. Nothing showing up though. Using F5 but so far no luck. What am I missing?

    1. Both .php files are in a inc folder.
    2. Markup in header
    3. Calling both php from functions file.

    Did I miss something?

    @StefsterNYC
    Copy link

    Ah! I got it working. Awesome.

    @maddtechwf
    Copy link

    I'm using F5 also. I have the navigation working but when it gets to a smart phone screen it doesn't work for some reason. Any ideas why?

    ** I FOUND THE FIX. If you downloaded Foundation 5.0.0 then you will have issues. If you download 5.0.1 or 5.0.2 it will fix it for you.

    @Maikenvv
    Copy link

    Thank you so much for this code. I've got Foundation 5.0.2. working with normal nav and mobile. I'm wondering if anyone also had a problem with the dropdown menu's. I can't get them to work. I can click on the parent, and darkens it's color, but no dropdown appears. I've already tried z-index.

    @demo38
    Copy link

    demo38 commented Dec 16, 2013

    Sending positive vibes - because you deserve them. Thanks for taking the time to put this together - hugely useful. @awshout

    @nilocoelhojunior
    Copy link

    Thank you so much for this code

    @StefsterNYC
    Copy link

    I'm not sure if anyone commented on this so I'm just going to throw this out there. When the menu goes below 767px a parent tab that has a page attached to it and children becomes a non usable tab. You click on it and it just slides the menu over to the children rather than actually going to that page. Has anyone else experienced that and if so what was the fix to this? Thanks.

    @bei-soan
    Copy link

    @StefsterNYC I have this issue too, but on every size. Do you have any news about this issue already?

    @mmerriweather
    Copy link

    @aweshout I used the function you wrote to add a search input to the right menu, and it is not showing up in the top bar menu. I added the function inside foundation-topbar-menu.php. Was that the wrong place to add it?

    <div class="top-bar-container fixed contain-to-grid">
                <nav class="top-bar" data-topbar>
                    <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(); ?>
                        <ul class="right"><li><?php top_bar_search(); ?></li>
    
    
                    </section>
                </nav>
            </div>
    {
        // code
    }

    @jeremybutler
    Copy link

    Very useful and time saving, thanks for making this public!

    @flowdee
    Copy link

    flowdee commented May 9, 2014

    manually added the "not-click" class which reactivated the dropdown but the mobile/responsive navigation doesn't work any more. suggestions? i click the icon but nothing happens

    @rosemckeon
    Copy link

    @flowdee check you have this in your head,

    <meta name="viewport" content="width=device-width">

    @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