我正在尝试为我的自定义wordpress主题编写自定义导航菜单。
<ul class="level-first">
<li class="">
<h5>Menu Item 1<i class="fa fa-plus"></i><i class="fa fa-minus"></i></h5>
<ul class="level-second">
<li class="">
<h5>By Type <i class="fa fa-plus"></i> <i class="fa fa-minus"></i> </h5>
<ul class="level-third">
<li>
<ul class="link-list">
<li><a href="#">Pens</a></li>
<li><a href="#">Portable</a></li>
<li><a href="#">Desktop</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="">
<h5>Menu Item 2<i class="fa fa-plus"></i><i class="fa fa-minus"></i></h5>
<ul class="level-second">
<li class="">
<h5>By Type <i class="fa fa-plus"></i> <i class="fa fa-minus"></i> </h5>
<ul class="level-third">
<li>
<ul class="link-list">
<li><a href="#">Pens</a></li>
<li><a href="#">Portable</a></li>
<li><a href="#">Desktop</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
问题是如何编写此结构遍历器
和使其可编辑的最简单方法是制作单个菜单,并将菜单标题用作列标题。
对于functions.php:<?php
// Register the menus
add_action( 'after_setup_theme', 'register_menus' );
function register_menus() {
register_nav_menu( 'megamenu1', __( 'Megamenu Column 1', 'theme-text-domain' ) );
register_nav_menu( 'megamenu2', __( 'Megamenu Column 2', 'theme-text-domain' ) );
register_nav_menu( 'megamenu3', __( 'Megamenu Column 3', 'theme-text-domain' ) );
register_nav_menu( 'megamenu4', __( 'Megamenu Column 4', 'theme-text-domain' ) );
register_nav_menu( 'support', __( 'Support Menu', 'theme-text-domain' ) );
}
// Add the menu title
add_filter( 'wp_nav_menu_items', [ $this, 'include_menu_title' ], 10, 2 );
function include_menu_title( $nav_items, $args ) {
if ( ! isset( $args->show_title ) || false === $args->show_title ) {
return $nav_items;
}
if ( $args->theme_location && ( $locations = get_nav_menu_locations() ) && isset( $locations[ $args->theme_location ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $args->theme_location ] );
// Add the menu title. We add the UL element manually, because otherwise it would wrap AROUND the H4 later in execution of the wp_nav_menu function.
$nav_items = '<h4>' . $menu->name . '</h4><ul class="' . $args->menu_class . '">' . $nav_items . '</ul>';
}
return $nav_items;
}
// Add the dropdown class to support menu items.
add_filter('nav_menu_css_class', function($classes, $item, $args) {
if ( 'support' !== $args->theme_location ) {
return $classes;
}
$classes[] = 'dropdown';
return $classes;
}, 10, 3);
然后是header.php:
<ul class="MainMenu nav navbar-nav"> <li class="has-megamenu"> <a href="#">Megamenu</a> <div class="megamenu"> <div class="container megamenu-background"> <?php $common_args = [ 'show_title' => true, // This is a custom arg used to indicate we want the title included. 'items_wrap' => '%3$s', // Remove the UL element. We'll add it back at the right place in the filter. 'container_class' => 'col-md-3 megamenu-column', 'menu_class' => 'vpm-menu-ul', ]; wp_nav_menu( array_merge( ['theme_location' => 'megamenu1'], $common_args ) ); wp_nav_menu( array_merge( ['theme_location' => 'megamenu2'], $common_args ) ); wp_nav_menu( array_merge( ['theme_location' => 'megamenu3'], $common_args ) ); wp_nav_menu( array_merge( ['theme_location' => 'megamenu4'], $common_args ) ); ?> </div> </div> </li> <?php wp_nav_menu([ 'theme_location' => 'support', 'items_wrap' => '%3$s', // Remove the UL element. 'container' => false, // Remove the container div. ]); ?> </ul>
class Custom_Walker_Nav_Menu extends Walker_Nav_Menu {
/**
* Unique id for dropdowns
*/
public $submenu_unique_id = '';
/**
* Starts the list before the elements are added.
* @see Walker::start_lvl()
*/
public function start_lvl( &$output, $depth = 0, $args = array() ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = str_repeat( $t, $depth );
$before_start_lvl = '<div class="megamenu">';
if($depth==0){
$output .= "{$n}{$indent}{$before_start_lvl}<ul id=\"$this->submenu_unique_id\" class=\"container megamenu-background sub-menu dropdown-content\">{$n}";
}
else{
$output .= "{$n}{$indent}<ul id=\"$this->submenu_unique_id\" class=\"sub-menu dropdown-content\">{$n}";
}
}
/**
* Ends the list of after the elements are added.
* @see Walker::end_lvl()
*/
public function end_lvl( &$output, $depth = 0, $args = array() ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = str_repeat( $t, $depth );
$after_end_lvl = '</div>';
if($depth==0){
$output .= "$indent</ul>{$after_end_lvl}{$n}";
}
else{
$output .= "$indent</ul>{$n}";
}
}
/**
* @see Walker::start_el()
*/
public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$indent = ( $depth ) ? str_repeat( $t, $depth ) : '';
$classes = empty( $item->classes ) ? array() : (array) $item->classes;
$classes[] = 'menu-item-' . $item->ID;
// set active class for current nav menu item
if( $item->current == 1 ) {
$classes[] = 'active';
}
// set active class for current nav menu item parent
if( in_array( 'current-menu-parent' , $classes ) ) {
$classes[] = 'active';
}
/**
* Filters the arguments for a single nav menu item.
*/
$args = apply_filters( 'nav_menu_item_args', $args, $item, $depth );
// add a divider in dropdown menus
if ( strcasecmp( $item->attr_title, 'divider' ) == 0 && $depth === 1 ) {
$output .= $indent . '<li class="divider">';
} else if ( strcasecmp( $item->title, 'divider') == 0 && $depth === 1 ) {
$output .= $indent . '<li class="divider">';
} else {
$class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args, $depth ) );
//adding col-md-3 class to column
if( in_array('menu-item-has-children', $classes ) ) {
if( $depth === 1 ) {
$class_names = $class_names ? ' class="col-md-3 mega-menucolumn '.esc_attr( $class_names ) . '"' : '';
} else {
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
}
}else{
$class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
}
$id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args, $depth );
$id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
$output .= $indent . '<li' . $id . $class_names .'>';
$atts = array();
$atts['title'] = ! empty( $item->attr_title ) ? $item->attr_title : '';
$atts['target'] = ! empty( $item->target ) ? $item->target : '';
$atts['rel'] = ! empty( $item->xfn ) ? $item->xfn : '';
if( in_array('menu-item-has-children', $classes ) ) {
$atts['href'] = ' ';
$this->submenu_unique_id = 'dropdown-'.$item->ID;
} else {
$atts['href'] = ! empty( $item->url ) ? $item->url : '';
$atts['class'] = '';
}
$atts['class'] .= 'menu-item-link-class ';
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args, $depth );
$attributes = '';
foreach ( $atts as $attr => $value ) {
if ( ! empty( $value ) ) {
$value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
$attributes .= ' ' . $attr . '="' . $value . '"';
}
}
if( ! in_array( 'icon-only' , $classes ) ) {
$title = apply_filters( 'the_title', $item->title, $item->ID );
$title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth );
}
$item_output = $args->before;
$item_output .= '<a'. $attributes .'>';
// set icon on left side
if( !empty( $classes ) ) {
foreach ($classes as $class_name) {
if( strpos( $class_name , 'fa' ) !== FALSE ) {
$icon_name = explode( '-' , $class_name );
if( isset( $icon_name[1] ) && !empty( $icon_name[1] ) ) {
$item_output .= '<i class="fa fa-'.$icon_name[1].'" aria-hidden="true"></i> ';
}
}
}
}
$item_output .= $args->link_before . $title . $args->link_after;
if( in_array('menu-item-has-children', $classes) ){
if( $depth == 0 ) {
$item_output .= ' <i class="fa fa-bolt" aria-hidden="true"></i>';
}
}
$item_output .= '</a>';
$item_output .= $args->after;
$output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
}
}
/**
* Ends the element output, if needed.
*
*/
public function end_el( &$output, $item, $depth = 0, $args = array() ) {
if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) {
$t = '';
$n = '';
} else {
$t = "\t";
$n = "\n";
}
$output .= "</li>{$n}";
}
} //