Skip to content

Instantly share code, notes, and snippets.

@mrmu
Last active November 30, 2020 20:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrmu/0b00bec641ae528cd7401af362756d46 to your computer and use it in GitHub Desktop.
Save mrmu/0b00bec641ae528cd7401af362756d46 to your computer and use it in GitHub Desktop.
WordPress Bootstrap Mega Menu Nav Walker
<?php
/* Usage:
* 至後台建立選單,並勾選 Mega menu,自訂的 Walker 會將第二層選項建成 .row .col 的形式
* 第二層選單的 css class 設為 mega-col,會自動註冊對應的「小工具容器」 (widget sidebar)
* 就能以小工具形式自訂 mega menu 的欄位內容。
*/
// 自訂 walker: Mu_Bootstrap_Mega_Menu_Nav_Walker
class Mu_Bootstrap_Mega_Menu_Nav_Walker extends Walker_Nav_Menu {
public function start_lvl(&$output, $depth = 0, $args = array()) {
// 排版用
$indent = str_repeat( "\t", $depth );
// 讓第一層子選單加上 caontainer > row
if ($depth === 0) {
$output .= "\n".$indent.'<ul class="dropdown-menu start-lvl mu-mega-wrap">';
$output .= "\n\t".$indent.'<div class="container mega-content">';
$output .= "\n\t\t".$indent.'<div class="row">'."\n";
}else{
$output .= "\n".$indent.'<ul class="start-lvl">'."\n";
}
}
public function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
$item_html = '';
// parent values (call by ref)
parent::start_el($item_html, $item, $depth, $args);
if ($item->is_dropdown && ($depth === 0)) {
$item_html = str_replace('<a', '<a class="dropdown-toggle" data-toggle="dropdown" data-target="#"', $item_html);
$item_html = str_replace('</a>', ' <b class="caret"></b></a>', $item_html);
}
$item_html = apply_filters('roots_wp_nav_menu_item', $item_html);
$output .= $item_html;
}
public function display_element($element, &$children_elements, $max_depth, $depth = 0, $args, &$output) {
$element->is_dropdown = (
(
!empty($children_elements[$element->ID]) &&
(
($depth + 1) < $max_depth ||
($max_depth === 0)
)
)
);
if ($element->is_dropdown) {
$element->classes[] = 'dropdown has-children';
}
// 第二層選項: 自動加上 .col 作為 megamenu 的 columns
if ($element && ($depth === 1)) {
$element->classes[] = 'col';
}
// 第二層選項: 若後台有設 .mega-col 類別,就去載入對應的 widget 內容
if ($element && ($depth === 1) && in_array('mega-col', $element->classes)) {
$output .= '<li class="col depth_'.$depth.'">';
$output .= '<ul>';
ob_start();
dynamic_sidebar( 'mega-col-' . $element->ID );
$dynamicSidebar = ob_get_contents();
ob_end_clean();
$output .= $dynamicSidebar;
$output .= '</ul>';
$output .= '</li>';
}else{
parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);
}
}
public function end_lvl(&$output, $depth = 0, $args = array()) {
$indent = str_repeat( "\t", $depth );
if ($depth === 0) {
$output .= "\n\t\t".$indent.'</div>'."\n";
$output .= "\n\t".$indent.'</div>'."\n";
$output .= "\n".$indent.'</ul>'."\n";
}else{
$output .= "\n".$indent.'</ul>'."\n";
}
}
}
// 移除 nav menu item 的 id 和 簡化 class (非必要)
add_filter('nav_menu_item_id', '__return_null');
add_filter('nav_menu_css_class', 'mu_mega_trim_roots_nav_menu_css_class', 10, 2);
function mu_mega_trim_roots_nav_menu_css_class($classes, $item) {
$slug = sanitize_title($item->title);
$classes = preg_replace('/(current(-menu-|[-_]page[-_])(item|parent|ancestor))/', 'active-${3}', $classes);
$classes = preg_replace('/(active-item)/', 'active', $classes);
$classes = preg_replace('/^((menu|page)[-_\w+]+)+/', '', $classes);
// 視情況自訂各個 menu item 的 class
// $classes[] = 'menu-' . $slug;
$classes = array_unique($classes);
return array_filter($classes);
}
// 自動註冊 mega menu 的自訂 widget
add_action('widgets_init', 'mu_mega_custom_cols_init');
function mu_mega_custom_cols_init() {
// 自訂選單location: mega_menu
register_nav_menus( array(
'mega_menu' => 'Mega Menu',
) );
$location = 'mega_menu';
$css_class = 'mega-col';
$locations = get_nav_menu_locations();
if ( isset( $locations[ $location ] ) ) {
$menu = get_term( $locations[ $location ], 'nav_menu' );
if ( $items = wp_get_nav_menu_items( $menu->name ) ) {
foreach ( $items as $item ) {
// 在 mega_menu 選單裡的選項若有 .mega-col 類別,就自動註冊一個 widget sidebar
if ( in_array( $css_class, $item->classes ) ) {
register_sidebar(
array(
'id' => 'mega-col-' . $item->ID,
'description' => 'Mega Menu Column',
'name' => $item->title . ' - Mega column',
'before_widget' => '<li id="%1$s" class="mega-menu-item">',
'after_widget' => '</li>',
)
);
}
}
}
}
}
add_action('wp_head', 'mu_mega_styles');
function mu_mega_styles() {
?>
<style>
.mu-mega-wrap{
width: 100%;
}
.mu-mega-wrap .navbar-nav, .navbar .collapse, .navbar-nav li {
position: static;
}
</style>
<?php
}
// 顯示選單
function mu_mega_nav_menu() {
$args = array(
'theme_location' => 'mega_menu',
'depth' => 0,
'menu_class' => 'navbar-nav mr-auto',
'walker' => new Mu_Bootstrap_Mega_Menu_Nav_Walker()
);
wp_nav_menu($args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment