Evidenziare la Classe Antenata wp_nav_menu() senza Figli nella Struttura di Navigazione

18 ott 2010, 21:42:13
Visualizzazioni: 31K
Voti: 32

(Nota dei moderatori: Originariamente intitolato "Classe antenata wp_nav_menu senza figli nella struttura di navigazione")

Ho un wp_nav_menu nell'header che contiene tre pagine. Quando mi trovo su una di queste pagine, l'elemento li che contiene quella pagina nel menu ottiene la classe .current_page_item. Queste tre pagine hanno dei template, e questi template contengono query personalizzate per ottenere tutti i post di un determinato tipo di contenuto. In effetti, i "figli" percepiti di questa pagina di livello superiore non sono effettivamente figli, sono solo di un tipo di contenuto che ho associato a quella pagina di livello superiore utilizzando un template.

Vorrei che le voci di menu di livello superiore ottenessero una classe 'current-ancestor' quando l'utente sta navigando una singola pagina di uno specifico tipo di post, ancora una volta, associato a quella pagina solo in una query personalizzata nel file template.

Spero che abbia senso - se non è così, fatemi sapere dove vi ho perso! Apprezzo molto qualsiasi aiuto.

--Modificato per specifiche: Per esempio, ho una pagina statica chiamata Workshops che utilizza un template. Il suo slug è workshops. Il template ha una funzione get_posts personalizzata e un loop al suo interno, che estrae e visualizza tutti i post di un tipo di contenuto personalizzato chiamato workshops. Se clicco sul titolo di uno di questi workshop, vengo portato al contenuto completo di quel contenuto. La struttura dei permalink del custom post type è impostata su workshops/postname, quindi come lo vede l'utente, questi contenuti sono figli della pagina Workshops, quando in realtà sono tutti dello stesso tipo di contenuto ma non correlati alla pagina. È questo divario che devo effettivamente colmare nel menu, evidenziando la voce di menu 'Workshops' durante la navigazione dei contenuti di tipo 'workshop'.

Di nuovo, spero che abbia senso, penso di aver detto 'workshop' più di 20 volte in un paragrafo!

3
Commenti

@Gavin - Puoi includere qualche dettaglio in più su ciò che stai cercando di ottenere? È più semplice rispondere in termini concreti piuttosto che in astratto. Inoltre se potessi spiegare la struttura degli URL correlata a questo sarebbe utile.

MikeSchinkel MikeSchinkel
18 ott 2010 23:14:46

@Gavin - Questo aiuta. Quindi la tua opzione di menu di primo livello è una lista di workshop in "Workshops" con un percorso /workshops/ e quando un utente è su una pagina di workshop (es. /workshops/example-workshop/) vuoi che la voce di menu "Workshops" abbia la classe current_page_item assegnata, corretto?

MikeSchinkel MikeSchinkel
19 ott 2010 07:37:19

wp_nav_menu() espone la classe current-menu-ancestor

Daniel Sachs Daniel Sachs
14 giu 2011 00:06:13
Tutte le risposte alla domanda 7
4
30

Esiste una soluzione più semplice. Dimentica di creare pagine per ogni tipo di post solo per avere voci di navigazione, perché come hai imparato, WP non ha modo di riconoscere che i tipi personalizzati che stai navigando sono correlati a quella pagina.

Invece, crea un link personalizzato in Aspetto->Menu. Inserisci semplicemente l'URL che restituirà il tuo tipo personalizzato, dagli un'etichetta e clicca su "Aggiungi al menu".

http://example.com/workshops/

o con permalink non ottimizzati:

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

questo da solo creerà semplicemente un pulsante di navigazione che mostra tutti i post con quel tipo di post personalizzato e aggiungerà anche la classe current-menu-item quando hai cliccato su quella voce di menu - ma non aggiungerà ancora la classe di navigazione su nessun URL diverso da questo

Quindi, una volta creato, vai nella configurazione di quella nuova voce e inserisci lo slug del tipo di post personalizzato nel campo "Attributo Titolo" (potresti anche usare il campo descrizione, ma quello è nascosto nelle opzioni dello schermo di amministrazione per impostazione predefinita).

Ora devi agganciare il filtro nav_menu_css_class (che viene attivato per ogni voce di menu) e verificare se il contenuto visualizzato è del tipo di post indicato nella tua voce di menu personalizzata:

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

In questo caso, controlleremo che il contenuto del campo Attributo Titolo non sia vuoto e se corrisponde al post_type attualmente in query. Se è così, aggiungiamo la classe current-menu-item al suo array di classi, quindi restituiamo l'array modificato.

Potresti modificarlo per far corrispondere semplicemente il titolo della voce di menu, ma se per qualche motivo vuoi intitolare la voce di menu diversamente dallo slug semplice del tipo di post, utilizzare il campo Attributo Titolo o Descrizione ti offre quella flessibilità.

Ora ogni volta che visualizzi un singolo elemento (o probabilmente anche elenchi di archivi) di un tipo di post che corrisponde a una voce di menu, a quella voce verrà assegnata la classe CSS current-menu-item in modo che la tua evidenziazione funzioni.

Nessuna pagina o modello di pagina necessario ;-) La query dell'URL si occupa di recuperare i post giusti. Il tuo template del loop si occupa di visualizzare l'output della query. Questa funzione si occupa di riconoscere ciò che viene mostrato e di aggiungere la classe CSS.

BONUS

Puoi persino automatizzare il processo utilizzando wp_update_nav_menu_item, facendo generare automaticamente voci di menu per tutti i tuoi tipi di post. Per questo esempio, dovresti prima aver recuperato l'$menu_id del menu di navigazione a cui vuoi aggiungere queste voci.

$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 ott 2010 08:25:38
Commenti

Ecco il punto! Sto usando i template di pagina solo perché i layout sono piuttosto complessi per quelle pagine e non si limitano a elencare le pagine, tuttavia posso comunque utilizzare quel filtro che hai fornito per verificare l'ID della pagina. La natura di questo tema è che le opzioni del tema ti permettono di abbinare le pagine ('home' è questa pagina, 'about' è questa pagina, ecc.), quindi dovrebbe funzionare perfettamente. Grazie per l'assistenza (incredibilmente dettagliata)!

Gavin Gavin
19 ott 2010 14:59:47

ho dovuto rimuovere il current_page_parent dalla voce di navigazione che era il mio blog - ma a parte questo ha funzionato. grazie

Philipp Kyeck Philipp Kyeck
10 ott 2011 17:58:54

questo non funzionava per me, poiché $item->attr_title estraeva il TITOLO, e io avevo scritto il titolo in lettere maiuscole. quindi ho cambiato l'attributo in $item->post_name e ora funziona bene per me.

honk31 honk31
29 nov 2013 19:42:24

Ho provato a far funzionare il codice per il mio tema, ma non riesco a farlo funzionare. Non viene applicata alcuna classe al mio elemento genitore nel menu, quando mi trovo sul custom post type portfolio. Ho utilizzato il codice sopra. Quale potrebbe essere il problema?

Casper Casper
25 mar 2014 17:51:18
0

invece di usare

$post_type = get_query_var('post_type');

Potresti provare:

$post_type = get_post_type();

In alcuni casi il post type non è impostato nella query var. Questo accade per il post_type predefinito "post", quindi se vuoi evidenziare un post elencato da una pagina di elenco, dovrai usare questo metodo. get_query_var() restituisce semplicemente una stringa vuota per i post type che non sono personalizzati.

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 - fantastico! Ho modificato un po' il tuo codice in modo che funzioni anche per una tassonomia specifica (che sto usando solo per il post_type correlato). L'idea è utilizzare l'attributo Title della voce di menu per memorizzare sia il nome del post_type che il nome della tassonomia, separati da un punto e virgola, che verranno poi elaborati dalla funzione.

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

    # Ottiene le variabili della query
    $post_type = get_query_var('post_type');  
    $taxonomy = get_query_var('taxonomy');

    # Ottiene e analizza l'attributo Title della voce di menu
    $title = $item->attr_title; // attributo Title della voce di menu, come post_type;taxonomy
    $title_array = explode(";", $title);
    $title_posttype = $title_array[0];
    $title_taxonomy = $title_array[1];

    # Aggiunge la classe se necessario
    if ($title != '' && ($title_posttype == $post_type || $title_taxonomy == $taxonomy)) {
        array_push($classes, 'current-menu-item');
    };
    return $classes;
}
13 apr 2011 03:12:54
0

Ecco la mia soluzione se vuoi lavorare con wp_list_pages.

Aggiungi questo nel tuo 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;
}

Ora aggiungi semplicemente nella tabella wp_options una nuova riga con un option_name di page_for_custom_post_type-xxxx e un option_value con l'ID della pagina che vuoi collegare.

Probabilmente hai notato che esiste già un'opzione chiamata page_for_posts. Se hai solo 1 custom post type puoi impostare la tua pagina in /wp-admin/options-reading.php nel menu a discesa e la navigazione imposterà correttamente il current_page.

Penso che il core di WordPress dovrebbe estendere questa sezione con un menu a discesa per ogni post type registrato.

13 giu 2011 21:58:05
2

Ho deciso di utilizzare le pagine e usare il nome del template della pagina come classe sull'elemento del menu. Questo mi permette di evitare di affollare l'attributo title che non mi piaceva in alcune delle altre soluzioni.

add_filter('nav_menu_css_class', 'mbudm_add_page_type_to_menu', 10, 2 );
//Se un elemento del menu è una pagina, aggiungi il nome del template come classe 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;
    }   
}

Ho anche aggiunto le classi del body nel file header.php

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

Infine, questa soluzione richiede un po' di CSS extra per applicare lo stato selezionato/attivo agli elementi del menu di navigazione. Lo uso per mostrare gli archivi delle tassonomie e i custom post type relativi alla pagina come figli di questa pagina:

/* stati selezionati - include le pagine figlie per tutto ciò che è relativo ai prodotti */
#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 ott 2011 05:28:44
Commenti

Questo mi ha dato il seguente errore:

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

Hai qualche idea su cosa sia successo qui?

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

Oh, penso di aver capito cosa sta succedendo. È perché stai restituendo $classes all'interno dell'istruzione if. Semplicemente spostando return $classes fuori e dopo quel if sembra risolvere l'errore sopra.

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

@Somatic - Ottimo codice! Ho apportato una modifica personalmente. Volevo mantenere l'attributo Title per il suo scopo originale, quindi ho inserito lo slug del Custom Post Type nella relazione del link (XFN) tra le proprietà avanzate del menu che puoi attivare nelle Opzioni Schermo. Ho modificato

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

e l'ho cambiato in

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

Ottimo lavoro Somatic.

Sfortunatamente, non capisco come elencare i tuoi custom post types in una pagina nel modo che spieghi. Se non uso una page-portfolio.php e la aggiungo a una pagina, ottengo solo una pagina 404.

Se faccio come fa Gavin, ho modificato leggermente la tua funzione per rimuovere anche "current_page_parent" dalla pagina del blog in questo modo.

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 dic 2010 14:36:55