it-swarm.dev

Evidenziando wp_nav_menu () Classe degli antenati senza figli nella struttura della Nav?

( Nota dei moderatori: Originariamente era intitolata "wp_nav_menu Classe di antenato senza figli nella struttura di navigazione")

Ho un wp_nav_menu nella mia intestazione che contiene tre pagine. Quando sono su una di quelle pagine, il li che contiene 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, il percepito "figli" di questa pagina di primo livello non sono in realtà bambini, sono solo di un tipo di contenuto che ho associato a quella pagina di primo livello utilizzando un modello.

Mi piacerebbe che gli elementi del menu di livello superiore ottenessero una classe 'current-ancestor' quando l'utente sta sfogliando una singola pagina di un determinato tipo di post, ancora una volta, associata a quella pagina solo in una query personalizzata nel file del modello.

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

- Modificato per specifiche: Ad esempio, ho una pagina statica chiamata Workshops che sta usando un modello. La sua lumaca è workshops . Il modello ha una funzione personalizzata get_posts e un ciclo al suo interno, che estrae e visualizza tutti i messaggi di un tipo di contenuto personalizzato chiamato workshops . Se faccio clic su uno dei titoli di questi workshop, sono portato al contenuto completo di quel contenuto. La struttura di permalink del tipo di post personalizzato è impostata su workshops / postname , così come l'utente vede, questi pezzi di contenuto sono figli della pagina Workshop, quando in realtà sono tutti un tipo di contenuto ma non correlato alla pagina. È quel divario che ho bisogno di chiudere efficacemente nel menu, evidenziando la voce di menu 'Workshop' quando sfoglia il contenuto di tipo 'workshop'.

Ancora una volta, spero che abbia senso, penso di aver detto "workshop" di 20 volte in un paragrafo!

30
Gavin

C'è una soluzione più semplice. Dimentica la creazione di pagine per ogni tipo di post solo così puoi avere elementi di navigazione, perché 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. Basta inserire l'URL che restituirà il tipo personalizzato e assegnargli un'etichetta, quindi premere "Aggiungi al menu".

http://example.com/workshops/

o non-piuttosto-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 del menu corrente quando hai fatto clic su quell'elemento di navigazione, ma non aggiungerà ancora il nav classe su qualsiasi URL diverso da questo

Quindi, una volta creato, accedi alla configurazione per quel nuovo oggetto e inserisci lo slug del tipo di post personalizzato nel campo "Title Attribute" (puoi anche utilizzare il campo description, ma quello è nascosto nelle opzioni della schermata di amministrazione di default).

Ora devi agganciare il filtro nav_menu_css_class (che viene attivato per ogni elemento di nav) e controllare 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, controlleremo che i contenuti del campo Attributo titolo non siano vuoti e se corrispondano al post_type corrente interrogato. In tal caso, aggiungiamo la classe del menu corrente al suo array di classi, quindi restituiamo l'array modificato.

È possibile modificare questo per abbinare semplicemente il titolo dell'elemento di navigazione, ma se per qualche motivo si desidera intitolare l'oggetto di navigazione in modo diverso rispetto allo slug normale del tipo di post, utilizzando il campo Attributo titolo o Descrizione si ottiene tale flessibilità.

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

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

BONUS

Puoi persino automatizzare il processo utilizzando wp_update_nav_menu_item, facendo in modo che gli elementi del menu vengano generati automaticamente per tutti i tipi di post. Per questo esempio, prima dovresti recuperare il $menu_id del menu di navigazione in 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'
        )
    );
}
29
somatic

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 per il post_type predefinito di "post", quindi se si desidera evidenziare un post che è stato elencato da una pagina di elenco, è necessario utilizzare questo. get_very_var () restituisce semplicemente 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;
}
4
Eric

@Somatic: è fantastico! Ho modificato un po 'il tuo codice, quindi funziona anche per una specifica tassonomia (che sto usando solo per il post_type correlato). L'idea è di usare l'attributo Title dell'oggetto item per memorizzare sia il nome del post_type AND 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
tzeldin88

Ho deciso di restare 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 titolo che non mi piaceva su 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 le classi del corpo a header.php

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

Infine questa soluzione richiede qualche css in più per applicare lo stato selezionato/attivo alle voci del menu di navigazione. Lo uso per mostrare gli archivi di tassonomia e i tipi di post personalizzati relativi alla pagina come figli 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;}
2
Steve

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

Adesso aggiungi solo una tabella wp_options a una nuova riga con nome_opzione di page_for_custom_post_type-xxxx e a option_value con page-ID u vuoi collegarti.

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 wordpress core dovrebbe estendere questa sezione con un menu a discesa per ogni tipo di messaggio registrato.

2
Temo

@Somatic - Grande codice! Ho fatto un cambiamento me stesso. Volevo mantenere l'attributo Title per lo scopo previsto, quindi ho inserito lo slug Custom Post Type nelle proprietà avanzate del menu Link Relationship (XFN) che è possibile abilitare in Opzioni schermo. Ho modificato

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

e cambiato in

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

Bel lavoro Somatico.

Sfortunatamente, non capisco come sia possibile elencare i tipi di post personalizzati in una pagina come spiegato. Se non utilizzo un page-portfolio.php e lo aggiungo a una pagina, tutto quello che ottengo è 404 pagine.

Se faccio come fa Gavin, ho modificato la tua funzione un po 'per rimuovere anche "current_page_parent" dalla pagina del blog come questa.

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;

}

0
Vayu