Wordpress Nav Walker — многоуровневая навигация

Мне нужна помощь с навигацией по сайту Wordpress. Я пытаюсь заставить Wordpress печатать мою навигацию в этом формате:

<ul data-menu="main" class="menu__level">
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-1" href="#">Vegetables</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-2" href="#">Fruits</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-3" href="#">Grains</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-4" href="#">Mylk & Drinks</a></li>
      </ul>
      
<!-- Submenu 1 / Shown when user clicks the first list item (item with data-submenu="submenu-1") on data-menu="main" -->
      <ul data-menu="submenu-1" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Stalk Vegetables</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Roots & Seeds</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Cabbages</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Salad Greens</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Mushrooms</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-1-1" href="#">Sale %</a></li>
      </ul>
      
<!-- Submenu 2 / Shown when user clicks the second list item (item with data-submenu="submenu-2") on data-menu="main" -->
      <ul data-menu="submenu-2" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Citrus Fruits</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Berries</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-2-1" href="#">Special Selection</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Tropical Fruits</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Melons</a></li>
      </ul>
      
<!-- Submenu 3 / Shown when user clicks the third list item (item with data-submenu="submenu-3") on data-menu="main" -->
      <ul data-menu="submenu-3" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Buckwheat</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Millet</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Quinoa</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Wild Rice</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Durum Wheat</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-3-1" href="#">Promo Packs</a></li>
      </ul>
      
<!-- Submenu 4 / Shown when user clicks the forth list item (item with data-submenu="submenu-4") on data-menu="main" -->
      <ul data-menu="submenu-4" class="menu__level">
        <li class="menu__item"><a class="menu__link" href="#">Grain Mylks</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Seed Mylks</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Nut Mylks</a></li>
        <li class="menu__item"><a class="menu__link" href="#">Nutri Drinks</a></li>
        <li class="menu__item"><a class="menu__link" data-submenu="submenu-4-1" href="#">Selection</a></li>
      </ul>

Но я не могу понять, как указать дочерние элементы для определенного родительского элемента, а затем распечатать их с помощью подменю данных.

Структура навигации взята отсюда: http://tympanus.net/Blueprints/MultiLevelMenu/

Спасибо!

Обновление: это пришло мне в голову: было бы проще или чище просто получить навигационные данные с помощью php, а затем заполнить их в правильном формате с помощью Javascript? Кто-нибудь знает, будет ли это лучшим способом справиться с этим?

Или как насчет использования rest-api с этим (я довольно новичок в этом, так что есть ли смысл использовать его как часть небольшого проекта веб-сайта)


person Eljas    schedule 26.01.2016    source источник


Ответы (2)


На самом деле, вы можете просто взять все данные меню (из определенного места) в массив и вывести их любым удобным для вас способом.

Например, у вас есть такая структура меню:

Menu_parent1_item
    Submenu_item_1
    Submenu_item_2
    Submenu_item_3
Menu_parent2_item
    Submenu2_item_1
    Submenu2_item_2
    Submenu2_item_3
Menu_parent3_item
    Submenu3_item_1
    Submenu3_item_2
    Submenu3_item_3

Поместите этот код внутрь function.php:

function custom_menu_output( $theme_location ) {
    if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
        $menu = get_term( $locations[$theme_location], 'nav_menu' );
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        $menus = array();

        foreach( $menu_items as $menu_item ) {
            $pid = $menu_item->menu_item_parent ? $menu_item->menu_item_parent : 0;

            $menus[$pid][] = array(
                'link' => $menu_item->url,
                'title' => $menu_item->title,
                'id' => $menu_item->ID,
            );
        }

        foreach($menus as $key => $menu) {
            if($key == 0)
                echo '<ul data-menu="main" class="menu__level">';
            else
                echo '<ul data-menu="submenu-'.$key.'" class="menu__level">';
            foreach($menu as $item) {
                if(isset($menus[$item['id']]))
                    echo '<li class="menu__item"><a class="menu__link" data-submenu="submenu-'.$item['id'].'" href="'.$item['link'].'">'.$item['title'].'</a></li>';
                else
                    echo '<li class="menu__item"><a class="menu__link" href="'.$item['link'].'">'.$item['title'].'</a></li>';
            }
            echo '</ul>';
        }

    } else {
        $menu_list = '<!-- no menu defined in location "'.$theme_location.'" -->';
    }
    echo $menu_list;
}

И используйте это в своем шаблоне следующим образом:

<?php custom_menu_output('menu_location_name_from_register_nav_menu'); ?>

Он будет генерировать HTML следующим образом (я основывал его на описании вашего вопроса):

<ul data-menu="main" class="menu__level">
    <li class="menu__item"><a class="menu__link" data-submenu="submenu-717" href="http://yourdomain.tld/your_link/">Menu_parent1_item</a></li>
    <li class="menu__item"><a class="menu__link" data-submenu="submenu-720" href="http://yourdomain.tld/your_link/">Menu_parent2_item</a></li>
    <li class="menu__item"><a class="menu__link" data-submenu="submenu-725" href="http://yourdomain.tld/your_link/">Menu_parent3_item</a></li>
</ul>

<ul data-menu="submenu-717" class="menu__level">
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu_item_1</a></li>
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu_item_2</a></li>
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu_item_3</a></li>
</ul>

<ul data-menu="submenu-720" class="menu__level">
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_1</a></li>
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_2</a></li>
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_3</a></li>
</ul>

<ul data-menu="submenu-725" class="menu__level">
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_1</a></li>
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_2</a></li>
    <li class="menu__item"><a class="menu__link" href="http://yourdomain.tld/your_link/">Submenu2_item_3</a></li>
</ul>

Вы можете дополнительно настроить этот код для своих нужд.

person Codeartist    schedule 30.01.2016
comment
Идеально! Именно то, что я искал. Я неправильно подошел к этому, думая, что уроки ходячих были единственным выходом. Спасибо! - person Eljas; 31.01.2016
comment
если у меня есть 3-уровневое меню в wordpress, то как я могу показать меню при наведении курсора на элементы li, у которых есть подменю, пожалуйста, поделитесь css или другими sutffs. - person Manish Agarwal; 12.05.2020

Вы можете использовать класс Walker, чтобы внести изменения в структуру ul и li.

class themeslug_walker_nav_menu extends Walker_Nav_Menu {


        private $color_idx = 0;

        // add classes to ul sub-menus
        function start_lvl( &$output, $depth) {
            //p($output);
            // 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(
                'sidebar-menu',
                ( $display_depth % 2  ? 'menu-odd' : 'menu-even' ),
                ( $display_depth >=2 ? 'sub-sub-menu' : '' ),
                'level-' . $display_depth
                );
            $class_names = implode( ' ', $classes );

            $back_btn = '';
            if($display_depth > 0){

                /*$parent_label = '<li class="top custom-row">
                                    <a class="close-menu" href="#"><span class="parent_label"></span><i class="fa fa-close"></i></a>
                                  </li>';

                $back_btn = '<li class="sidebar-item back no-children back'.$display_depth.'">
                              <div class="inner">
                                <a class="hit-area" href="#">Back</a>
                                <i class="fa fa-chevron-left"></i>
                              </div>
                            </li>';*/
            }

            // build html
            $incri = $this->color_idx-1;
            $output .= "\n" . $indent . '<ul class="menu__level" data-menu="submenu-'.$incri.'">' .$parent_label.$back_btn. "\n";
        }

        // add main/sub classes to li's and links
         function start_el( &$output, $item, $depth, $args ) {


            global $wp_query;
            $indent = ( $depth > 0 ? str_repeat( "\t", $depth ) : '' ); // code indent

            // depth dependent classes
            /*$depth_classes = array(
                'sidebar-item',
                ( $depth == 0 ? 'li0' : '' ),
                ( $depth == 1 ? 'li1' : '' ),
                ( $depth == 2 ? 'li2' : '' ),
                ( $depth == 3 ? 'li3' : '' ),
                /*( $depth % 2 ? 'menu-item-odd' : 'menu-item-even' ),
                'menu-item-depth-' . $depth
            );*/



            if(in_array('menu-item-has-children',$item->classes)){
                $has_children = 'data-has-children="1"';
                $has_children_var = 1;
                $depth_classes[] = 'has-children';
            } else{
                $has_children_var = 0;
                $depth_classes[] = 'no-children';
            }


            $li_attributes = 'data-level="'.$depth.'" data-title="'.apply_filters( 'the_title', $item->title, $item->ID ).'" '.$has_children;



            $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 ) ) );

            // build html
            $output .= $indent . '<li class="menu__item">';

            // link attributes

            $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        ) .'"' : '';
            if($has_children_var == 1){
                $attributes .= ' data-submenu="submenu-'.$this->color_idx.'"';
            } 
            $attributes .= ' class="menu__link"';


            $item_output = sprintf( '%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s',
                $args->before,
                $attributes,
                $args->link_before,
                apply_filters( 'the_title', $item->title, $item->ID ),
                ($has_children_var == 1 ? $args->link_after : ''),
                $args->after
            );

            // build html
            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

            if($has_children_var == 1){
                $this->color_idx++;
            }
        }

    }

Но он не предоставляет метода отделения подменю ul от родительского li.

В противном случае можно управлять всеми классами, такими как submenu-1, submenu-2.

Попробуйте изменить этот код.

Для справки см. этот веб-сайт Energy & Manpower.

Правое боковое меню при нажатии на кнопку меню в правой части страницы построено таким же образом.

person Prakash Rao    schedule 29.01.2016
comment
Или вам придется создавать отдельные меню из бэкэнда для каждого ul и назначать им классы и атрибуты данных через класс Walker. - person Prakash Rao; 29.01.2016
comment
Это довольно близко к тому, что я пытаюсь сделать. Но чтобы это конкретное меню Tympanus Blueprint работало, эти подменю должны быть отдельными. Я уже пытался представить это как ваш пример кода, но он немного тормозит с этой структурой. Но если новых ответов не будет, мне, возможно, придется использовать другой подход к структуре моего меню. :) - person Eljas; 29.01.2016