Evidenziando wp_nav_menu () Classe di antenati senza bambini nella struttura di navigazione?


30

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

Ho un wp_nav_menunella mia intestazione che conteneva tre pagine. Quando sono su una di quelle pagine, il licontenuto di quella pagina nel menu ottiene la classe .current_page_item. Queste tre pagine hanno modelli e questi modelli 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 in realtà bambini, sono solo di un tipo di contenuto che ho associato a quella pagina di livello superiore utilizzando un modello.

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

Spero che abbia un senso - se no, fammi sapere dove ti ho perso! Apprezzo molto qualsiasi aiuto.

- Modificato per specifiche: ad esempio, ho una pagina statica chiamata Workshop che utilizza un modello. La sua lumaca è officine . Il modello ha una funzione get_posts personalizzata e un ciclo al suo interno, che estrae e visualizza tutti i post di un tipo di contenuto personalizzato chiamato workshop . Se faccio clic sul titolo di uno di questi seminari, vengo portato al contenuto completo di quel contenuto. La struttura del permalink del tipo di post personalizzato è impostata su workshop / nome post, così come lo vede l'utente, questi contenuti sono figli della pagina Workshop, quando in realtà sono tutti di un tipo di contenuto ma non correlati alla pagina. È quel divario che devo colmare efficacemente nel menu, evidenziando la voce di menu "Workshop" durante la navigazione del contenuto di tipo "workshop".

Ancora una volta, spero che abbia un senso, penso di aver detto 'workshop' verso l'alto di 20 volte in un paragrafo!


@Gavin - Puoi includere qualche dettaglio in più su ciò che stai cercando di realizzare. È più facile scrivere una risposta in termini concreti che se proviamo a farlo in astratto. Inoltre, se potessi spiegare la struttura del tuo URL relativa a questi, sarebbe utile.
MikeSchinkel,

1
@Gavin - Questo aiuta. Quindi la tua opzione di menu di livello superiore è un elenco di seminari in "Workshop" con un percorso di /workshops/e quando un utente si trova su una pagina del workshop (cioè /workshops/example-workshop/) vuoi che la voce di menu "Workshops" abbia la classe current_page_itemassegnata, corretta?
MikeSchinkel,

wp_nav_menu () espone la classe corrente-menu-antenata
Daniel Sachs,

Risposte:


29

C'è una soluzione più semplice. Dimentica la creazione di pagine per ogni tipo di post solo in modo da poter disporre di elementi di navigazione, poiché, come hai appreso, WP non ha modo di riconoscere che i tipi personalizzati che stai navigando sono correlati a quella pagina.

Invece, crea un collegamento personalizzato in Aspetto-> Menu. Inserisci l'URL che restituirà il tuo tipo personalizzato e assegnagli un'etichetta, quindi premi "Aggiungi al menu".

http://example.com/workshops/

o non-abbastanza-permalink:

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

questo da solo creerà semplicemente un pulsante di navigazione che visualizza tutti i post con quel tipo di post personalizzato e aggiungerà anche la classe di voci di menu corrente quando si fa clic su quella voce di navigazione, ma non aggiungerà ancora la classe di navigazione su qualsiasi URL diverso da questo

Quindi, una volta creato, vai nella configurazione per quel nuovo elemento e inserisci la lumaca del tipo di post personalizzato nel campo "Attributo titolo" (puoi anche usare il campo descrizione, ma quello è nascosto nelle opzioni della schermata di amministrazione per impostazione predefinita).

Ora, devi agganciare il nav_menu_css_classfiltro (che viene attivato per ogni elemento di navigazione) e verificare se il contenuto visualizzato è del tipo di post indicato nell'elemento di navigazione personalizzato:

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, verificheremo che i contenuti del campo Attributo titolo non siano vuoti e che corrispondano al post_type corrente da interrogare. In tal caso, aggiungiamo la classe current-menu-item al suo array di classi, quindi restituiamo l'array modificato.

Puoi modificarlo in modo che corrisponda semplicemente al titolo dell'elemento di navigazione, ma se per qualche motivo desideri assegnare un titolo all'elemento di navigazione in modo diverso rispetto alla semplice lumaca del tipo di post, l'utilizzo del campo Attributo del titolo o Descrizione ti dà quella flessibilità.

Ora, ogni volta che visualizzi un singolo elemento (o probabilmente anche elenchi di archivi) di un tipo di post che corrisponde a un elemento del menu di navigazione, a quell'elemento verrà assegnata la voce di menu corrente della classe CSS in modo che la tua evidenziazione funzionerà.

Non sono necessarie pagine o modelli di pagina ;-) La query URL si occupa di recuperare i post giusti. Il modello di loop si occupa della visualizzazione dell'output della query. Questa funzione si occupa di riconoscere ciò che viene mostrato e aggiungere la classe CSS.

BONUS

Puoi persino automatizzare il processo usando wp_update_nav_menu_item, generando automaticamente voci di menu per tutti i tuoi tipi di post. Per questo esempio, devi prima aver recuperato il $menu_idmenu di navigazione a cui desideri aggiungere questi elementi.

$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'
        )
    );
}

Questa è roba! Sto usando i modelli di pagina solo perché i layout sono piuttosto complessi per quelle pagine e non elencano solo le pagine, tuttavia posso comunque utilizzare quel filtro fornito per controllare 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,

ho dovuto rimuovere l' current_page_parentelemento di navigazione che era il mio blog, ma per il resto ha funzionato. grazie
becco

questo non ha funzionato per me, dal momento che ho $item->attr_titletirato fuori il TITOLO, e ho scritto il titolo in maiuscolo. quindi ho cambiato l'attributo in $item->post_namee ora funziona bene per me.
honk31,

Ho provato a far funzionare il codice per il mio tema, ma non riesco a farlo funzionare. Non ci sarà alcuna classe applicata alla mia voce principale nel menu, quando sono sul tipo di post personalizzato portfolio. Ho usato il codice sopra. Quale può essere il problema?
Casper,

4

invece di usare

$ post_type = get_query_var ('post_type');

Potresti provare:

$ post_type = get_post_type ();

A volte il tipo di post non è impostato nella query var. Questo è il caso del post_type predefinito di "post", quindi se si desidera evidenziare un post che è stato elencato da una pagina di elenco, sarà necessario utilizzarlo. get_very_var () restituisce solo una stringa vuota per i tipi di post 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;
}

2

@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 è di utilizzare l'attributo Title della voce di menu per memorizzare sia il nome del post_type sia il nome della tassonomia, separati da un punto e virgola, e quindi esplosi dalla funzione.

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

2

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 nella tabella wp_options una nuova riga con un nome_opzione di page_for_custom_post_type-xxxx e un valore_opzione con l' ID pagina che vuoi connettere.

Forse hai riconosciuto che esiste già un'opzione chiamata page_for_posts . Se hai solo 1 tipo di post personalizzato, puoi impostare la tua pagina in /wp-admin/options-reading.php nel menu a discesa e la navigazione imposterà correttamente la pagina corrente.

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


2

Ho deciso di rimanere con le pagine e utilizzare il nome del modello di pagina come classe sull'elemento di navigazione. Questo mi permette di evitare di ingombrare l'attributo del titolo che non mi è piaciuto di alcune delle altre soluzioni.

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

Ho anche aggiunto classi di body a header.php

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

Infine, questa soluzione richiede alcuni CSS aggiuntivi per applicare lo stato selezionato / attivo alle voci del menu di navigazione. Lo uso per mostrare archivi di tassonomia e tipi di post personalizzati relativi alla pagina come elementi secondari di questa pagina:

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

Questo mi ha dato il seguente errore: hai Warning: join() [function.join]: Invalid arguments passed in /home/path/to/wp-includes/nav-menu-template.php on line 76 idea di cosa sia successo qui?
Jeff K.

Oh, penso di vedere cosa sta succedendo. È perché stai restituendo $ classi all'interno dell'istruzione if. Il semplice spostamento return $classesall'esterno e successivamente ifsembra risolvere l'errore sopra riportato.
Jeff K.

1

@Somatic - Ottimo codice! Ho fatto un cambiamento da solo. Volevo mantenere l'attributo del titolo per lo scopo previsto, quindi ho inserito la lumaca Tipo di messaggio personalizzato nelle proprietà del menu avanzato Link Relationship (XFN) che è possibile abilitare in Opzioni schermo. Ho modificato

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

e lo ha cambiato in

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

0

Bel lavoro Somatic.

Sfortunatamente, non capisco come puoi elencare i tuoi tipi di post personalizzati in una pagina come spieghi. Se non utilizzo un page-portfolio.php e lo aggiungo a una pagina, ottengo solo 404 pagine.

Se mi piace Gavin, ho modificato la tua funzione un po '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;

}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.