Evidențierea clasei strămoș wp_nav_menu() fără copii în structura de navigare

18 oct. 2010, 21:42:13
Vizualizări: 31K
Voturi: 32

(Notă moderatori: Titlul original era "Clasa strămoș wp_nav_menu fără copii în structura de navigare")

Am un wp_nav_menu în header care conține trei pagini. Când mă aflu pe una dintre aceste pagini, elementul li care conține acea pagină în meniu primește clasa .current_page_item. Aceste trei pagini au șabloane, iar aceste șabloane conțin interogări personalizate pentru a obține toate postările de un anumit tip de conținut. În esență, "copiii" percepuți ai acestei pagini de nivel superior nu sunt de fapt copii, ci sunt doar de un tip de conținut pe care l-am asociat cu acea pagină de nivel superior folosind un șablon.

Aș dori ca elementele de meniu de nivel superior să primească o clasă 'current-ancestor' când utilizatorul navighează pe o pagină individuală a unui tip specific de postare, din nou, asociată cu acea pagină doar într-o interogare personalizată din fișierul șablon.

Sper că are sens - dacă nu, spuneți-mi unde v-am pierdut! Apreciez foarte mult orice ajutor.

--Editat pentru specificații: De exemplu, am o pagină statică numită Workshops care folosește un șablon. Slug-ul său este workshops. Șablonul are o funcție personalizată get_posts și o buclă în interiorul său, care extrage și afișează toate postările de un tip de conținut personalizat numit workshops. Dacă fac clic pe titlul unuia dintre aceste workshop-uri, sunt dus la conținutul complet al acelei bucăți de conținut. Structura permalink-ului pentru tipul de postare personalizat este setată la workshops/postname, astfel încât din perspectiva utilizatorului, aceste bucăți de conținut sunt copii ai paginii Workshops, când în realitate sunt toate de un singur tip de conținut dar nerelaționat cu pagina. Acest decalaj trebuie să-l închid efectiv în meniu, evidențiind elementul de meniu 'Workshops' când navighez prin conținut de tip 'workshop'.

Din nou, sper că are sens, cred că am spus 'workshop' de peste 20 de ori într-un singur paragraf!

3
Comentarii

@Gavin - Poți include câteva detalii suplimentare despre ce încerci să realizezi. E mai ușor să scriu un răspuns în termeni concreti decât dacă încercăm să facem asta în termeni abstracti. De asemenea, dacă ai putea explica structura URL-urilor legate de acestea, ar fi de ajutor.

MikeSchinkel MikeSchinkel
18 oct. 2010 23:14:46

@Gavin - Asta ajută. Deci opțiunea ta principală din meniu este o listă de ateliere la "Ateliere" cu calea /workshops/ și când un utilizator este pe o pagină de atelier (adică /workshops/exemplu-atelier/) vrei ca elementul de meniu "Ateliere" să primească clasa current_page_item, corect?

MikeSchinkel MikeSchinkel
19 oct. 2010 07:37:19

wp_nav_menu() expune clasa current-menu-ancestor

Daniel Sachs Daniel Sachs
14 iun. 2011 00:06:13
Toate răspunsurile la întrebare 7
4
30

Există o soluție mai simplă. Uitați de crearea de pagini pentru fiecare tip de postare doar pentru a avea elemente în meniul de navigare, deoarece, așa cum ați învățat, WP nu are nicio modalitate de a recunoaște că tipurile personalizate pe care le vizualizați sunt legate de acea pagină.

În schimb, creați o legătură personalizată în Aspect->Meniuri. Pur și simplu introduceți URL-ul care va returna tipul dvs. personalizat și dați-i o etichetă, apoi apăsați "Adaugă în meniu".

http://example.com/workshops/

sau pentru permalink-uri neoptimizate:

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

doar acest lucru va crea un buton de navigare care afișează toate postările cu acel tip de postare personalizată și va adăuga și clasa current-menu-item când ați dat clic pe acel element de navigare - dar nu va încă adăuga clasa de navigare pe orice alt URL decât acesta

Apoi, odată creat, accesați configurația pentru acel element nou și introduceți slug-ul tipului de postare personalizată în câmpul "Atribut Titlu" (ați putea folosi și câmpul de descriere, dar acesta este ascuns în opțiunile ecranului de administrare în mod implicit).

Acum, trebuie să conectați filtrul nav_menu_css_class (care este declanșat pentru fiecare element de navigare) și să verificați dacă conținutul vizualizat este de tipul indicat în elementul dvs. personalizat de navigare:

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

În acest caz, vom verifica dacă conținutul câmpului Atribut Titlu nu este gol și dacă se potrivește cu post_type curent care este interogat. Dacă da, adăugăm clasa current-menu-item la matricea sa de clase, apoi returnăm matricea modificată.

Ați putea modifica acest lucru pentru a se potrivi pur și simplu cu titlul elementului de navigare, dar dacă dintr-un motiv oarecare doriți să denumiți elementul de navigare diferit de slug-ul simplu al tipului de postare, utilizarea câmpului Atribut Titlu sau Descriere vă oferă această flexibilitate.

Acum, ori de câte ori vizualizați un singur element (sau probabil chiar și liste de arhivă) ale unui tip de postare care se potrivește cu un element din meniul de navigare, acel element va primi clasa CSS current-menu-item, astfel încât evidențierea dvs. să funcționeze.

Nu sunt necesare pagini sau șabloane de pagini ;-) Interogarea URL se ocupă de preluarea postărilor corecte. Șablonul dvs. de buclă se ocupă de afișarea rezultatului interogării. Această funcție se ocupă de recunoașterea a ceea ce este afișat și de adăugarea clasei CSS.

BONUS

Puteți chiar automatiza procesul folosind wp_update_nav_menu_item, prin generarea automată a elementelor de meniu pentru toate tipurile dvs. de postări. Pentru acest exemplu, ar trebui mai întâi să obțineți $menu_id al meniului de navigare în care doriți să adăugați aceste elemente.

$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'
        )
    );
}
19 oct. 2010 08:25:38
Comentarii

Exact asta! Folosesc șabloane de pagină doar pentru că layout-urile sunt destul de complexe pentru acele pagini și nu doar listează paginile, dar tot pot folosi filtrul pe care l-ai oferit pentru a verifica ID-ul paginii. Natura acestui temă este că opțiunile de temă te ajută să asociezi paginile ('acasă' este această pagină, 'despre' este această pagină, etc.), așa că ar trebui să funcționeze perfect. Mulțumesc pentru ajutorul (incredibil de detaliat)!

Gavin Gavin
19 oct. 2010 14:59:47

a trebuit să elimin current_page_parent din elementul de navigație care era blogul meu - dar în rest a funcționat. mersi

Philipp Kyeck Philipp Kyeck
10 oct. 2011 17:58:54

nu a funcționat pentru mine, deoarece $item->attr_title extragea TITLUL, iar eu am scris titlul cu litere mari. așa că am schimbat atributul în $item->post_name și acum funcționează perfect pentru mine.

honk31 honk31
29 nov. 2013 19:42:24

Am încercat să fac codul să funcționeze pentru tema mea, dar nu reușesc. Nu se aplică nicio clasă elementului părinte din meniu când sunt pe tipul de post personalizat portfolio. Am folosit codul de mai sus. Care ar putea fi problema?

Casper Casper
25 mar. 2014 17:51:18
0

în loc să folosești

$post_type = get_query_var('post_type');

Ai putea încerca:

$post_type = get_post_type();

Uneori tipul de postare nu este setat în variabila de interogare. Acesta este cazul pentru tipul implicit de postare "post", așa că dacă vrei să evidențiezi o postare care a fost listată dintr-o pagină de listare, va trebui să folosești această funcție. get_query_var() returnează doar un șir gol pentru tipurile de postare care nu sunt personalizate.

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;
}
17 mar. 2011 16:18:20
0

@Somatic - asta e fantastic! Am modificat puțin codul tău ca să funcționeze și pentru o Taxonomie specifică (pe care o folosesc doar pentru post_type-ul asociat). Ideea este să folosim atributul Title al elementului de meniu pentru a stoca atât numele post_type-ului CÂT și numele taxonomiei, separate prin punct și virgulă, care apoi sunt explodate de funcție.

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

    # obținere variabile din interogare
    $post_type = get_query_var('post_type');  
    $taxonomy = get_query_var('taxonomy');

    # obținere și parsare atribut Title din Meniu
    $title = $item->attr_title; // atributul Title al elementului de meniu, ca post_type;taxonomy
    $title_array = explode(";", $title);
    $title_posttype = $title_array[0];
    $title_taxonomy = $title_array[1];

    # adăugare clasă dacă e necesar
    if ($title != '' && ($title_posttype == $post_type || $title_taxonomy == $taxonomy)) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}
13 apr. 2011 03:12:54
0

Iată soluția mea dacă doriți să lucrați cu wp_list_pages.

Adăugați acest cod în fișierul 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;
}

Acum adăugați în tabelul wp_options un nou rând cu un option_name de tipul page_for_custom_post_type-xxxx și o option_value cu ID-ul paginii pe care doriți să o conectați.

Probabil ați observat că există deja o opțiune numită page_for_posts. Dacă aveți un singur tip de postare personalizată, puteți seta pagina în /wp-admin/options-reading.php în meniul derulant și navigația va seta corect current_page.

Cred că nucleul WordPress ar trebui să extindă această secțiune cu un meniu derulant pentru fiecare tip de postare înregistrat.

13 iun. 2011 21:58:05
2

Am decis să folosesc pagini și să utilizez numele șablonului de pagină ca clasă pe elementul de navigație. Acest lucru îmi permite să evit aglomerarea atributului title, ceea ce nu mi-a plăcut la alte soluții.

add_filter('nav_menu_css_class', 'mbudm_add_page_type_to_menu', 10, 2 );
// Dacă un element de meniu este o pagină, adaugă numele șablonului ca clasă CSS
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;
    }   
}

De asemenea, am adăugat clase pentru body în header.php

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

În final, această soluție necesită CSS suplimentar pentru a aplica starea de selectat/activ pe elementele din meniul de navigație. O folosesc pentru a afișa arhivele de taxonomii și tipurile personalizate de postări legate de pagină ca elemente copil ale acestei pagini:

/* stări selectate - include subpagini pentru orice legat de produse */
#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;}
15 oct. 2011 05:28:44
Comentarii

Aceasta mi-a dat următoarea eroare:

Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76

Ai vreo idee ce s-a întâmplat aici?

Jeff K. Jeff K.
21 oct. 2011 03:04:45

Oh, cred că am înțeles ce se întâmplă. Este pentru că returnezi $classes în interiorul instrucțiunii if. Pur și simplu mutând return $classes în afara și după acel if pare să rezolve eroarea de mai sus.

Jeff K. Jeff K.
21 oct. 2011 04:14:08
0

@Somatic - Cod excelent! Am făcut o mică modificare personală. Am dorit să păstrez Atributul Title pentru scopul său inițial, așa că am plasat slug-ul Custom Post Type în Link Relationship (XFN) din proprietățile avansate ale meniului, care pot fi activate în Screen Options. Am modificat

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

și l-am schimbat în

if ($item->xfn != '' && $item->xfn == $post_type) {
23 sept. 2011 22:30:40
0

Bună treabă, Somatic.

Din păcate, nu înțeleg cum poți lista tipurile tale personalizate de postări într-o pagină așa cum explici. Dacă nu folosesc o pagină page-portfolio.php și o adaug într-o pagină, primesc doar eroarea 404.

Dacă procedez ca Gavin, am modificat puțin funcția ta pentru a elimina și clasa "current_page_parent" din pagina de blog, astfel:

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;

}

10 dec. 2010 14:36:55