Как в WordPress зарегистрировать и добавить выпадающее при наведении меню?

113
10 июня 2021, 23:10

Есть сайт на WordPress, где в тему хочу добавить bootstrap меню с выпадающим списком при наведении. Регистрирую меню стандартным способом:

<?php 
register_nav_menus(array(
'top'    => 'Верхнее меню'
));
wp_nav_menu( array(
    'container'       => 'div',
    'container_class' => 'collapse navbar-collapse navbar-ex1-collapse', 
    'menu_class'=>'nav navbar-nav navbar-right',
    'theme_location'=>'top'
) );
?>

Затем хочу перенести в него функционал этого меню, но есть проблемы с добавлением в ссылку классов class="dropdown-toggle" атрибутов data-toggle="dropdown" и во внутренний список ul класса dropdown-menu. Как это можно сделать? фидл

.dropdown:hover > .dropdown-menu { 
  display: block; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.js"></script> 
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.css" rel="stylesheet"> 
<nav class="navbar navbar-default navbar-static"> 
  <div class="container-fluid"> 
    <div class="navbar-header"> 
      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".js-navbar"> 
        <span class="sr-only">Toggle navigation</span> 
        <span class="icon-bar"></span> 
        <span class="icon-bar"></span> 
        <span class="icon-bar"></span> 
      </button> 
      <a class="navbar-brand" href="#" style="padding:15px 15px;">Название проекта</a> 
    </div> 
    <div class="collapse navbar-collapse js-navbar"> 
      <ul class="nav navbar-nav"> 
        <li><a href="#">Главная</a> 
        </li> 
        <li class="dropdown"> 
          <a id="drop1" href="#" class="dropdown-toggle" data-toggle="dropdown"> 
            Меню 
            <span class="caret"></span> 
          </a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
            <li class="divider"></li> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
          </ul> 
        </li> 
        <li class="dropdown"> 
          <a id="drop1" href="#" class="dropdown-toggle" data-toggle="dropdown"> 
            Меню 
            <span class="caret"></span> 
          </a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
            <li class="divider"></li> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
          </ul> 
        </li> 
      </ul> 
      <ul class="nav navbar-nav navbar-right"> 
        <li class="dropdown"> 
          <a id="drop1" href="#" class="dropdown-toggle" data-toggle="dropdown"> 
            Меню 
            <span class="caret"></span> 
          </a> 
          <ul class="dropdown-menu"> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
            <li class="divider"></li> 
            <li><a href="#">Текст подпункта</a> 
            </li> 
          </ul> 
        </li> 
      </ul> 
    </div> 
  </div> 
</nav>

Answer 1

Нужно использовать класс Walker, следующий код при добавлении в function.php, добавляет нужные классы к пунктам меню и ссылкам внутри него, при этом стандартные классы меню wordpress не выводятся.

class mainMenuWalker extends Walker_Nav_Menu {
  function start_el(&$output, $item, $depth, $args) {
    // назначаем классы li-элементу и выводим его
    $class_names = ' class="main-menu_item"';
    $output.= '<li' .$class_names. '>';
    // назначаем атрибуты a-элементу
    $attributes.= !empty( $item->url ) ? ' href="' .esc_attr($item->url). '" class="main-menu_link"  ' : '';
    $item_output = $args->before;
    // проверяем, на какой странице мы находимся
    $current_url = (is_ssl()?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    $item_url = esc_attr( $item->url );
    $item_output.= '<a'. $attributes .'>'.$item->title.'</a>';

    // заканчиваем вывод элемента
    $item_output.= $args->after;
    $output.= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
  }
}  

И в шаблоне где выводиться меню, выводим его следующим образом:

<?php $main_menu = new mainMenuWalker (); ?>
            <?php wp_nav_menu(array(
                                    'theme_location' => 'header_menu',
                                    'container' => 'nav',
                                    'container_class' => 'main-menu',
                                    'menu_class' => 'main-menu_list',
                                    'menu_id' => 'menu-header',
                                    'walker' => $main_menu
                                )); ?>  

В этом варианте конечно классы добавляются напрямую, без использования массива classes и у вложенного меню у тега ul генерируется дефолтный класс sub-menu.
Если же необходим более тонкий контроль, то еще немного расширим класс Walker:

class mainMenuWalker extends Walker_Nav_Menu {
    //для начала зададим класс для вложенного пункта меню тегу ul
    //функция start_lvl формирует превую строчку в шаблоне вывода списка, это нам и нужно.
    function start_lvl( &$output, $depth = 0, $args = array() ) {
        $indent = str_repeat("\t", $depth);
        $output .= "\n$indent<ul class=\"my-class\">\n";// указываем нужный нам класс, теперь все вложенные теги ul будут иметь указанный класс.
    }
    // если необходимо обозначить тег li, что он является родительским элементом вложенного списка модифицируем немного функцию display_element.
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        //получим  id элемента пункта меню
        $parent_elem = $this->db_fields['id'];
        // проверим есть ли в нем вложенный список
        if ( !empty( $children_elements[ $element->$parent_elem ] ) ) {
            // запишем в массив classes необходимый нам класс и присвоим элементу списка
            $element->classes['parent_class'] = 'parent-item';
        }
        Walker_Nav_Menu::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }
  //Ну а здесь уже приведем в нужный нам вид классы li элемента
  function start_el(&$output, $item, $depth, $args) {
    // назначаем классы li-элементу и выводим его
    //для этого добавим наш класс в массив classes
    $item->classes['my_class'] = 'main-menu_item';
    // и напрямую укажем какие классы из массива мы хотим использовать.
    $class_names = ' class="' .esc_attr( $item->classes['my_class'] .' '. $item->classes['parent_class'] ). '"';
    $output.= '<li ' .$class_names. '>';
    // назначаем атрибуты a-элементу
    $attributes.= !empty( $item->url ) ? ' href="' .esc_attr($item->url). '" class="main-menu_link"  ' : '';
    $item_output = $args->before;
    // проверяем, на какой странице мы находимся
    $current_url = (is_ssl()?'https://':'http://').$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
    $item_url = esc_attr( $item->url );
    $item_output.= '<a'. $attributes .'>'.$item->title.'</a>';

    // заканчиваем вывод элемента
    $item_output.= $args->after;
    $output.= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
  }
}  

PS
Eсли хотим использовать все классы и дефолтные, указываем просто массив $item->classes

тогда строка будет иметь вид:

$class_names = join( ' ', $item->classes );
$class_names = ' class="' .esc_attr( $class_names ). '"';
$output.= '<li id="menu-item-' . $item->ID . '"' .$class_names. '>';

Можно воспользоваться фильтрами и отсортировать классы так как нам нужно

Несколько ссылок по теме:
Может оказаться полезной
Кодекс (англ)
wp-кама
еще статья из wp-кама

READ ALSO
Синхронизация остатков

Синхронизация остатков

Стоит следующая задача, может кто направит на путь истинный :) Есть магазин, который работает в оффлайнеБудет разрабатываться интернет-магазин

115
Выдает ошибку php

Выдает ошибку php

Выдает: что "Регистрация не удалась" и на базу данных ничего не приходит, в чем мб ошибка?

380
Сохранение множества картинок в yii2

Сохранение множества картинок в yii2

Вообщем такое дело, решил потренироваться в traits и заодно избавится от одного расширения для сохранения картинок и в итоге написал такой код:

341
html_entity_decode возвращает строку в &lt;p&gt;

html_entity_decode возвращает строку в <p>

html_entity_decode возвращает строку в p, а мне нужно чтобы она не была обернута в тэг pКак можно это сделать? Потому как хочу на этот

80