Добавьте класс "имеет детей" в родительский li при изменении навигационного меню Walker


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

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

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

Есть идеи?

Заранее благодарю.

 23
Author: patnz, 2011-05-10

5 answers

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 ) {
            // ...
        }
    }
 25
Author: Jan Fabry, 2011-05-10 08:51:03

Обновление: Начиная с 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.

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

 7
Author: rjb, 2015-10-08 20:17:57

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

/**
 * 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 );

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

 2
Author: kaiser, 2011-05-10 19:36:49

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

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

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

 1
Author: alexndm, 2011-05-10 08:07:48
if ( $this->has_children ) {
    $item_output .= 'has_children';
}
 -1
Author: yaroslav, 2015-11-13 18:54:12