web-dev-qa-db-fra.com

Description des éléments de menu? Walker personnalisé pour wp_nav_menu ()

Normal Wordpress Menu ressemble à:

Accueil | Blog | À propos de nous | Contact

Mais j'ai vu de nombreuses pages avec des descriptions sous ces liens:

Page d'accueil | Nos blogs | À propos de nous | Contact
.... nous rencontrer ... | lire plus | informations de base | formulaire de contact

Comment y parvenir?

(Je veux que ce soit la fonction principale de tous mes thèmes, donc pas de plugins s'il vous plaît, je veux juste savoir comment ça se passe)

102
Wordpressor

Vous avez besoin d'un programme personnalisé pour le menu de navigation.

Fondamentalement, vous ajoutez un paramètre 'walker' aux options wp_nav_menu() et appelez une instance d'une classe améliorée:

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_Walker étend Walker_Nav_Menu et modifie la fonction start_el( &$output, $item, $depth, $args ) pour rechercher $item->description.

Un exemple de 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
        );
    }
}

Ou, alternativement, comme @nevvermind a commenté , vous pouvez inherit toutes les fonctionnalités de la fonction start_el du parent et seulement append la description à $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 ) 
    );
}

Exemple de sortie:

enter image description here

Activez maintenant le champ de description dans wp-admin/nav-menus.php pour pouvoir modifier ce champ. Si vous n'êtes pas WP, vous n'y mettez que le contenu complet de votre message.

enter image description here

Lectures complémentaires:

Et c'est tout.

113
fuxia

Depuis WordPress 3.0 , vous n’avez plus besoin d’un marcheur personnalisé!

Il y a le filtre walker_nav_menu_start_el , voir https://developer.wordpress.org/reference/hooks/walker_nav_menu_start_el/

Exemple:

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);
31
Joost

Ce n'est pas meilleur ou pire que d'autres suggestions; c'est juste différent. C'est court et gentil aussi.

Plutôt que d'utiliser le champ de description comme @toscho suggère, vous pouvez renseigner le champ "Titre" de chaque élément de menu avec le texte souhaité, puis utiliser ce code CSS:

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

Il serait également facile d’utiliser jQuery pour l’ajouter, mais le texte est suffisamment ornemental pour que CSS semble approprié.

8
mrwweb

Vous pouvez également écrire un élément <span> après le libellé de navigation dans les menus et utiliser la règle CSS suivante pour modifier le paramètre display (il s'agit de inline par défaut):

span {display:block}
2
Markus