web-dev-qa-db-ja.com

ワードプレスメンテナンスウォーカークラス

サイドバーにメニューを表示するためにjQuery UIアコーディオンを使用しています。すでにマークアップとJavaScriptを作成していますが、wp_nav_menuから出力したマークアップを作成しようとしています。 Walker_Nav_Menuを拡張したカスタムWalkerクラスを作成しています。

これが私たちが目指しているマークアップです。

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

残念ながら、私が欲しい方法でマークアップを出力するためのカスタムWalkerクラスを取得することはできません。 Walker Classに関する例やチュートリアルは素晴らしいものです。まだSEやGoogleで探しているものをまだ正確に見つけていません。

ありがとう

5
abrudtkuhl

最も簡単な方法は、Walker_Nav_MenuではなくWalker_Classクラスを拡張することです(parent/IDフィールドが設定されていて、マークアップなどを維持したい場合が多いため)。

主な方法は次のとおりです。

  • start_el/end_el - リスト内の要素を表示する責任があります
  • start_lvl/end_lvl - サブメニューの表示を担当

また、クラスの仕組みを制御するだけのwalkdisplay_elementがあります。ほとんどの目的のために、上記の4つの関数は拡張クラスで変更される必要があるものです。

そうは言っても、あなたが持つ構造は実際にはネストされていないので、ここでは実際にWalkerクラスを完全には使用していません。ただし、このカスタムウォーカークラスは、ほとんどの場合にあなたを導きます。

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

} 

これは、あなたがする必要があることを実演するための非常に単純なクラスです。あなたの構造は入れ子になっていないので - これは我々が2つのレベルを超えて下がる(すなわち、孫たちに)場合、正しく見えないかもしれません。

使用法:

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

(私は最近このチュートリアルをWalker Classで書いています: http://wp.tutsplus.com/tutorials/creative-coding/understanding-the-walker-class/ あなたが役に立つと思うかもしれません)

8
Stephen Harris

私がウサギの穴を降りる前に私があなたの答えを見たことを願います。しかし、私は、Walkerクラスの拡張を使用して、私たちのデザイナーによって提供されたマークアップを複製することができました、そしてそれはjQuery UI Accordionとうまく働きます。

    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) {

  }
}

それは私をかなり遠くに連れて行きました。しかし、私はまだwp_nav_menuがすべてをULにラップしているという問題を抱えていました。これはjQuery Accordionスクリプトを壊しました。だから私はそれを削除する必要があり、実験の後に次のようにカスタムWalkerでメニューをレンダリングすることになった….

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

注:私はメニューに引数の中に自分自身をエコーし​​ないように伝えます。代わりに、その親レベルのULを削除するために正規表現を実行します。

また、注目に値します..あなたがあなたのjQueryアコーディオンに自動高さを指示しないならば、これはがらくたのように見えるでしょう。

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

WPが追加したクラスを除いて、結果は私のデザイナーからのオリジナルのマークアップに多少近くなります。

2
abrudtkuhl