Descriere pentru elementele de meniu? Walker personalizat pentru wp_nav_menu()

6 apr. 2011, 01:25:50
Vizualizări: 113K
Voturi: 111

Un meniu WordPress normal arată așa:

Acasă | Blog | Despre noi | Contact

Dar am văzut multe pagini cu descrieri sub aceste link-uri:

Acasă | Blogurile noastre | Despre noi | Contact
...vizitează-ne...| citește mai mult| informații de bază| formular de contact

Cum se poate realiza acest lucru?

(Vreau să fie o funcție de bază pentru toate temele mele, deci fără plugin-uri vă rog, vreau doar să știu cum se face)

0
Toate răspunsurile la întrebare 4
5
126

Ai nevoie de un walker personalizat pentru meniul de navigare.

Practic, adaugi un parametru 'walker' la opțiunile wp_nav_menu() și apelezi o instanță a unei clase îmbunătățite:

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

Clasa Description_Walker extinde Walker_Nav_Menu și modifică funcția start_el( &$output, $item, $depth, $args ) pentru a căuta $item->description.

Un exemplu de bază:

/**
 * Creează o listă HTML de elemente de meniu de navigare.
 * Înlocuiește Walker-ul nativ, folosind descrierea.
 *
 * @see    https://wordpress.stackexchange.com/q/14037/
 * @author fuxia
 */
class Description_Walker extends Walker_Nav_Menu
{
    /**
     * Începe generarea elementului.
     *
     * @param  string $output Trimis prin referință. Folosit pentru a adăuga conținut suplimentar.
     * @param  object $item   Obiect de date al elementului de meniu.
     * @param  int $depth     Adâncimea elementului de meniu. Poate fi folosită pentru padding.
     * @param  array|object $args    Șiruri suplimentare. De fapt, întotdeauna o 
                                     instanță a stdClass. Dar acesta este 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        ) .'"';

        // inserează descrierea doar pentru elementele de nivel superior
        // poți modifica acest aspect
        $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;

        // Deoarece $output este trimis prin referință, nu este nevoie să returnăm nimic.
        $output .= apply_filters(
            'walker_nav_menu_start_el'
        ,   $item_output
        ,   $item
        ,   $depth
        ,   $args
        );
    }
}

Sau, alternativ cum a comentat @nevvermind, poți moșteni toate funcționalitățile funcției start_el a părintelui și doar să adaugi descrierea la $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 ) 
    );
}

Exemplu de rezultat:

exemplu de meniu cu descriere

Acum activează câmpul de descriere în wp-admin/nav-menus.php pentru a putea edita acest câmp. Dacă nu faci asta, WP va arunca întregul conținut al postării în el.

activare câmp descriere în administrare meniu

Lecturi suplimentare:

Și asta e tot.

6 apr. 2011 03:15:46
Comentarii

Dacă pentru tine moștenirea != rescrierea întregii metode, ci doar păstrarea aceluiași nume, încearcă asta: 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 nevvermind
14 dec. 2011 15:15:57

@nevvermind Ar trebui măcar să verifici dacă descrierea conține ceva. ;) Poziția descrierii în exemplul meu este doar cea mai simplă modalitate de a ilustra soluția. Dacă trebuie să adaugi descrierea în anchor, trebuie să reconstruiești întreaga funcție.

fuxia fuxia
16 dec. 2011 12:38:44

da, ar trebui să rescrii întreaga metodă, fără îndoială, dar pentru cei care au nevoie să (să zicem...) adauge ceva la ea, acest lucru le-ar putea salva de multe dureri de cap. Și toată vina este a WP. Arrrgh!

nevvermind nevvermind
16 dec. 2011 16:47:54

Foarte bun și l-am folosit în acest răspuns modificându-l puțin, poate poți să-l îmbunătățești dacă am ratat ceva, mulțumesc.

The Alpha The Alpha
28 aug. 2012 17:24:30

Ceea ce aveam nevoie cu adevărat era funcția wp_nav_menu, dar trebuia să modific parametrul 'container_class' pentru cazul meu particular, unde în anumite condiții înlocuiam meniul principal cu altul, dar aveam nevoie ca clasele să rămână consistente pentru css.

D. Dan D. Dan
25 ian. 2018 17:15:25
1
42

Începând cu WordPress 3.0, nu mai este nevoie de un walker personalizat!

Există filtrul walker_nav_menu_start_el, vezi https://developer.wordpress.org/reference/hooks/walker_nav_menu_start_el/

Exemplu:

function add_description_to_menu($item_output, $item, $depth, $args) {

   if (strlen($item->description) > 0 ) {
      // adăugăm descrierea după link
      $item_output .= sprintf('<span class="description">%s</span>', esc_html($item->description));
    
      // sau.. inserăm descrierea ca ultim element în interiorul link-ului ($item_output se termină cu "</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);
23 feb. 2015 17:31:03
Comentarii

Super! Eu foloseam soluția nav walker de la @toscho, dar aceasta este mult mai elegantă și ușor de întreținut. Ar trebui să fie răspunsul acceptat, o practică mult mai bună.

Ronaldt Ronaldt
8 iul. 2015 13:29:04
0

Acest lucru nu este mai bun sau mai rău decât alte sugestii; este doar diferit. Este scurt și la obiect.

În loc să folosești câmpul de descriere așa cum sugerează @toscho, ai putea completa câmpul "Titlu" pentru fiecare element de meniu cu textul dorit, apoi să folosești acest CSS:

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

De asemenea, ar fi ușor să folosești jQuery pentru a-l adăuga, dar întrucât textul este mai mult decorativ, CSS pare mai potrivit.

18 apr. 2012 08:52:12
1

De asemenea, poți scrie un element <span> după eticheta de navigare în meniuri și poți folosi următoarea regulă CSS pentru a schimba setarea display (implicit este inline):

span {display:block}
8 sept. 2011 11:58:03
Comentarii

Este o soluție simplă și ușoară, dar de ce să folosești span dacă îl faci block oricum? xhtml/html4 nu permite elemente block în interiorul link-urilor, însă html5 permite, așa că poți folosi direct div și nu mai ai nevoie de niciun css!

James Mitch James Mitch
5 mar. 2013 23:02:16