ウィジェットのツリーメニューの開閉をjQueyスクリプトとCSSで実装する
WordPressでの企業ブログの制作で、カテゴリーや固定ページのウィジェットに対して、開閉可能なツリーメニューを設置する機会が二度ほどあった。
jQueryの素のtoggle()は楽で古いブラウザに互換性はあるけど、メニューの開閉のスライドがなんともまぁ昔ながらの様式だし論外。(というか、jQueryのtoggle()を未だに使っている人って流石にいないよね・・・?)
かといってがっつり作り込まれたツリーメニュー展開用のスクリプトもイマイチ使う気になれない。スクリプトの様式に合わせてフィルターフックでウィジェットをいじるのも嫌だし、ソースコードの管理が面倒くさいし。
というわけで、時間をあまりかけずに、シンプルかつそれなりにきれいに動かしたいので、jQueyのスクリプトとCSSでざっくりとしたツリーメニューを開閉するコードを作成した。
動きとしてはこんなやつ。
なんかB◯otstrapとかF◯undationとかにあるあるありがちなものだけど、管理しづらいものよりはるかにマシだろうと思う。
今回はWordPressが絡むのでスクリプトのダウンロードとかは割愛するが、コード内容と実装は以下。
まずは、CSSを「treemenu.css」、jQueryスクリプトを「treemenu.js」とでもして保存する。
CSS – treemenu.css
.treemenu{
position: relative;
z-index: 10;
}
.treemenu > ul{
height: 0;
overflow: hidden;
transition-duration: 0.5s;
transition-timing-function: ease;
}
.treemenu.treemenu-after > ul{
height: auto !important;
}
.treemenu > ul > li{
opacity: 0;
transform: translateY(-20px);
transition-duration: 0.5s;
transition-timing-function: ease;
}
.treemenu.treemenu-opened > ul > li{
opacity: 1;
transform: translateY(0);
}
.treemenu > .treemenu-button{
position: absolute;
z-index: 10;
top: 0;
right: 0;
cursor: pointer;
transform: rotate(0deg);
transform-origin: 50% 50%;
transition-duration: 0.4s;
transition-timing-function: ease;
}
.treemenu.treemenu-opened > .treemenu-button{
transform: rotate(180deg);
transform-origin: 50% 50%;
}
jQueryスクリプト – treemenu.js
(function($){
$.fn.treeMenu = function(options){
var option = {};
var static = {
base: 'treemenu',
opened: 'treemenu-opened',
after: 'treemenu-after',
button: 'treemenu-button',
delay: 500,
};
var config = $.extend(option, options);
var inc = $(this);
var treeMenu = (function(){
return{
init: function(){
inc.parent().addClass(static.base)
.append('<div class="' + static.button + '"><span class="arrow"></span></div>');
this.clip($('.' + static.button));
},
clip: function(button){
button.bind('click', function(){
var t = $(this),
m = t.parent('.' + static.base);
if(m.hasClass(static.opened) && m.hasClass(static.after)){
var h = 0, st = null;
t.prev().children().each(function(n){
h = h + $(this).outerHeight(true);
});
t.prev().css({'height': h});
m.removeClass(static.opened);
m.removeClass(static.after);
st = setTimeout(function(){
t.prev().css({'height': ''});
clearTimeout(st);
}, 1);
}else{
var h = 0, st = null;
m.addClass(static.opened);
t.prev().children().each(function(n){
h = h + $(this).outerHeight(true);
});
t.prev().css({'height': h});
st = setTimeout(function(){
if(m.hasClass(static.opened)){
m.addClass(static.after);
t.prev().css({'height': ''});
}
clearTimeout(st);
}, static.delay);
}
});
},
};
})();
treeMenu.init();
return(this);
};
})(jQuery);
次に、以下の前提から、これらをWordPress側に実装する。
- jQueryはWordPress標準のものを読んでいること。(まぁ別にユーザー定義のjQueryでもおk。)
- テーマ直下に「inc」ディレクトリを作っておいて、そこに上記のコードをそれぞれ保存しておくこと。(この辺はテーマのディレクトリのルールに応じて適宜どうぞ。)
- フィルターフックなどでウィジェットは弄らない。(特定のところ以外は弄っても問題ないけど。)
functions.php
function theme_enqueue_scripts() {
wp_enqueue_script( 'theme-js-treemenu', get_template_directory_uri() . '/inc/treemenu.js', array( 'jquery' ) );
wp_enqueue_style( 'theme-css-treemenu', get_template_directory_uri() . '/inc/treemenu.css' );
}
add_action( 'wp_enqueue_scripts', 'user_enqueue_scripts' );
function theme_read_scripts() {
$string = <<<EOT
<script type="text/javascript">
(function($){
$(document).ready(function(){
$('.widget ul.children').treeMenu();
});
})(jQuery);
</script>
<style type="text/css">
/* 展開ボタンのサイズ調整用 */
.treemenu > .treemenu-button{
padding-top: 10px;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
font-size: 15px;
line-height: 1.0em;
}
/* 展開ボタンのアロー */
.treemenu > .treemenu-button > .arrow::after{
content: "▼";
}
</style>
EOT;
echo $string;
}
add_action( 'wp_head', 'theme_read_scripts' );
スクリプトの始動のDOMを「.widget ul.children」と書く。
フィルターフックでウィジェットのコードをコマネチしなくてもいいように、このような始動を行うようにスクリプトを作っている。
(というか、WordPressデフォルトのウィジェットでは、親の<li>タグが中に子の<ul>を持っていたとしても、idやclassなどは明示されない。固定ページウィジェットのツリー、カテゴリーウィジェットで「階層を表示」は<ul>にはchildrenが付く。)
※フィルターフックでウィジェットをいじくるときは、<ul>のchildrenは残しといてね!
で、添え書きのように<style>タグを書いてあるが、これは開閉ボタンの見た目の調整用。
style.cssの中に入れてしまっても特に問題なし。
これで多分恐らく思うに記事表題とサンプルのような動作を実装できるはず。
今回のところは以上。
・・・で、書いた後でなんだけど。
どう考えても、今更感溢れてる件。
ウィジェットに動作を入れるとは言えツリーメニューとか何番煎じなんだよ。
なんかイマイチ締まらないけど・・・まぁいっか!(某地獄兄弟との決闘を忘れた天の人風)
