web-dev-qa-db-ja.com

各ul.sub-menuの最後の<li>に.lastクラスを追加します

WordPressメニューにfirstクラスとlastクラスを追加する方法について多くのコードを見ましたが、私の場合は、WPが生成するサブメニューの最後のliにlastクラスを追加したいと思います。 。これが最も単純な形で達成したいことです。

<ul>
    <li>Menu item one</li>
    <li class="has-sub-menu">Menu item two
        <ul class="sub-menu">
            <li>Sub menu item one</li>
            <li>Sub menu item two</li>
            <li class="last">Sub menu item three</li>
        </ul>
    </li>
    <li>Menu item three</li>
</ul>

そしてここに私が現在持っているものがあります、それは最初と最後のクラスを親メニュー項目だけに追加します。これは適応できますか?

function add_first_and_last($items) {
    $items[1]->classes[] = 'first';
    $items[count($items)]->classes[] = 'last';
    return $items;
}

add_filter('wp_nav_menu_objects', 'add_first_and_last');

私はこれをphpに固執し、:last-child(ie 7&8で動作させたい)やjQueryを使わないでください。

4
Andrew

次をfunctions.phpに入れてください

class SH_Last_Walker extends Walker_Nav_Menu{

   function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {

        $id_field = $this->db_fields['id'];

       //If the current element has children, add class 'sub-menu'
       if( isset($children_elements[$element->$id_field]) ) { 
            $classes = empty( $element->classes ) ? array() : (array) $element->classes;
            $classes[] = 'has-sub-menu';
            $element->classes =$classes;
       }
        // We don't want to do anything at the 'top level'.
        if( 0 == $depth )
            return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );

        //Get the siblings of the current element
        $parent_id_field = $this->db_fields['parent'];      
        $parent_id = $element->$parent_id_field;
        $siblings = $children_elements[ $parent_id ] ;

        //No Siblings?? 
        if( ! is_array($siblings) )
            return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );

        //Get the 'last' of the siblings.
        $last_child = array_pop($siblings);
        $id_field = $this->db_fields['id'];

            //If current element is the last of the siblings, add class 'last'
        if( $element->$id_field == $last_child->$id_field ){
            $classes = empty( $element->classes ) ? array() : (array) $element->classes;
            $classes[] = 'last';
            $element->classes =$classes;
        }

        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }
}

使用法

wp_nav_menuを使用していて、 'last'クラスを追加したい場合は、上記のwalkerを指定してください。

wp_nav_menu( array('theme_location'=>'primary','walker' => new SH_Last_Walker(),'depth' => 0) ); 

theme_locationdepthは好きなものにすることができます、重要な部分はwalker属性です。

サイド備考

このコードは、呼び出されたときに$children_elements[$parent_id]配列内の各要素の設定を解除し、最後の要素に到達したとき(つまり、要素が1つしか含まれていないとき)を確認することによって改善できます。ここではwp_list_filterが適していると思います。これは効率を改善しないかもしれませんが、より良いかもしれません。

また、parentフィールドとidフィールドをハードコーディングすることもできます - 移植性のためにこれは行っていません。次のクラスは、提供されているWalkerクラスの拡張機能(ページリスト、カテゴリリストなど)を拡張できます。

4
Stephen Harris

JQueryはこのようになります。

jQuery(document).ready( function($) {
    $('.sub-menu > li:last-child').addClass('last-item');

} );

しかし、PHPに関しては、Rarst _ here _ によって提供されたこの答えを見てください。

更新

上記のリンクからのRartの解決策は事実上うまくいくのか、そしてコードスニペットはそうです。

add_filter( 'wp_nav_menu_items', 'first_last_class' );

function first_last_class( $items ) {

    $first = strpos( $items, 'class=' );

    if( false !== $first )
         $items = substr_replace( $items, 'first ', $first+7, 0 );

    $last = strripos( $items, 'class=');

    if( false !== $last )
         $items = substr_replace( $items, 'last ', $last+7, 0 );

    return $items;
}

出力は私にこのようなものを与えました。

<ul>
    <li class="first">Menu item one</li>
    <li>Menu item two
        <ul class="sub-menu">
            <li class="first">Sub menu item one</li>
            <li>Sub menu item two</li>
            <li class="last">Sub menu item three</li>
        </ul>
    </li>
    <li class="last">Menu item three</li>
</ul>

これは、CSSセレクターを介してul ul li要素を正常にスタイル設定できることを意味します。

3
userabuser

考慮すべき点:IE7とIE8は最後の子をサポートしていませんが、最初の子をサポートしています。そのため、どのCSSを最後の項目に適用する必要があるかに応じて、元に戻すことができます。

また、FWIW、あなたのテーマは他の分野でデフォルトでjQueryを使用しているので(例えばcommentセクション)、それはより早くよりきれいなオプションになるでしょう。

2
Norcross