web-dev-qa-db-fra.com

WordPress Menu Custom Walker Class

Nous utilisons un accordéon jQuery UI pour afficher un menu dans la barre latérale. Nous avons déjà écrit le balisage et javascript et j'essaie simplement de faire en sorte que wp_nav_menu produise le même balisage que nous avons déjà écrit. Je crée une classe Walker personnalisée qui étend Walker_Nav_Menu.

Voici le balisage que nous visons

<h2><a href="#">Parent Item</a></h2>
<div>
    <ul>
    <li><a href="">Child Item 1</a></li>
    <li><a href="">Child Item 2</a></li>
    <li><a href="">Child Item 3</a></li>
    <li><a href="">Child Item 4</a></li>
    <li><a href="">Child Item 5</a></li>
    </ul>
</div>
<h2><a href="#">Parent Item 2</a></h2>
<div>
    <ul>
    <li><a href="">Child Item 1</a></li>
    <li><a href="">Child Item 2</a></li>
    <li><a href="">Child Item 3</a></li>
    <li><a href="">Child Item 4</a></li>
    <li><a href="">Child Item 5</a></li>
    </ul>
</div>

Malheureusement, je ne parviens pas à obtenir la Walker Class personnalisée pour générer le balisage souhaité. Des exemples ou des tutoriels sur la classe Walker seraient formidables. Je n'ai toujours pas trouvé exactement ce que je cherche sur SE ou Google.

Merci

5
abrudtkuhl

Le moyen le plus simple consiste à étendre la classe Walker_Nav_Menu plutôt que le Walker_Class (car les champs parent/ID sont définis et vous souhaitez souvent conserver une partie du balisage, etc.).

Les principales méthodes sont:

  • start_el/end_el - responsable de l'affichage d'un élément dans une liste
  • start_lvl/end_lvl - responsable de l'affichage d'un sous-menu

De plus, il existe walk et display_element qui contrôlent en grande partie les mécanismes de la classe. Dans la plupart des cas, les quatre fonctions ci-dessus sont celles qui doivent être modifiées dans une classe extensible.

Cela dit, la structure que vous recherchez n'est pas vraiment imbriquée, vous n'utilisez donc pas vraiment la classe Walker dans son intégralité. Cependant, cette classe de marcheur personnalisée vous mènera à l'essentiel:

class SH_Accordian_Walker extends Walker_Nav_Menu {  

    //Start 'sub menu'
    function start_lvl(&$output, $depth=0, $args=array()) {  

        if($depth > 0)
           return parent::end_lvl(&$output, $depth);

        $output .= '<div><ul>';
    }  

    //End 'sub menu'
    function end_lvl(&$output, $depth=0, $args=array()) {  
        if($depth > 0)
           return parent::end_lvl(&$output, $depth);

        $output .= '</ul></div>';
    }  

    // Start element
    function start_el(&$output, $item, $depth=0, $args=array()) {  
        if( 0 == $depth ){
             $output.= '<h2><a href="'.esc_attr($item->url).'">'.apply_filters( 'the_title', $item->title, $item->ID ).'</a></h2>';
             return; 
        }

        // level 2+
        parent::start_el(&$output, $item, $depth, $args);  
    }  

    // Don't need to add any output - sub menus aren't nested
    function end_el(&$output, $item, $depth=0, $args=array()) {
       if($depth > 0)
         parent::end_el(&$output, $item, $depth);
    }  

} 

Ceci est simplement un cours très simple pour montrer ce que vous devez faire. Étant donné que votre structure n'est pas imbriquée - cela pourrait ne pas sembler correct si nous descendons de plus de 2 niveaux (c'est-à-dire pour les petits-enfants).

Usage:

wp_nav_menu( array( 
       'theme_location' => 'primary',
       'walker'=> new SH_Accordian_Walker, 
       'depth'=>2,
       'items_wrap'=> '%3$s'
     ) );

(J'ai récemment écrit ce tutoriel sur Walker Class: http://wp.tutsplus.com/tutorials/creative-coding/understanding-the-walker-class/ que vous pourriez trouver utile)

8
Stephen Harris

J'aurais aimé voir ta réponse avant de descendre dans le terrier du lapin. Cependant, j'ai pu reproduire le balisage fourni par notre concepteur en utilisant une extension de la classe Walker et il fonctionne parfaitement avec l'accordéon jQuery UI.

    class sidebar_nav_walker extends Walker_Nav_Menu {
    function start_el(&$output, $item, $depth, $args) {
      global $wp_query;
      if (0 == $depth) {
        // parent item
        $output .= '<h2>';

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

        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
        $output .= '</h2>';

      } else {
        // child items
        $class_names = $value = '';
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;

        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
        $class_names = ' class="' . esc_attr( $class_names ) . '"';

        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

        $output .= $indent . '<li' . $id . $value . $class_names .'>';

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

        $item_output = $args->before;
        $item_output .= '<a'. $attributes .'>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
      }

    }

  function start_lvl(&$output, $depth, $args=array()) {  
      $output .= "\n<div><ul>\n";  
  }

  // Displays end of a level. E.g '</ul>'  
  // @see Walker::end_lvl()  
  function end_lvl(&$output, $depth, $args=array()) { 
      $output .= "</ul></div>\n";  
  }

    /**
     * @see Walker::end_el()
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Page data object. Not used.
     * @param int $depth Depth of page. Not Used.
     */
    function end_el(&$output, $item, $depth) {

  }
}

Cela m'a amené assez loin. Mais j'ai toujours eu un problème avec wp_nav_menu envelopper le tout dans une UL. Cela a brisé le script jQuery Accordion. Je devais donc le supprimer et, après expérimentation, le menu avec le Walker personnalisé a été rendu comme suit ...

  <nav id="nav">
    <?php
      $menu = wp_nav_menu(
        array(
          'container' =>  false,
          'echo'  =>  false,
          'before'  =>  '',
          'after' =>  '',
          'link_before' =>  '',
          'link_after'  =>  '',
          'walker'  =>  new sidebar_nav_walker()
        )
      );
      echo preg_replace( array( '#^<ul[^>]*>#', '#</ul>$#' ), '', $menu );
    ?>
  </nav>

Remarque: je dis au menu de ne pas se faire écho dans les arguments. Au lieu de cela, j'exécute une expression régulière dessus pour supprimer cette UL de niveau parent.

A noter également .. Cela ressemblera à de la merde si vous ne dites pas à votre jQuery Accordion de ne pas autoheight.

$(function() {
    $("#nav").accordion({
            collapsible: true,
            autoHeight: false
    });
});

Le résultat est quelque peu proche du balisage original de mon concepteur, mis à part les classes que WP ajoute dans.

2
abrudtkuhl