wp-materialize-navwalker
wp-materialize-navwalker copied to clipboard
Walker for main and mobile menu
I have navbar like this:
<nav class="grey darken-4" role="navigation">
<div class="nav-wrapper container"><a id="logo-container" href="<?php echo esc_url( home_url( '/' ) ); ?>" class="brand-logo"><?php bloginfo('name'); ?></a>
<?php
$menu = array(
'theme_location' => 'primary_header',
'menu_class' => 'right hide-on-med-and-down',
'walker' => new wp_materialize_navwalker()
);
$menuMobile = array(
'theme_location' => 'primary_header',
'menu_class' => 'side-nav',
'menu_id' => 'nav-mobile'
);
wp_nav_menu($menu);
wp_nav_menu($menuMobile);
?>
<a href="#" data-activates="nav-mobile" class="button-collapse"><i class="material-icons">menu</i></a>
</div>
</nav>
And it is working quite good with Your walker, but when I add second walker to the mobile menu, the main menu brokes. Any idea for this?
Same issue as me any solution for this issue ?
My English is not so good. but this code that's work for me
<nav role="navigation"> <div class="nav-wrapper container"> <a id="logo-container" href="#" class="brand-logo">Logo</a> <a href="#" data-activates="nav-mobile" class="button-collapse"><i class="fa fa-bars" aria-hidden="true"></i></a> <?php wp_nav_menu( array( 'menu' => 'Primary', 'theme_location'=>'Primary', 'container' => '', 'menu_class' => 'right hide-on-med-and-down', 'walker' => new wp_materialize_navwalker() )); ?> </div> </nav>
and footer.php
`$(function() {
elemSwap = function() {
if ($(window).width() < 992) {
$('.nav-wrapper.container > ul').attr("id", "nav-mobile");
$('.nav-wrapper.container > ul').removeClass('right hide-on-med-and-down').addClass('side-nav');
$('nav .button-collapse').click(function(event) {
$('.side-nav').css({
"transform": "translateX(0%)"
});
});
} else {
$('.nav-wrapper.container > ul').attr("id", "menu-menu");
$('.nav-wrapper.container > ul').removeClass('side-nav').addClass('right hide-on-med-and-down');
}
}
elemSwap();
$(window).resize(elemSwap);
});
`
I'm having the same issue. This works with one menu (the desktop). But when I try to use this code to generate the mobile menu as well, the dropdowns stop working.
my code https://drive.google.com/open?id=0B0Fi5ctV-4KJZFpPTEhBY2xGQ1U
I'm going to do update once Materializecss hit stable (1.0) version.
Hey, I (kinda) killed 2 birds with one stone here.
So, I'm relatively new to PHP (only just started playing with wordpress functions/php about 3 months ago), so this may not be the best way to do it, but I've addressed the following:
Multiple Navwalkers
To get this to work, you must declare a
$GLOBALS
variable (in my setup,$GLOBALS['count'] = 0;
) before walking the nav, and it's lame, but increment it manually.<ul class="left hide-on-med-and-down"> <?php $GLOBALS['count']=0; wp_nav_menu( array( 'menu' => 'top_menu', 'theme_location'=>'top_menu', 'menu_class' => 'hide-on-med-and-down', 'walker' => new wp_materialize_navwalker() )); ?> </ul> <ul id="slide-out" class="side-nav blue-grey darken-4"> <?php $GLOBALS['count']++; wp_nav_menu( array( 'menu' => 'top_menu', 'theme_location'=>'top_menu', 'walker' => new wp_materialize_navwalker(), )); ?> </ul>
And then replace your
wp_materialize_navwalker.php
contents with this<?php /** * Class Name: wp_materialize_navwalker * GitHub URI: # * Description: A custom WordPress nav walker class to "fully" implement the Materialize CSS nested navigation style in a custom theme using the WordPress manager * Version: 1.0.0 * Author: Kailo - https://kailo.io * Updated: Nov. 2, 2017 by Mackenzie Fritschle as a shoddy compatibility for multiple walkers * License: MIT * License URI: # */ class wp_materialize_navwalker extends Walker { var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' ); function start_lvl( &$output, $depth = 0, $args = array() ) { // Depth-dependent classes. $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent $display_depth = ( $depth + 1); // because it counts the first submenu as 0 $classes = array( 'dropdown-content', ( $display_depth % 2 ? 'menu-odd' : 'menu-even' ), ( $display_depth >=2 ? 'sub-sub-menu' : '' ), 'menu-depth-' . $display_depth ); $class_names = implode( ' ', $classes ); // Build HTML for output. $output .= "\n" . $indent . ' class="' . $class_names . '">' . "\n"; } function end_lvl( &$output, $depth = 0, $args = array() ) { $indent = str_repeat("\t", $depth); $output .= "$indent</ul>\n"; } function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { global $wp_query; $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent // Depth-dependent classes. $depth_classes = array( ( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ), ( $depth >=2 ? 'sub-sub-menu-item' : '' ), ( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ), 'menu-item-depth-' . $depth ); $depth_class_names = esc_attr( implode( ' ', $depth_classes ) ); // Passed classes. $classes = empty( $item->classes ) ? array() : (array) $item->classes; $class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) ); /* Add active class */ if(in_array('current-menu-item', $classes)) { $classes[] = 'active'; unset($classes['current-menu-item']); } /* Check for children */ $children = get_posts(array( 'post_type' => 'nav_menu_item', 'nopaging' => true, 'numberposts' => 1, 'meta_key' => '_menu_item_menu_item_parent', 'meta_value' => $item->ID )); if (!empty($children)) { $classes[] = 'dropdown'; } $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 ) . '"' : ''; $output .= $indent . '<li id="nav-menu-item-'.$item->ID.'-'.$GLOBALS['count'].'" class="' . $depth_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 ) .'"' : ''; $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : ''; $attributes .= ! empty( $children ) ? ' data-activates="dropdown-'. $item->ID.'-'.$GLOBALS['count'] .'"' : ''; $attributes .= ! empty( $children ) ? ' class="dropdown-button '. $depth_class_names .'"' : ''; $item_output .= '<a'. $attributes .'>'; $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; if(!empty($children)) $item_output .= '<i class="material-icons right">arrow_drop_down</i>'; $item_output .= '</a>'; $item_output .= $args->after; if(!empty($children)) $item_output .= '<ul id="dropdown-'.$item->ID.'-'.$GLOBALS['count'].'"'; $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } function end_el( &$output, $item, $depth = 0, $args = array() ) { $output .= "</li>\n"; } }
SideNav Navwalker addition
Create a new file called wp_materialize_navwalker_clps.php, and paste this inside
<?php
/**
* Class Name: wp_materialize_navwalker_clps
* GitHub URI: #
* Description: A custom WordPress nav walker class to "fully" implement the Materialize CSS nested navigation style in a custom theme using the WordPress manager
* Version: 1.0.0
* Author: Kailo - https://kailo.io
* License: MIT
* License URI: #
*/
class wp_materialize_navwalker_clps extends Walker {
var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );
function start_lvl( &$output, $depth = 0, $args = array() ) {
// Depth-dependent classes.
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
$display_depth = ( $depth + 1); // because it counts the first submenu as 0
$classes = array(
( $display_depth === 0 ? 'collapsible' : '' ),
( $display_depth % 2 ? 'menu-odd' : 'menu-even' ),
( $display_depth >=2 ? 'sub-sub-menu' : '' ),
'menu-depth-' . $display_depth
);
$class_names = implode( ' ', $classes );
// Build HTML for output.
$output .= "\n" . $indent . ' class="' . $class_names . '">' . "\n";
}
function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
($display_depth === 1 ? $output .= "$indent</ul></div></li></ul>\n" : $output .= "$indent</ul></li></ul>\n" );
}
function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
global $wp_query;
$indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent
// Depth-dependent classes.
$depth_classes = array(
( $depth == 0 ? 'main-menu-item' : 'sub-menu-item' ),
( $depth >=2 ? 'sub-sub-menu-item' : '' ),
( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
'menu-item-depth-' . $depth
);
$depth_class_names = esc_attr( implode( ' ', $depth_classes ) );
// Passed classes.
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$class_names = esc_attr( implode( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) ) );
/* Add active class */
if(in_array('current-menu-item', $classes)) {
$classes[] = 'active';
unset($classes['current-menu-item']);
}
/* Check for children */
$children = get_posts(array(
'post_type' => 'nav_menu_item',
'nopaging' => true,
'numberposts' => 1,
'meta_key' => '_menu_item_menu_item_parent',
'meta_value' => $item->ID
));
if (!empty($children)) {
$classes[] = 'collapsible';
}
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
$output .= $indent . '<li id="nav-menu-item-'.$item->ID.'-'.$GLOBALS['count'].'" class="' . $depth_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 ) .'"' : '';
$attributes .= ! empty( $item->url ) ? $attributes .= empty( $children ) ? ' href="' . esc_attr( $item->url ) .'"' : '' : ''; //First-level collapsibles don't actually follow the link. I'm not sure of a better way to do this, but you COULD instead put make this normal and use javascript to only activate on doubleclick
$attributes .= ! empty( $children ) ? ' class="'. $depth_class_names .'"' : '';
if( $depth >= 1 ){
if(!empty($children)){
$item_output .= '<ul><li>';
$item_output .= '<div class="subheader">';
}
} else {
if(!empty($children)){
$item_output .= '<ul class="collapsible"><li>';
$item_output .= '<div class="collapsible-header">';
}
}
$item_output .= '<a'. $attributes .'>';
$item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
if( $depth < 1 )
if(!empty($children))
$item_output .= '<i class="fas fa-caret-down"></i>';
$item_output .= '</a>';
if(!empty($children))
$item_output .= '</div>';
$item_output .= $args->after;
if(!empty($children))
//( $depth === 1 ? '<div class="collapsible-body">' : '' );
( $depth === 0 ? $item_output .= '<div class="collapsible-body"><ul id="collapsible-'.$item->ID.'-'.$GLOBALS['count'].'"' : $item_output .= '<ul id="collapsible-'.$item->ID.'-'.$GLOBALS['count'].'"' );
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
//( $depth === 1 ? '</div>' : '' );
}
function end_el( &$output, $item, $depth = 0, $args = array() ) {
$output .= "</li>\n";
}
}
Follow the same steps as before, but instead of
wp_materialize_navwalker
, enterwp_materialize_navwalker_clps
. So just to skim over, put this in your functions.php// Register wp-materialize-navwalker require_once get_template_directory() . '/wp_materialize_navwalker_clps.php';
And use this to walk it like so
<?php wp_nav_menu( array( 'menu' => 'Primary', 'theme_location'=>'Primary', 'menu_class' => 'mobile', 'walker' => new wp_materialize_navwalker_clps() )); ?>
I hope this helps anyone for the meantime as we wait for something likely more professional than my code :P
Ah, hang on, let me restructure that comment. I'm not sure how to make different branches (or if I should). Basically, The top block of code is going to be for multiple of the same navwalker, while the bottom is for sideNav (and you can follow the same steps to make multiple, just using the _clps
file instead).
So both of those additions work together (and that's what I'm doing on a website), and must be used together of course if you want a normal nav AND a sidenav.
example:
<nav class="blue-grey darken-4">
<div class="nav-wrapper">
<ul class="left hide-on-med-and-down">
<?php
$GLOBALS['count']=0;
wp_nav_menu( array(
'menu' => 'top_menu',
'theme_location'=>'top_menu',
'menu_class' => 'hide-on-med-and-down',
'walker' => new wp_materialize_navwalker()
));
?>
</ul>
<ul id="slide-out" class="side-nav blue-grey darken-4">
<?php
$GLOBALS['count']++;
wp_nav_menu( array(
'menu' => 'top_menu',
'theme_location'=>'top_menu',
'menu_class' => 'mobile',
'walker' => new wp_materialize_navwalker_clps(),
));
?>
</ul>
<a href="#" data-activates="slide-out" class="button-collapse"><i class="material-icons">menu</i></a>
</div>
</nav>
Hello @schnoodly, first, thanks for your soltution - it (kinda) works ^^
Coding a wp theme based on my materialize.css website, had the same issue as you for a nav menu, so I tried your solution, but it doesn't work for me...
I have some dropdown items in my nav and something goes wrong in slide-out mobile menu... I've also noticed that you don't use collapsible-accordion class in your /wp_materialize_navwalker_clps.php....
I'm just trying to understand if I implemented wrong your function or you didn't think about this option..? If it's ok for you, could you attach your fuction.php and init.js files ?
THanks in advance
@Aksumiron,
Sorry about the late reply, didn't realize anyone had said anything. Not a fan of GitHub's lack of notification area...
You're right, apparently I didn't have the accordion in there. I've updated the _clps
code to add Accordions. Not sure why it wasn't in there at the time, to be honest. I've grown a lot as a developer since then, so completely possible I was doing something contrived and ugly. After this, you should just be able to include it like normal, although you do still have to initialize the javascript for both sidenav
and collapsible
.