折りたたみが最も簡単 details と summary をjQueryに置き換えるメモ

セレクタを変えただけのスクリプトを追加

jQueryのスクリプトでは、要素をセレクトして何かを実行させます。要素のセレクタといえば、# のIDだとか、. のclass名だとか、h や li みたいなタグだとか、そういうやつです。何かを選んで何かをさせます。
slideToggleという命令を誰に対して行うのか、.js-summary なのか、h3.sub-title なのか、言葉そのものは何だっていいわけです。こちらが言葉を付けて、その言葉で何かを実行させます。

対してHTMLのdetailsとsummary はタグ自体が重要で、このタグ名によってのみ動作が決まります。言葉はdetailsとかsummaryとか決められています。これに合わせて、こちらがその内容を書き示します。

つまりjQueryのかんたんなスクリプトは、要素のセレクタを変えることでどんなやつにも適応できるわけです。
何を当たり前のことをグダグダ書いているかというとこういうことです。

スマホ用ハンバーガーメニュー内に置いたグローバルナビゲーション(メニュー)Widgetに対してslideToggleを与えることができました。

と、さらりと読んで全貌を理解出来る人はあまりいません。では行きます。

スマホのsecondary内メインナビゲーション

この話を書き始めると他の余計な話も混ざってくるので、先にその余計な部分のあらすじを書いてすっ飛ばしますと、それはこうです。

あらすじ

  1. 昨今、サイドバーが流行りません。スマホのせいです。WordPressでも公式テーマがペラい一枚ものデザインに変わってきています。
  2. サイドバーがあったのはtwentyseventeenまでで、このテンプレートは今でも有用です。
  3. サイドバーがあるテンプレートでは、スマホ表示でサイドバーが下に落ちてカッコ悪くい上に使いにくいです。
  4. そこでハンバーガーメニューによるレスポンシブなウインドウ表示がしたくなります。
  5. 最初はスマホ用に簡易な専用メニューを作ったりしていました。
    しかしそもそもサイドバーが全部レスポンシブなスライドメニュー内に収まれば万事解決じゃないのかと気づきます。
  6. サイドバー(#secondary)全部を横からせり出すウインドウに収めようと奮闘、成功させます。
  7. スマホにだけ表示させるため、サイドバーの一番上にグローバルナビゲーション(メインメニュー)のwidgetを置きます。
  8. しかし、メニューに階層表示があると階層がだらだらと表示されてしまいます。
    ここで「階層メニューを開閉させたい」となります。

やっとここまできました。そういうわけで、グローバルメニューのwidget、階層構造がそのまま全部出力された形ですが、これを降りた畳みたい。という話です。
detailsとsummaryでは上手く行きません。だってhtmlタグは成形されて出力済みです。detailsとかsummaryとかってタグを挟み込める余地はありません。
slideToggleのスクリプトならいけそうです。「何に対して命令するのか」のその「何」部分(要素のセレクタです)を自分で書けるからです。すでに仕上がっているリストを折りたたみに対応させることが出来そうに思えます。

Widgetのナビゲーション

widgetから「ナビゲーション」を選んでメニューを選択しますとメニューがサイドバーに現れます。そのメニューには内容に応じたclassが付くので、スクリプトに利用できるかもしれません。まずそれを調べます。

Widgetにメニューを置く。スマホのみで表示させるように、Widget Options や Widget Logic といったプラグインを使用して出現条件を定めますがそれはまた別の話ですね

普通に置くとこのようになります。階層はすべて展開しています。

この展開された部分を折りたたみたいわけです。

この部分をブラウザのインスペクタで調べると、メニュー名に応じたclassが付与されているのが判ります。また、中身のリストにも細かくclassが付与されていることが判ります。それが判ればこっちのものです。

この場合、.menu-home-container、その中の ul#menu-home というものがありました。これが目的のやつですね。これをスライドトグルのスクリプトに反映させましょう。

何かをクリックしたら何かが開く。

というこのスクリプトに反映させるため、「何か」の名を取得したい。さらにインスペクタで探ります。

クリックする「何か」とは何でしょう。階層を持つ要素です。何かが開くの「何か」は何でしょう。階層を持つ要素が内包する要素です。調べましょう。調べました。

階層がある部分、それは「.menu-item-has-children」でした。確かに子を持つアイテムです。判りやすいclass名を付けてくださってありがとう。

子を持つメニューアイテムli.menu-item-has-children をクリックしたら何かが開きます。「隣接する要素」ではないですね。それは「内包する要素」です。ありました。「ul.sub-menu」がそれです。

何かをクリックしたら何かが開く。
has-childrenをクリックしたら内包する sub-menuが開くのです。

とりあえずスクリプトその1を引っ張ってきて、ターゲットを変更しましょう。

jQuery(function(){
    jQuery('.js-summary').each(function(){
        jQuery(this).on('click',function(){
           jQuery(this).toggleClass('open');
            jQuery("+.js-container",this).slideToggle(300);
            return false;
        });
    });
});

これですね。これの、クリック部分を li.menu-item-has-children に、開く部分を ul.sub-menu にセットします。

隣接の場合は “+.js-container” と指定しました。「+」は兄弟要素、すぐお隣さんを選択するセレクタです。ul.sub-menu は内包してますから “>.sub-menu” と、こう書きます。「>」は直下の子要素を示します。「 」(スペース)では含まれるもの全部を含みますから孫にまで手が伸びて上手くないです。「>」であることが最高の働きをするのでお間違いなきよう。

<script>
    // js-details summary 1. js-summary + js-details-container
jQuery(function(){
    jQuery('li.menu-item-has-children').each(function(){
        jQuery(this).on('click',function(){
           jQuery(this).toggleClass('open');
            jQuery(">.sub-menu",this).slideToggle(300);
            return false;
        });
    });
});
</script>

こうなりました。「子を持つli」をクリックしたら、そのクリックしたものの直下の子要素「.sub-menu」のみが表示トグルされます。

ここまでで、次のような動きが手に入りました。

 

いいですね。でも初期状態で展開してしまっています。初期状態は非表示、クリックしたら出現するというのが理想です。というかマイルールです。ですのでここはCSSで調整します。

li.menu-item-has-children>a:before {
    content: "\f139";
    font-family: 'dashicons';
    font-size: 20px;
    line-height: 0;
    vertical-align: -.2em;
}

li.menu-item-has-children.open>a:before {
    content: "\f140";
    font-family: 'dashicons';
}

li.menu-item-has-children > ul.sub-menu {
    display: none;

こんな感じで、初期状態は sub-menu が「display:none」です。ついでにhas-children要素に三角印を付けておきましょう。こうなりました。

完璧です。完璧ですがこれでは駄目です。

「li.menu-item-has-children」はwidget以外にメニューバーにもあるからです。全部の「li.menu-item-has-children」が対象となってしまいますんで、ここはwidgetのみと限定、この例では「.widget_nav_menu .menu li.menu-item-has-children」と、widgetのclassから記述して限定しておきます。

ということで完璧です。

ただの折りたたみスクリプトが、スマホ用レスポンシブスライド何とかのメニュー表示にまで威力を発揮しました。

だらだら書きましたがまとめません。