[WP/JS覚書]カスタムメニューの子ページをJQueryでドロップダウン(アコーディオン)構造にしたい場合のtips

2013年5月13日

カスタムメニューのプラグインやカスタマイズで探してもなかなか出てこなくて、
最終的にこちらのページリストのカスタマイズ方法を説明されてるページが大変参考になりました。
こちらのスクリプト記述を利用させてもらいました。
ありがとうございます。

WordPress 階層構造のページリストをドロップダウンメニューにする | hijiriworld Web

カスタムメニュー用にfunctions.jsを変更

参考元のページは、固定ページのリスト(wp list pages)をナビゲーションにしているので、これをカスタムメニューにしたときとの違いを照合しました。

hogehoge.comにてドロップダウンしたいとこだけ抜き出したが、こんな感じ。

<ul id="menu-mainnavi" class="menu">
<li id="menu-item-32" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-32"><a href="http://hogehoge.com/wp/menu/">Menu</a>
<ul class="sub-menu">
<li id="menu-item-98" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-98"><a href="http://hogehoge.com/wp/menu/food/">Food</a></li>
<li id="menu-item-106" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-106"><a href="http://hogehoge.com/wp/menu/drink/">drink</a></li>
</ul>
</ul>

見比べると、以下のクラス名が対応してることがわかりました。(アンダーバーとハイフンの違いにも注目!!)

page_item ⇔ menu-item
children ⇔ sub-menu
current_page_item ⇔ current-menu-item

これを元に紹介ページのfunctions.jsを以下のように書き換えました。

$(document).ready(function(){
    $("ul.sub-menu").hide();
    $("li.menu-item").hover(function() {
        $("ul.sub-menu",this).slideDown("fast");
    },
    function() {
        $("ul.sub-menu",this).slideUp("fast");
    });
});

このfunctions.jsを任意の場所にアップします。
Jqueryは恐らく他の仕様で既に入ってる場合が多いと思うのですが、これがないと動かないですぞ!
念のため下記の記述にはJqueryのリンクも入れておきます。

wp_enqueue_script関数でスクリプトタグの仕込み

20130513追記
最初はwp_enqueue_script関数で、function.jsに書いたほうがスマートと思ってたのですが、考えてみると他のscriptで直書きにしているものもあるので、競合の調整を考えると、最初の導入時はヘッダーに素直に直書きの方がいいんじゃないかと今は考えています。
ある程度テンプレートや使うJSが固まって、それを一気にfunction.jsに記述するというのが最終形態と考えます。

下の記述をheader.phpかfunction.phpに記述しますが、3.2.1以前ですとwp_enqueue_script関数は
<php wp_head(); ?>より前に記述しないと出力されないので注意。
◯function.phpに記述する場合

wp_enqueue_script('jquery.min.js', get_bloginfo('template_url').'/js/jquery.min.js');
wp_enqueue_script('functions', get_bloginfo('template_url').'/js/functions.js');

◯header.phpに記述する場合
Wordpressフォルダ内にJSフォルダを置く場合

<script src="<?php bloginfo('template_url'); ?>/js/function.js"></script>

vicunaのvegaスタイルのJSフォルダに入れる場合(自分用)

<script src="<?php bloginfo('template_url'); ?>/style-vega/js/function.js"></script>

以下はwp_enqueue_scriptを使った場合

<?php wp_enqueue_script('jquery.min.js', get_bloginfo('template_url').'/js/jquery.min.js'); ?>
<?php wp_enqueue_script('functions', get_bloginfo('template_url').'/js/functions.js'); ?>

※Jqueryのバージョン1.6.1と1.6.2→1.6.1で動くことを確認しています。
どこまでバージョン落としても大丈夫なのかはわからんです。

実際のソースには、以下のように出力されてます。

<script type='text/javascript' src='https://hogehoge.com/wp/wp-content/themes/wp.vicuna.exc/js/jquery-1.6.1.min.js?ver=3.3.2'></script>
<script type='text/javascript' src='https://hogehoge.com/wp/wp-content/themes/wp.vicuna.exc/js/functions.js?ver=3.3.2'></script>

参考

wp_enqueue_scriptの仕様がWordPress3.3でちょこっと変わったって話 | マイペースクリエイターの覚え書き
3.3以降から出力位置は</body>の直前にも出力できるようになったそうです。

WordPress で jQuery などの外部ファイルを読み込む wp_enqueue_script() | ウェブル
wp_enqueue_script(‘jquery’);でWordpressが元々梱包しているjqueryを呼び出してくれるとのことだったのだが、今回のはちゃんとjqueryを指定しないとうまくいかなかったです。

最終形態

2回めに設置したときに改めて、wp_enqueue_scriptについて調べ直しました。

最終的にはjsフォルダは直下として、function.phpに前に出力するように記述するのが一番スマートな気がしてます。

◯function.phpに記述した場合で、前に出力する記述

wp_enqueue_script('jquery-1.6.2.min.js','/js/libs/jquery-1.6.2.min.js', array(), '1.0' ,true);
wp_enqueue_script('functions','/js/functions.js', array(), '1.0' ,true);

CSSの調整

元ページに参考のCSSが載ってますが、子ページのない時に作ってあった自前のCSSで調整しました。

参考サイトさんの、このへんの法則をヒントに調整できそうです。

初期状態

・すべてのページ(li)に menu-item というクラス名が付く。
・子ページのページリスト(ul)に sub-menu というクラス名が付く。

親ページがアクティブな時

・現在アクティブなページ(li)に current-menu-item というクラス名が付く。

子ページがアクティブな時

・現在アクティブなページ(li)に current-menu-item というクラス名が付く。
・その直近の親ページ(li)に current-menu-ancestor current-menu-parent というクラス名が付く。

ちなみに子ページがアクティブなときは、直近の親ページになぜか以下のクラス名も付加されます。
どう見てもクラス名をアンダーバーからハイフン仕様に変更したっぽいよね・・・(ーー;
バージョンアップ時の変更と整合性をとるためでしょうか。

current-page-ancestor current-page-parent
current_page_parent current_page_ancestor

20121210追記_親ページ非公開時の子ページの取り扱い

期間限定のページが終わって、そのページを削除することになったのですが、
Wordpressのこの仕様ですと、固定ページを非公開にすれば、自動的にメニューから消えます。そこが便利!
しかし、もし親ページとそれに連なる子ページがある場合で、親ページだけ非公開にすると、子ページは自動的に親となってメニューの一番下に付きます。
この場合、子ページも非公開にするか、子ページだけ残す場合は順番を見直すことを忘れないように。