Podświetlanie wp_nav_menu () Klasa przodka bez dzieci w strukturze nawigacji?

30

( Uwaga moderatorów: pierwotnie zatytułowano „wp_nav_menu Klasa przodka bez dzieci w strukturze nawigacji”)

Mam wp_nav_menuw nagłówku, który miał trzy strony. Kiedy jestem na jednej z tych stron, lizawieranie tej strony w menu otrzymuje klasę .current_page_item. Te trzy strony mają szablony, a szablony te zawierają niestandardowe zapytania, aby uzyskać wszystkie posty określonego typu treści. W efekcie postrzegane „dzieci” tej strony najwyższego poziomu nie są w rzeczywistości dziećmi, są tylko typem treści, który skojarzyłem z tą stroną najwyższego poziomu za pomocą szablonu.

Chciałbym, aby elementy menu najwyższego poziomu uzyskały 'current-ancestor'klasę, gdy użytkownik przegląda pojedynczą stronę określonego typu postu, ponownie powiązaną z tą stroną tylko w niestandardowym zapytaniu w pliku szablonu.

Mam nadzieję, że to ma sens - jeśli nie, daj mi znać, gdzie cię straciłem! Bardzo doceniam każdą pomoc.

- Zredagowane dla szczegółów: Na przykład mam statyczną stronę o nazwie Warsztaty, która używa szablonu. Jego ślimakiem są warsztaty . Szablon ma niestandardową funkcję get_posts i pętlę, która ściąga i wyświetla wszystkie posty o niestandardowym typie treści zwane warsztatami . Jeśli kliknę tytuł jednego z tych warsztatów, przejdę do pełnej treści tego fragmentu. Struktura bezpośredniego linku niestandardowego typu posta jest ustawiona na workshop / postname, tak jak użytkownik to widzi, te fragmenty treści są potomkami strony Warsztatów, podczas gdy w rzeczywistości wszystkie mają jeden typ treści, ale nie są powiązane ze stroną. Jest to luka, którą muszę skutecznie zamknąć w menu, podkreślając pozycję menu „Warsztaty” podczas przeglądania treści typu „warsztat”.

Ponownie, mam nadzieję, że to ma sens, myślę, że powiedziałem „warsztat” w górę o 20 razy w jednym akapicie!

Gavin
źródło
@Gavin - Czy możesz podać kilka innych szczegółów tego, co próbujesz osiągnąć. Łatwiej jest napisać odpowiedź w konkretny sposób, niż gdybyśmy próbowali to zrobić w sposób abstrakcyjny. Przydałoby się również wyjaśnienie związanej z nimi struktury adresów URL.
MikeSchinkel,
1
@Gavin - To pomaga. Zatem twoją opcją menu najwyższego poziomu jest lista warsztatów w „Warsztatach” ze ścieżką /workshops/i kiedy użytkownik jest na stronie warsztatów (tj. /workshops/example-workshop/) Chcesz, aby element menu „Warsztaty” miał current_page_itemprzypisaną klasę , prawda?
MikeSchinkel,
wp_nav_menu () udostępnia klasę przodka bieżącego menu
Daniel Sachs

Odpowiedzi:

29

Istnieje prostsze rozwiązanie. Zapomnij o tworzeniu stron dla każdego typu posta, abyś mógł mieć elementy nawigacyjne, ponieważ, jak się dowiedziałeś, WP nie może rozpoznać, że przeglądane typy niestandardowe są powiązane z tą stroną.

Zamiast tego utwórz niestandardowy link w Wygląd-> Menu. Wystarczy wpisać adres URL, który zwróci niestandardowy typ i nadać mu etykietę, a następnie nacisnąć „Dodaj do menu”.

http://example.com/workshops/

lub non-pretty-permalink:

http://example.com/?post_type=workshops

samo to po prostu utworzy przycisk nawigacyjny, który wyświetla wszystkie posty z tym niestandardowym typem postu, a także doda klasę bieżącego menu po kliknięciu tego elementu nawigacyjnego - ale nie doda jeszcze klasy nawigacyjnej do żadnego URL inny niż ten

Następnie, po utworzeniu, przejdź do konfiguracji dla tego nowego elementu i wprowadź informację o typie niestandardowego postu w polu „Atrybut tytułu” (możesz również użyć pola opisu, ale ten jest ukryty w opcjach ekranu administratora domyślnie).

Teraz musisz zaczepić nav_menu_css_classfiltr (który jest uruchamiany dla każdego elementu nawigacji) i sprawdzić, czy przeglądana zawartość jest typu posta wskazanego w niestandardowym elemencie nawigacji:

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_query_var('post_type');
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}

W takim przypadku sprawdzimy, czy zawartość pola Tytuł atrybutu nie jest pusta i czy odpowiada bieżącemu typowi post_, którego dotyczy zapytanie. Jeśli tak, dodajemy klasę bieżącego menu do tablicy klas, a następnie zwracamy zmodyfikowaną tablicę.

Możesz to zmodyfikować tak, aby pasowało do tytułu elementu nawigacyjnego, ale jeśli z jakiegoś powodu chcesz tytułować element nawigacyjny inaczej niż zwykły ślimak typu postu, użycie pola Atrybut tytułu lub Opis daje tę elastyczność.

Teraz za każdym razem, gdy przeglądasz pojedynczy element (lub prawdopodobnie nawet zarchiwizujesz listę) typu postu pasującego do elementu menu nawigacyjnego, element ten otrzyma element bieżącej pozycji menu CSS, dzięki czemu podświetlenie będzie działać.

Żadne strony ani szablony stron nie są potrzebne ;-) Zapytanie URL zajmuje się pobieraniem właściwych postów. Szablon pętli zajmuje się wyświetlaniem wyników zapytania. Ta funkcja zajmuje się rozpoznawaniem tego, co jest wyświetlane, i dodawaniem klasy CSS.

PREMIA

Możesz nawet zautomatyzować ten proces wp_update_nav_menu_item, automatycznie generując pozycje menu dla wszystkich typów postów. W tym przykładzie musisz najpierw pobrać $menu_idmenu nawigacyjne, do którego chcesz dodać te elementy.

$types = get_post_types( array( 'exclude_from_search' => false, '_builtin' => false  ), 'objects' );
foreach ($types as $type) {
    wp_update_nav_menu_item( $menu_id, 0, array(
        'menu-item-type' => 'custom',
        'menu-item-title' => $type->labels->name,
        'menu-item-url' => get_bloginfo('url') . '/?post_type=' . $type->rewrite['slug'],
        'menu-item-attr-title' => $type->rewrite['slug'],
        'menu-item-status' => 'publish'
        )
    );
}
somatyczny
źródło
To jest to! Używam szablonów stron tylko dlatego, że układy są dość skomplikowane dla tych stron i nie tylko listy stron, ale nadal mogę użyć tego filtra, który podałeś, aby sprawdzić identyfikator strony. Charakter tego motywu polega na tym, że opcje motywu pozwalają dopasować strony („strona główna” to ta strona, „około” to ta strona itp.), Więc powinno to działać idealnie. Dziękujemy za (niezwykle szczegółową) pomoc!
Gavin,
musiałem usunąć current_page_parentelement nawigacyjny, który był moim blogiem - ale w przeciwnym razie działał. thx
pkyeck 10.10.11
to nie działało dla mnie, odkąd $item->attr_titlewyciągnąłem TYTUŁ, a tytuł napisałem dużymi literami. więc zmieniłem atrybut na $item->post_namei teraz działa dla mnie dobrze.
honk31,
Próbowałem uruchomić kod dla mojego motywu, ale nie mogę go uruchomić. W moim niestandardowym typie postów nie zostanie zastosowana żadna klasa dla mojego elementu nadrzędnego w menu portfolio. Użyłem powyższego kodu. Co może być problemem?
Casper
4

zamiast używać

$ post_type = get_query_var ('post_type');

Możesz spróbować:

$ post_type = get_post_type ();

Czasami typ wpisu nie jest ustawiony w zapytaniu var. Dzieje się tak w przypadku domyślnego typu post_typ „post”, więc jeśli chcesz podświetlić post wymieniony na stronie z listą, musisz go użyć. get_very_var () zwraca tylko pusty ciąg znaków dla typów postów, które nie są niestandardowe.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {
    $post_type = get_post_type();
    if ($item->attr_title != '' && $item->attr_title == $post_type) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}
Eric
źródło
2

@Somatic - to fantastyczne! Zmodyfikowałem nieco twój kod, aby działał również dla określonej taksonomii (której używam tylko dla pokrewnego typu post_). Chodzi o to, aby użyć atrybutu Tytuł elementu menu do przechowywania zarówno nazwy typu post_ ORAZ nazwy taksonomii, oddzielonych średnikiem, a następnie rozerwanej przez funkcję.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2 );
function current_type_nav_class($classes, $item) {

    # get Query Vars
    $post_type = get_query_var('post_type');  
    $taxonomy = get_query_var('taxonomy');

    # get and parse Title attribute of Menu item
    $title = $item->attr_title; // menu item Title attribute, as post_type;taxonomy
    $title_array = explode(";", $title);
    $title_posttype = $title_array[0];
    $title_taxonomy = $title_array[1];

    # add class if needed
    if ($title != '' && ($title_posttype == $post_type || $title_taxonomy == $taxonomy)) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}
tzeldin88
źródło
2

Oto moje rozwiązanie, jeśli chcesz pracować z wp_list_pages.

dodaj to do swojego functions.php

add_filter('page_css_class', 'my_page_css_class', 10, 2);
function my_page_css_class($css_class, $page){
    $post_type = get_post_type();
    if($post_type != "page"){
        $parent_page = get_option('page_for_custom_post_type-'.$post_type);
        if($page->ID == $parent_page)
            $css_class[] = 'current_page_parent';
    }
    return $css_class;
}

Teraz wystarczy dodać w wp_options tabeli nowy wiersz z OPTION_NAME z page_for_custom_post_type-xxxx i wartość_opcji z widoku-ID u chce się połączyć.

Być może wiesz, że istnieje już opcja o nazwie page_for_posts . Jeśli masz tylko 1 niestandardowy typ postu, możesz ustawić swoją stronę na /wp-admin/options-reading.php w menu rozwijanym, a nawigacja prawidłowo ustawi stronę bieżącą.

Myślę, że rdzeń wordpress powinien rozszerzyć tę sekcję o listę rozwijaną dla każdego zarejestrowanego typu posta.

Temo
źródło
2

Postanowiłem trzymać się stron i używać nazwy szablonu strony jako klasy w elemencie nawigacyjnym. Pozwala mi to uniknąć zaśmiecania atrybutu tytułu, co nie podobało mi się w niektórych innych rozwiązaniach.

add_filter('nav_menu_css_class', 'mbudm_add_page_type_to_menu', 10, 2 );
//If a menu item is a page then add the template name to it as a css class 
function mbudm_add_page_type_to_menu($classes, $item) {
    if($item->object == 'page'){
        $template_name = get_post_meta( $item->object_id, '_wp_page_template', true );
        $new_class =str_replace(".php","",$template_name);
        array_push($classes, $new_class);
        return $classes;
    }   
}

Mam także klasy treści dodane do header.php

<body <?php body_class(); ?>>

Wreszcie to rozwiązanie wymaga dodatkowego css, aby zastosować stan wybrany / aktywny do elementów menu nawigacyjnego. Używam go do wyświetlania archiwów taksonomii i niestandardowych typów postów związanych ze stroną jako dzieci tej strony:

/* selected states - include sub pages for anything related to products */
#nav-main li.current-menu-item a,
body.single-mbudm_product #nav-main li.lp_products a,
body.tax-mbudm_product_category #nav-main li.lp_products a,
#nav-main li.current_page_parent a{color:#c00;}
Steve
źródło
Dało mi to następujący błąd: Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76 Masz pojęcie, co się tutaj stało?
Jeff K.
Och, chyba widzę, co się dzieje. To dlatego, że zwracasz $ klas w instrukcji if. Po prostu wyjście na return $classeszewnątrz, a potem ifwydaje się , że rozwiązuje powyższy błąd.
Jeff K.
1

@Somatic - Świetny kod! Sam dokonałem jednej zmiany. Chciałem zachować atrybut tytułu zgodnie z jego przeznaczeniem, dlatego zamiast tego umieściłem informację o niestandardowym typie postu we właściwościach menu zaawansowanego powiązania z linkiem (XFN), które można włączyć w opcjach ekranu. zmodyfikowałem

if ($item->attr_title != '' && $item->attr_title == $post_type) {

i zmieniłem na

if ($item->xfn != '' && $item->xfn == $post_type) {
użytkownik8899
źródło
0

Dobra robota Somatic.

Niestety nie rozumiem, w jaki sposób można wyświetlić niestandardowe typy postów na stronie w sposób wyjaśniony. Jeśli nie użyję page-portfolio.php i nie dodam go do strony, otrzymam tylko 404 strony.

Jeśli robię to, co robi Gavin, zmodyfikowałem trochę twoją funkcję, aby usunąć również „current_page_parent” ze strony bloga w ten sposób.

add_filter('nav_menu_css_class', 'current_type_nav_class', 10, 2);
function current_type_nav_class($css_class, $item) {
$post_type = get_query_var('post_type');

if (get_post_type()=='portfolio') {
    $current_value = "current_page_parent"; 
    $css_class = array_filter($css_class, function ($element) use ($current_value) { return ($element != $current_value); } );
}

if ($item->attr_title != '' && $item->attr_title == $post_type) {       
    array_push($css_class, 'current_page_parent');
};
return $css_class;

}

Vayu
źródło