Dodaj klasę „has_children” do nadrzędnego li podczas modyfikowania Walker_Nav_Menu

22

Piszę niestandardową klasę walkera dla wp_nav_menu i chcę mieć możliwość określenia, czy li zawiera podmenu. Więc chcę, aby mój znacznik był:

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

Wiem, jak dobrze dodawać i usuwać klasy. Nie mogę znaleźć niczego, co mogłoby mi powiedzieć, czy bieżący element zawiera elementy potomne.

Jakieś pomysły?

Z góry dziękuję.

patnz
źródło

Odpowiedzi:

23

start_el()powinien uzyskać tę informację w swoim $argsparametrze, ale wydaje się, że WordPress wypełnia$argstylko, jeśli jest tablicą , podczas gdy w niestandardowych menu nawigacyjnych jest to obiekt. Jest to zgłaszane na bilecie Trac . Ale nie ma problemu, możesz wypełnić to sam, jeśli również przesłonisz display_element()metodę w niestandardowym walkerze (ponieważ jest to najłatwiejsze miejsce na dostęp do tablicy elementów potomnych):

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 ) {
            // ...
        }
    }
Jan Fabry
źródło
Cześć Jan, możesz mi pomóc z tym pytaniem ? Próbowałem twojego kodu, ale nie mogłem go uruchomić. Czy możesz podać mi więcej przykładowego kodu?
Giri
Zapoznaj się z pełnym przykładem implementacji w dalszej części tej strony.
rjb
Wielkie dzięki @Jan Fabry .. Byłem zaskoczony moim niestandardowym walkerem .. Atlast twój fragment kodu pomógł mi.
Harish Chinju
7

Aktualizacja: Począwszy od WordPress 3.7 (październik 2013 r.), Dodano klasy CSS, aby wskazać elementy menu podrzędnego i strony w menu motywów - nie trzeba używać niestandardowego walkera, ponieważ jest on załatwiany w rdzeniu WordPress.

Klasy CSS mają nazwy menu-item-has-childreni page_item_has_children.


Aby znaleźć kompletne rozwiązanie dla każdego, kto się spieszy (podziękowania dla poprzedniej odpowiedzi Jana Fabry'ego), zobacz pełną implementację poniżej.

Wyświetl nawigację w szablonie motywu:

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

Następnie dołącz do motywu następujące elementy 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);
    }
}

Wynikowy wynik HTML będzie przypominał:

<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>

Aby uzyskać więcej informacji na temat korzystania z klasy walkera WordPress, zobacz Opis klasy Walker .

Cieszyć się!

rjb
źródło
Błąd krytyczny: W trybie D: \ www \ wordpress \ wp-content \ themes \ wpt_theme \ functions.php w linii 44 usunięto przekazywanie odwołania według czasu połączenia
Tahir Yasin
Linia nr 44 jest nadrzędna :: start_el (& $ output, $ item, $ depth, $ args);
Tahir Yasin
2

Ta funkcja jest dokładnie tym, co chcesz mieć. Pokazuje także całkiem skuteczny sposób modyfikowania elementów menu nawigacyjnego. Ponadto możesz go otworzyć dla bardziej zaawansowanych funkcji (np. Motywu potomnego) za pomocą filtru pozycji:

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

I tak, prawie w każdym przypadku nie ma potrzeby niestandardowego chodzika.

kajzer
źródło
Dzięki, potrzebuję teraz walkera, ale przyjrzę się temu na następną rundę!
patnz
1

jeśli chcesz zrobić listę rozwijaną, możesz to zrobić tylko za pomocą css. utwórz niestandardową nawigację w WP z dziećmi, WordPress automatycznie przypisuje podmenu klasy do podrzędnego ul. Wypróbuj ten CSS

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

Możesz dodać trochę jQuery, aby trochę urozmaicić, ale to powinno dać ci działające menu rozwijane.

alexndm
źródło
Dzięki za wielopoziomowe, składane menu drzewa, do którego również wstawiam elementy sterujące, ale zdecydowanie dobrze jest zrobić tyle, ile to możliwe z css!
patnz
-1
if ( $this->has_children ) {
    $item_output .= 'has_children';
}
Jarosław
źródło
3
Proszę wyjaśnić, co robi ten kod i jak to jest odpowiedzieć na pytanie.
cybmeta
I proszę opublikować kod w szerszym kontekście. W rzeczywistości większość osób, które odwiedzą, nie będzie miała pojęcia, gdzie to wkleić, i źle to zrobi.
s_ha_dum