web-dev-qa-db-ja.com

最後のサブメニュー項目にカスタムHTMLを追加

私はWordpressのテーマにカスタムメニューを追加しています。メインのサブメニューが</ul>を閉じる前に、最後のサブメニュー項目にカスタムHTMLを追加する必要があります。

新しいメニューを登録しました

//functions.php
function register_my_menus() {
register_nav_menus(
array(
  'accessories'  => __( 'Accessories Menu' )
)
);
}

そして、私は私の新しいメニューを私のヘッダーに呼び出しました。

//header.php
wp_nav_menu( array( 'theme_location' => 'accessories', 
                    'walker'   => BENZ_Walker_Nav_Menu_ACC                 
        ) ); 

このdivを自分のサブメニューに追加するように新しいWalkerを変更しようとしましたが、これによって各メニュー項目のdivが追加されました

// functions.php ==this adds one div foreach li==comment out
class BENZ_Walker_Nav_Menu_ACC extends Walker_Nav_Menu {

function start_lvl(&$output, $depth) {
    $output .= '<ul class="sub-menu">';
}
  function end_lvl(&$output, $depth) {
        //$output .='<div>the div that I want to show only once</div></ul>';
        $output .= '</ul>';
        }
    }       
}

上記の例は、私のニーズに対しては機能しないため、コメントアウトされています。

また、メニューの最後に次の2つの例を追加してHTMLを追加しようとしました。

//functions.php == this shows custom html after the top-level `<li>`
function BENZ_menu_extras($menu, $args) {
if( 'accessories' !== $args->theme_location )
    return $menu;
return $menu . '<div>the div that I want to show only once</div>';
}
add_filter('wp_nav_menu_items','BENZ_menu_extras', 10, 2);

これは非常に近いですが、メニューのトップレベルの階層にHTMLは必要ありませんが、代わりに1レベル深くなります。

私もこの例を試してみました..

function add_last_nav_item($items, $args) {
if (!is_admin() && $args->theme_location == 'accessories') {
$items .= '<div>the div that I want to show only once</div>';
}
return $items;
}
add_filter( 'wp_nav_menu_items', 'add_last_nav_item', 10, 2 );

ただし、これは最初の例と同じです。

どのように私達のdivをここに追加するために$depth変数で上記の関数のどちらかを使うことができます....

<div class="accessories menu">
  <ul id="menu-accessories" class="menu sf-menu">
    <li id="menu-item-1905">
      <a class="sf-with-ul" href="http://#">ACCESSORIES</a>
      <ul class="sub-menu">
        <li id="menu-item-1897">
          <a class="sf-with-ul" href="http://#">stuff</a>
          <ul class="sub-menu">
            <li id="menu-item-1899">stuff1</li>
            <li id="menu-item-1898">stuff1</li>
          </ul>
        </li>
        <li id="menu-item-1903">
          <a class="sf-with-ul" href="http://#">other stuff</a>
          <ul class="sub-menu">
            <li id="menu-item-1906">other stuff1</li>
            <li id="menu-item-1907">other stuff2</li>
          </ul>
        </li>
        <li id="menu-item-1911">
          <a class="sf-with-ul" href="http://#">blue stuff</a>
          <ul class="sub-menu">
            <li id="menu-item-1912">blue stuff 1</li>
            <li id="menu-item-1913">blut stuff 2</li>
          </ul>
        </li>
    <!--This is where i want to put one div so its in the main submenu-->
    <div>the div that I want to show only once</div>
      </ul>
    </li>
  </ul>
</div>

https://jsfiddle.net/qpbpofpp/3/ /

読んでくれてありがとう。

--BEGIN EDIT--これは私が得た最も近いものです..

 //functions.php
 class BENZ_Walker_Nav_Menu_ACC extends Walker_Nav_Menu {
 function start_lvl(&$output, $depth) {
       $output .= '<ul class="sub-menu">';
}
function end_lvl(&$output, $depth) {
    if ($depth = 2){
        $output .= '<div>the div that I want to show only once</div></ul>';
    } else {
        $output .= '</ul>';
           }
    }    
}

3つすべてのサブメニューの後に表示されるようになりましたが、1回だけ表示する必要があります。

5
RobBenz

わかりました。デフォルトでは、end_lvl()関数$depthはサブメニューのときは 0から始まり、深さが深くなるにつれて大きくなります。そのため、{$depth}が0に等しいかどうかをテストして、最初のサブメニューセットにのみ適用する必要があります。

function end_lvl( &$output, $depth, $args ) {
    if( 0 == $depth ) {
        $output .= '<div>the div that I want to show only once</div>';
    }

    $indent = str_repeat( "\t", $depth );
    $output .= "{$indent}</ul>\n";
}
5
Howdy_McGee

wp_nav_menu_itemsのフィルタはこれを行う方法です。以下を実行してください(単にheader.phpというテーマを一時的にハックしてください:

function add_last_nav_item($items, $args) {
  // if (!is_admin() && $args->theme_location == 'accessories') {
    $items .= '<div>the div that I want to show only once</div>';
  // }
  return $items;
}
add_filter( 'wp_nav_menu_items', 'add_last_nav_item', 10, 2 );

wp_nav_menu();

あなたはあなたが説明した効果を正確に見るはずです。あなたがあらゆるレベルでそのコード出力を見ているのなら、おそらくあなたのカスタムウォーカーに何か問題があります。 ソースを見れば - メニューツリーが "ウォーク"された後にCoreでそのフィルタが一度適用されることがわかります。メニューの既存の項目の末尾に、複数の項目を追加しないでください。

コードの表示レベルを制御するには、修正されたウォーカーが最善の方法です。

class BENZ_Walker_Nav_Menu_ACC extends Walker_Nav_Menu {
  private $insert = true;
  function start_lvl(&$output, $depth) {
    $output .= '<ul class="sub-menu">';
  }
  function end_lvl(&$output, $depth) {
    if ($depth = 2 && $this->insert === true){
      $output .= '<div>the div that I want to show only once</div></ul>';
      $this->insert = false;
    } else {
      $output .= '</ul>';
    }
  }    
}

wp_nav_menu(array('walker' => new BENZ_Walker_Nav_Menu_ACC));

$insertクラスプロパティに注目してください。最初の挿入でfalseに設定され、それが一度だけ現れるようにします。

4
s_ha_dum