Добавить класс has_children в родительский li при изменении Walker_Nav_Menu

22

Я пишу настроенный класс ходунка для wp_nav_menu и хочу иметь возможность указать, содержит ли li подменю. Поэтому я хочу, чтобы моя разметка была:

<li class="has_children [other-wordpress-classes]">
    <a class="parent-link">Some item</a>
    <ul class="sub-menu">

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

Любые идеи?

Заранее спасибо.

patnz
источник

Ответы:

23

start_el()должна получить эту информацию в своем $argsпараметре, но, похоже, WordPress заполняет$args ее только в том случае, если это массив , а для пользовательских меню навигации это объект. Об этом сообщается в билете Trac . Но нет проблем, вы можете заполнить это самостоятельно, если вы также переопределите display_element()метод в своем пользовательском обходчике (потому что это самый простой способ получить доступ к массиву дочерних элементов):

class WPSE16818_Walker extends Walker_Nav_Menu
{
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output )
    {
        $id_field = $this->db_fields['id'];
        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
        }
        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            // ...
        }
    }
Ян Фабри
источник
Здравствуйте, Ян, вы можете помочь мне с этим вопросом ? Я попробовал твой код, но не смог заставить его работать. Можете ли вы дать мне еще пример кода?
Гири
Обратитесь к полному примеру реализации ниже на этой странице.
RJB
Большое спасибо @Jan fabry .. Меня поддержали мои обычные ходоки .. Atlast ваш фрагмент помог мне.
Хариш Чинджу
7

Обновление: Начиная с WordPress 3.7 (октябрь 2013 г.), классы CSS были добавлены для обозначения дочерних элементов меню и страниц в меню тем - нет необходимости использовать пользовательский обходчик, как это делается в ядре WordPress.

Классы CSS названы menu-item-has-childrenи page_item_has_children.


Для полного решения для любого, кто спешит (кредит на предыдущий ответ Яна Фабри), см. Полную реализацию ниже.

Выведите навигацию в шаблон вашей темы:

wp_nav_menu( array(
    'theme_location' => 'navigation-primary',
    'container' => false,
    'container_class' => '',
    'container_id' => '',
    'menu_class' => '',
    'menu_id' => '',
    'walker' => new Selective_Walker(),
    'depth' => 2
    )
);

Затем включите в свою тему следующее functions.php:

class Selective_Walker extends Walker_Nav_Menu {
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $id_field = $this->db_fields['id'];

        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = !empty( $children_elements[$element->$id_field] );
        }

        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            $item->classes[] = 'has_children';
        }

        parent::start_el(&$output, $item, $depth, $args);
    }
}

Результирующий вывод HTML будет выглядеть следующим образом:

<ul>
    <li><a href="#">Home</a></li>
    <li class="has_children"><a href="#">About</a>
        <ul class="sub-menu">
            <li><a href="#">Our Mission</a></li>
        </ul>
    </li>
    <li><a href="#">Services</a></li>
    <li class="has_children"><a href="#">Products</a>
        <ul class="sub-menu">
            <li><a href="#">Lorem Ipsum</a></li>
            <li><a href="#">Lorem Ipsum</a></li>                
        </ul>
    </li>
    <li><a href="#">Contact Us</a></li>
</ul>

Для получения дополнительной информации об использовании класса Walker в WordPress см. Понимание класса Walker .

Наслаждайтесь!

rjb
источник
Неустранимая ошибка: удаленная ссылка на время вызова была удалена в D: \ www \ wordpress \ wp-content \ themes \ wpt_theme \ functions.php в строке 44
Тахир Ясин
Строка # 44 является parent :: start_el (& $ output, $ item, $ deep, $ args);
Тахир Ясин
2

Эта функция именно то, что вы хотите иметь. Он также показывает вам довольно эффективный способ изменения пунктов меню навигации. Кроме того, вы можете открыть его для более сложных (например, дочерняя тема) функций через фильтр элементов:

/**
 * Classes for a navigation named "Topnav" in the nav location "top".
 * Shows examples on how to modify the current nav menu item
 * 
 * @param (object) $items
 * @param (object) $menu
 * @param (object) $args
 */
function wpse16818_nav_menu_items( $items, $menu, $args )
{
    # >>>> start editing

    // examples for possible targets
    $target['name'] = 'Topnav';
    // The targeted menu item/s
    $target['items'] = array( (int) 6 );

    # <<<< stop editing

    // filter for child themes: "config_nav_menu_topnav"
    $target = apply_filters( 'config_nav_menu_'.strtolower( $target['name'] ), $target );

    // Abort if we're not with the named menu
    if ( $menu->name !== $target['name'] ) 
        return;

    foreach ( $items as $item )
    {
        // Check what $item contains
        echo '<pre>'; print_r($item); echo '</pre>';

        // First real world example:
        $item->classes = 'span-4';

        // Second real world example:
        // Append this class if we are in one of the targeted items
        if ( in_array( (int) $item->menu_order, $target['items'] ) )
            $item->classes .= ' last';
    }

    return $items;
}
add_filter( 'wp_get_nav_menu_items', 'wpse16818_nav_menu_items', 10, 3 );

И да, почти во всех случаях нет необходимости в обычном ходунке.

кайзер
источник
Спасибо, мне сейчас нужен ходок, но я посмотрю на это в следующий раз!
Патнц
1

если вы хотите сделать выпадающий список, вы можете сделать это только с помощью CSS. Создавая пользовательскую навигацию в WP с детьми, WordPress автоматически назначает класс .sub-menu для дочернего ul. Попробуйте этот CSS

    nav li {position:relative;}
   .sub-menu {display:none; position:absolute; width:300px;}
    nav ul li:hover ul {display:block;}

Возможно, вы захотите добавить jQuery, чтобы немного оживить его, но это должно дать вам рабочее раскрывающееся меню.

alexndm
источник
Спасибо за многоуровневое складное древовидное меню, в которое я вставляю элементы управления, но, безусловно, хорошо сделать как можно больше с css!
Патнц
-1
if ( $this->has_children ) {
    $item_output .= 'has_children';
}
ярослав
источник
3
Пожалуйста, объясните, что делает этот код и как он отвечает на вопрос.
cybmeta
И, пожалуйста, разместите код в более широком контексте. Как и большинство, люди, которые посещают, не будут знать, где попытаться вставить это, и получат это неправильно.
s_ha_dum