WordPressでカスタムメニューのウィジェットのようなものを作る

もともとあるサイトをもとにテーマを作成していたのですが、BootstrapのNavbarで使用できる、divider機能をどう使えばよいか迷いました。

Bootstrap の divider 機能 (矢印部分)

画像のように、ドロップダウンメニューの最後だけであれば、Walkerのend_lvlあたりにタグを追加してやればいいのですが、リストの中間にdividerを設置したい場合に困ってしまいます。

そこで、WordPressにある、ナビメニューのカスタマイザー機能をうまく使えないかな、と考えました。

カスタマイザー

ここで視覚的に変更できると楽だと思うのですが、純正状態で用意されているのは、「固定ページ」「投稿」「カスタムリンク」「カテゴリー」の4つのみ。

特定の名前を指定した、この4つのうちどれか (例えば”divider”という名前のカテゴリー) を使って、Walker内で$item->titleから判別し、dividerを表示してもいいけど・・・。

・・

・・・

いや、それは違うだろ(笑)

 

ということで新しい要素を用意してみようと試みたのですが・・・。

この”要素”はなんて呼ばれてるの・・・?

カスタマイザー上部から見ることのできるヘルプには、「ウィジェット」と、公式ドキュメントには「アイテム」などと、どれが正しいのやら・・・。

日本語で検索しても何も出てきませんでした・・・。

 

管理画面のソースコードを覗いて、それを基にwpのソースコードを辿っていくと以下の関数に当たった。

function wp_nav_menu_post_type_meta_boxes() in /wp-admin/includes/nav-menu.php

なるほど。この要素がそろった項目のかたまり を メタボックス(meta box) って呼んでるのね。(なおここまで到達するのに3日かかった模様)

そこで「WordPress meta box custom menu」と検索してみたら、たくさん情報が出てきました。

どうでもいいけど、日本語のプラグイン解説サイトって英語直訳しただけのだったり、PHPしか触ったことのなさそうな方が書いてたりと役に立たないの多いですよね・・・。解説するならそれなりに知識つけて下され・・・。(特大ブーメラン)

結構情報があったので必要な要素だけに絞って作ってみました。

調べてみて分かったことまとめ

  • メタボックスは、add_meta_box() 関数で登録できる
  • add_meta_box() 関数の第4, 5引数には、それぞれ’nav-menus’, ‘side’を渡さなくてはならない
  • admin_init にフックをかけてやるといいらしい
  • 自分でつくったメタボックスを囲っている<div>タグにはidをつける必要がある (例: <div id=”custom-nav-menu-metabox”>)
  • 同様に、”メニューに追加”ボタンとなる、<input type=”submit”>タグにはidをつける必要がある。その際、上で付けたidの先頭に、”submit-“とつけなくてはならない。 (例: <input type=”submit” id=”submit-custom-nav-menu-metabox” />)

これをもとに作ってみたのがこちら

<?php
add_action('admin_init', 'register_custom_menu_metabox');

function register_custom_menu_metabox() {
	add_meta_box('custom-nav-menu-item-divider-metabox', 'ディバイダー (区切り線)', 'render_custom_menu_metabox', 'nav-menus', 'side', 'low');
}

function render_custom_menu_metabox() {
	/**
	 * メニューのメタボックスを表示します
	 **/
	global $_nav_menu_placeholder;
	$nav_menu_id = "custom-nav-menu-metabox";
	$menu_item_number = intval($_nav_menu_placeholder) - 1;
	?>
	<div id="<?php echo $nav_menu_id; ?>">
		<p>ドロップダウンリストの区切り線です<br />一番上の階層へ追加しても何も起こりません</p>

		<div id="tabs-panel-my-plugin-all" class="tabs-panel tabs-panel-active">
			<ul id="my-plugin-checklist-pop" class="categorychecklist form-no-clear" >
				<li>
					<label class="menu-item-title">
						<input type="checkbox" class="menu-item-checkbox" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-object-id]" value="1" /> チェックを入れてください
					</label>

					<input type="hidden" class="menu-item-db-id" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-db-id]" value="0" />
					<input type="hidden" class="menu-item-object" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-object]" value="divider-object-slug" />
					<input type="hidden" class="menu-item-parent-id" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-parent-id]" value="0" />
					<input type="hidden" class="menu-item-type" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-type]" value="divider" />
					<input type="hidden" class="menu-item-title" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-title]" value="ディバイダー" />
					<input type="hidden" class="menu-item-url" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-url]" value="$item->url" />
					<input type="hidden" class="menu-item-target" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-target]" value="" />
					<input type="hidden" class="menu-item-attr_title" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-attr_title]" value="" />
					<input type="hidden" class="menu-item-classes" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-classes]" value="" />
					<input type="hidden" class="menu-item-xfn" name="menu-item[<?php echo $menu_item_number; ?>][menu-item-xfn]" value="" />
				</li>
			</ul>
		</div>

		<p class="button-controls">
			<span class="add-to-menu">
				<input type="submit" class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu' ); ?>" name="add-my-plugin-menu-item" id="submit-<?php echo $nav_menu_id; ?>" />
				<span class="spinner"></span>
			</span>
		</p>
	</div>
	<?php
}
?>

ガバガバスクリプトですがご了承ください()

動かしてみると・・・

左側のメタボックスに作ったアイテムが追加されています。

追加中・・・

追加できた!!

この状態では何もできないので、トップメニューのWalkerから$item->typeによってこのアイテムを判別してディバイダーを表示してやるようにしましょう。

そして以下のように設定し、

 

確認すると・・・

しっかりと表示されています!

つくってみて分かったこと

色々と試してみて動かなかったりしたときは以下を確認してみてください。

  • グローバル変数 “$_nav_menu_placeholder の値 – 1” を、inputタグのnameに使う (例: name=”menu-item[その値][menu-item-db-id]” )
  • 要素が増えるのであれば更に-1する
  • 各要素 (アイテム) ごとにhiddenな<input>タグがたくさん使われる
  • checkboxはどうやら残しておかないと正しく動かないっぽい (Javascriptがそのように組まれているのだろう)
  • checked=”checked”とつけてもいいけど、disabledにすると一回のページ読み込みで1個のディバイダーしか追加できなくなるので不便
  • PHPのスクリプトよりHTMLタグを正しく書いてやることの方が大事

作ってみると意外とあっさりしてました。

コメントを残す