Descrizione delle voci di menu? Walker personalizzato per wp_nav_menu ()


104

Il normale menu Wordpress è simile a:

Home | Blog | Chi siamo | Contatto

Ma ho visto molte pagine con descrizioni sotto questi link:

Home Page | I nostri blog | Chi siamo | Contattaci
.... raggiungici ... | leggi di più | informazioni di base | Modulo di Contatto

Come raggiungere questo obiettivo?

(Voglio che sia la funzione principale per tutti i miei temi, quindi nessun plug-in per favore, voglio solo sapere come è fatto)

Risposte:


115

È necessario un walker personalizzato per il menu di navigazione.

Fondamentalmente, aggiungi un parametro 'walker'alle wp_nav_menu()opzioni e chiami un'istanza di una classe avanzata:

wp_nav_menu(
    array (
        'menu'            => 'main-menu',
        'container'       => FALSE,
        'container_id'    => FALSE,
        'menu_class'      => '',
        'menu_id'         => FALSE,
        'depth'           => 1,
        'walker'          => new Description_Walker
    )
);

La classe Description_Walkerestende Walker_Nav_Menue modifica la funzione start_el( &$output, $item, $depth, $args )da cercare $item->description.

Un esempio di base:

/**
 * Create HTML list of nav menu items.
 * Replacement for the native Walker, using the description.
 *
 * @see    https://wordpress.stackexchange.com/q/14037/
 * @author fuxia
 */
class Description_Walker extends Walker_Nav_Menu
{
    /**
     * Start the element output.
     *
     * @param  string $output Passed by reference. Used to append additional content.
     * @param  object $item   Menu item data object.
     * @param  int $depth     Depth of menu item. May be used for padding.
     * @param  array|object $args    Additional strings. Actually always an 
                                     instance of stdClass. But this is WordPress.
     * @return void
     */
    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 )
    {
        $classes     = empty ( $item->classes ) ? array () : (array) $item->classes;

        $class_names = join(
            ' '
        ,   apply_filters(
                'nav_menu_css_class'
            ,   array_filter( $classes ), $item
            )
        );

        ! empty ( $class_names )
            and $class_names = ' class="'. esc_attr( $class_names ) . '"';

        $output .= "<li id='menu-item-$item->ID' $class_names>";

        $attributes  = '';

        ! empty( $item->attr_title )
            and $attributes .= ' title="'  . esc_attr( $item->attr_title ) .'"';
        ! empty( $item->target )
            and $attributes .= ' target="' . esc_attr( $item->target     ) .'"';
        ! empty( $item->xfn )
            and $attributes .= ' rel="'    . esc_attr( $item->xfn        ) .'"';
        ! empty( $item->url )
            and $attributes .= ' href="'   . esc_attr( $item->url        ) .'"';

        // insert description for top level elements only
        // you may change this
        $description = ( ! empty ( $item->description ) and 0 == $depth )
            ? '<small class="nav_desc">' . esc_attr( $item->description ) . '</small>' : '';

        $title = apply_filters( 'the_title', $item->title, $item->ID );

        $item_output = $args->before
            . "<a $attributes>"
            . $args->link_before
            . $title
            . '</a> '
            . $args->link_after
            . $description
            . $args->after;

        // Since $output is called by reference we don't need to return anything.
        $output .= apply_filters(
            'walker_nav_menu_start_el'
        ,   $item_output
        ,   $item
        ,   $depth
        ,   $args
        );
    }
}

Oppure, in alternativa, come ha commentato @nevvermind , potresti ereditare tutte le funzionalità della funzione del genitore start_ele semplicemente aggiungere la descrizione a $output:

function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) 
{
    parent::start_el( $output, $item, $depth, $args );
    $output .= sprintf( 
        '<i>%s</i>', 
        esc_html( $item->description ) 
    );
}

Uscita campione:

inserisci qui la descrizione dell'immagine

Ora abilita il campo descrizione wp-admin/nav-menus.phpper ottenere la possibilità di modificare questo campo. Se non lo fai WP semplicemente trasporta il contenuto completo del tuo post in esso.

inserisci qui la descrizione dell'immagine

Ulteriori letture:

E questo è tutto.


11
Se per te l' eredità! = Riscrivi l'intero metodo, mantieni lo stesso nome , prova questo:public function start_el(&$output, $item, $depth, $args) { parent::start_el($output, $item, $depth, $args); $output .= sprintf('<i>%s</i>', esc_html($item->description)); }
nevvermind

2
@nevvermind Dovresti almeno verificare se la descrizione ha del contenuto. ;) La posizione della descrizione nel mio codice di esempio è solo il modo più semplice per illustrare la soluzione. Se è necessario inserire la descrizione nell'ancoraggio, è necessario ricostruire l'intera funzione.
fuxia

1
sì, dovresti scrivere l'intero metodo, non c'è dubbio, ma per le persone che hanno bisogno di (diciamo ...) aggiungerlo, potrebbe solo risparmiare un sacco di mal di testa. E questa è tutta colpa di WP. Arrrgh!
nevvermind

Bello e l'ho usato in questa risposta modificando un po ', forse puoi renderlo migliore se ho perso qualcosa, grazie.
L'Alpha,

Quello che in realtà serviva era il wp_nav_menu , ma avevo bisogno di cambiare il parametro 'container_class', a lavorare per il mio particolare caso d'uso, dove ho una certa condizione scambiato al menu principale per un altro, ma aveva bisogno di classi per essere coerente per i CSS.
D. Dan

33

Da WordPress 3.0 , non hai più bisogno di un walker personalizzato!

C'è il walker_nav_menu_start_elfiltro, vedi https://developer.wordpress.org/reference/hooks/walker_nav_menu_start_el/

Esempio:

function add_description_to_menu($item_output, $item, $depth, $args) {
    if (strlen($item->description) > 0 ) {
        // append description after link
        $item_output .= sprintf('<span class="description">%s</span>', esc_html($item->description));

        // insert description as last item *in* link ($input_output ends with "</a>{$args->after}")
        //$item_output = substr($item_output, 0, -strlen("</a>{$args->after}")) . sprintf('<span class="description">%s</span >', esc_html($item->description)) . "</a>{$args->after}";
    }

    return $item_output;
}
add_filter('walker_nav_menu_start_el', 'add_description_to_menu', 10, 4);

1
Bello! Stavo usando la soluzione nav walker di @toscho, ma è molto più pulita e più facile da mantenere. Dovrebbe essere la risposta accettata, pratica molto migliore.
Neejoh,

8

Questo non è migliore o peggiore di altri suggerimenti; è solo diverso. È anche breve e dolce.

Anziché utilizzare il campo della descrizione come suggerisce @toscho , è possibile compilare il campo "Titolo" su ciascuna voce di menu con il testo desiderato, quindi utilizzare questo CSS:

.menu-item a:after { content: attr(title); }

Sarebbe anche facile usare jQuery per aggiungerlo, ma il testo è abbastanza ornamentale che CSS sembra appropriato.


2

Puoi anche scrivere un <span>elemento dopo l'etichetta di navigazione nei menu e utilizzare la seguente regola CSS per modificarne l' displayimpostazione (è inlineper impostazione predefinita):

span {display:block}

2
Beh, è ​​una soluzione semplice e facile, ma perché usarlo spanse lo fai bloccare comunque? xhtml / html4 non consente gli elementi di blocco all'interno dei collegamenti, html5 invece lo fa, quindi basta usare dive non c'è bisogno di alcun CSS!
James Mitch,
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.