WordPressのウィジェットで表示される「カテゴリー」ですが、使用しているテーマ(スキン)によっては、親カテゴリーと子カテゴリーの区別がつきにくく、階層が深くなると非常に見づらくなってしまうことがあります。
「それならいっそのこと、親階層をクリックしたら子階層が開くアコーディオン形式にすればいいのでは?」と思い立ち、jQueryを使ってカテゴリーメニューの開閉を実装しました。
今回は、そのカスタマイズ手順とコードを備忘録として残しておきます。
(※WordPressのコアファイルを編集する箇所があるため、アップデート時には注意が必要です)
1. カテゴリー出力テンプレートの編集
まずは、カテゴリーのリストを出力しているコアファイルを編集し、アコーディオン化しやすいHTML構造(親カテゴリーからはAタグを外すなど)に変更します。
編集ファイル:wp-includes/category-template.php
※ start_el 関数の内部(828行目付近)を修正します。
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
extract($args);
$cat_name = esc_attr( $category->name );
$cat_name = apply_filters( 'list_cats', $cat_name, $category );
// 変更箇所:親カテゴリーの場合はAリンクを付けず、<p><span>タグで囲む
$show_count_flg = true;
if($has_children == 1){
$link .= "<p><span>$cat_name";
if ( !empty($show_count) && $show_count_flg )
$link .= ' (' . intval($category->count) . ')';
$show_count_flg = false;
$link .= "</span></p>";
} else {
// 子カテゴリー(最下層)の場合は通常のAリンクを出力
$link .= '<a href="' . esc_url( get_term_link($category) ) . '" ';
if ( $use_desc_for_title == 0 || empty($category->description) )
$link .= 'title="' . esc_attr( sprintf(__( 'View all posts filed under %s' ), $cat_name) ) . '"';
else
$link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"';
$link .= '>';
$link .= $cat_name ;
if ( !empty($show_count) && $show_count_flg )
$link .= ' (' . intval($category->count) . ')';
$show_count_flg = false;
$link .= '</a>';
}
// --- 中略(フィードアイコンの出力処理など) ---
// 投稿数の表示位置変更に伴うフラグ制御
if ( !empty($show_count) && $show_count_flg )
$link .= ' (' . intval($category->count) . ')';
if ( 'list' == $args['style'] ) {
$output .= "\t<li";
$class = 'cat-item cat-item-' . $category->term_id;
if ( !empty($current_category) ) {
$_current_category = get_term( $current_category, $category->taxonomy );
if ( $category->term_id == $current_category )
$class .= ' current-cat';
elseif ( $category->term_id == $_current_category->parent )
$class .= ' current-cat-parent';
}
$output .= ' class="' . $class . '"';
$output .= ">$link\n";
} else {
$output .= "\t$link<br />\n";
}
}2. ウィジェット出力部分のクラス・ID付与
次に、カテゴリーリストの最上層となる <ul> タグに、jQueryで制御するためのクラスとIDを付与します。 これが見つかるまでに非常に苦労しましたが、なんとウィジェットのコアファイルに直書きされていました。
編集ファイル:wp-includes/default-widgets.php ※ 478行目付近を修正します。
} else {
?>
<ul class="accordion" id="accordion">
<?php
$cat_args['title_li'] = '';
wp_list_categories(apply_filters('widget_categories_args', $cat_args));
?>
</ul>3. jQueryスクリプトの追加
開閉のギミックを実装するためのJavaScriptを記述します。 使用しているテーマの header.php の <head> 内、または外部JSファイルに追記してください(※要jQuery本体)。
<script type="text/javascript">
$(function(){
// accordionクラス内の pタグがクリックされた時の処理
$(".accordion p").click(function(){
// 次の ul要素(子カテゴリーリスト)をスライドで開閉
$(this).next("ul").slideToggle();
// 開閉状態に合わせて矢印アイコン等の制御用クラスを付与
$(this).children("span").toggleClass("open");
});
});
</script>4. CSSでのデザイン調整
最後に、見た目を整えます。テーマの style.css 等に追記してください。 (各サイトのデザインに合わせて適宜変更してください)
/* アコーディオン全体の設定 */
ul.accordion { padding: 0px; border-bottom: 0px; }
ul.accordion#accordion li { padding: 0px; border-bottom: 0px; }
ul.accordion#accordion p { margin: 0px; cursor: pointer; }
ul.accordion a {
display: block; padding: 10px;
background-position: 95% center; background-repeat: no-repeat;
text-decoration: none; color: #FFF;
}
ul.accordion span {
display: block; padding: 10px;
background-position: 95% center; background-repeat: no-repeat;
color: #FFF; cursor: pointer;
}
/* 初期状態:折り畳み部分(子階層)を隠す */
ul.accordion ul { display: none; }
/* 背景グラデーション設定 */
ul.accordion > li, ul.accordion > li > p {
background: -moz-linear-gradient(top, #666, #000);
background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#000));
}
ul.accordion > li > ul > li, ul.accordion > li > ul > li > p {
background: #888; border-bottom: 1px solid #444;
}
ul.accordion > li > ul > li > ul > li {
background: #FFF; border-bottom: 1px dotted #888;
}
ul.accordion > li > ul > li > ul > li:last-child { border: none; }
/* 開閉アイコンの設定(別途画像を用意してください) */
ul.accordion > li > p span { background-image: url(img/a_close.png); }
ul.accordion > li > p span.open { background-image: url(img/a_open.png); }
ul.accordion > li > a { background-image: url(img/a_link.png); }
ul.accordion > li > ul > li > p span { background-image: url(img/b_close.png); }
ul.accordion > li > ul > li > p span.open { background-image: url(img/b_open.png); }
ul.accordion > li > ul > li > a { background-image: url(img/b_link.png); }
ul.accordion > li > ul > li > ul > li a { background-image: url(img/c_link.png); color: #333; }まとめ
実際にやってみて一番苦労したのは、「親カテゴリーの判定がどこで行われているのか」と「最上層の <ul> がどこに記述されているのか」を探すことでした。 print_r で値を確認したり、ファイル内を検索しまくって、まさかウィジェットのコアファイル(default-widgets.php)に直書きされているとは……この調査だけで半日潰れました。
同じようにカテゴリーのアコーディオン化で悩んでいる方の参考になれば幸いです。
通常のカテゴリーでもよかったんですが、
今のスキンだと子カテゴリーも親カテゴリーと同様に見えるためものすごく見づらい。
修正するならいっそのこと親階層を開閉できるようにしたらいいんじゃない?
という考えでカテゴリーのアコーディオン化をすることにしました。
jqueryを使ってメニューの開閉します。
サンプルはこのブログのカテゴリーを参考にしてください。
方法はスマートフォンサイト制作ブログさんのを参考にさせていただきました。ありがとうございます。
①wp-includes/category-template.php
- 親カテゴリーはAリンクをつけないように修正
- レイアウトを考慮し、投稿数の表示位置を変更。
828行目付近(//20120901 渉猟 ****部分内が変更箇所)
function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
extract($args);
$cat_name = esc_attr( $category->name );
$cat_name = apply_filters( 'list_cats', $cat_name, $category );
//20120901 渉猟 add start
$show_count_flg = true;
if($has_children == 1){
$link .= "<p><span>$cat_name";
if ( !empty($show_count) && $show_count_flg )
$link .= ' (' . intval($category->count) . ')';
$show_count_flg = false;
$link .= "</span></p>";
}else{
//20120901 渉猟 add end
$link .= '<a href="' . esc_url( get_term_link($category) ) . '" ';
if ( $use_desc_for_title == 0 || empty($category->description) )
$link .= 'title="' . esc_attr( sprintf(__( 'View all posts filed under %s' ), $cat_name) ) . '"';
else
$link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"';
$link .= '>';
//20120901 渉猟 modify start
$link .= $cat_name ;
if ( !empty($show_count) && $show_count_flg )
$link .= ' (' . intval($category->count) . ')';
$show_count_flg = false;
$link .= $cat_name . '</a>';
//20120901 渉猟 modify end
//20120901 渉猟 add start
}
//20120901 渉猟 add end
if ( !empty($feed_image) || !empty($feed) ) {
$link .= ' ';
if ( empty($feed_image) )
$link .= '(';
$link .= '<a href="' . esc_url( get_term_feed_link( $category->term_id, $category->taxonomy, $feed_type ) ) . '"';
if ( empty($feed) ) {
$alt = ' alt="' . sprintf(__( 'Feed for all posts filed under %s' ), $cat_name ) . '"';
} else {
$title = ' title="' . $feed . '"';
$alt = ' alt="' . $feed . '"';
$name = $feed;
$link .= $title;
}
$link .= '>';
if ( empty($feed_image) )
$link .= $name;
else
$link .= "<img src='$feed_image'$alt$title" . ' />';
$link .= '</a>';
if ( empty($feed_image) )
$link .= ')';
}
//20120901 渉猟 modify start
//if ( !empty($show_count) )
if ( !empty($show_count) && $show_count_flg )
$link .= ' (' . intval($category->count) . ')';
//20120901 渉猟 modify start
if ( 'list' == $args['style'] ) {
$output .= "t<li";
$class = 'cat-item cat-item-' . $category->term_id;
if ( !empty($current_category) ) {
$_current_category = get_term( $current_category, $category->taxonomy );
if ( $category->term_id == $current_category )
$class .= ' current-cat';
elseif ( $category->term_id == $_current_category->parent )
$class .= ' current-cat-parent';
}
$output .= ' class="' . $class . '"';
$output .= ">$linkn";
} else {
$output .= "t$link<br />n";
}
}
②wp-includes/default-widgets.php
- 最上階層の<ul>がここに記載されている。
- <ul>だと誤作動の可能性が高いため、id及びclassを付与
478行目付近(//20120901 渉猟 ****部分内が変更箇所)
<php
} else {
//20120901 渉猟 modify
?>
<?php //<ul> ?>
<ul class="accordion" id="accordion">
<?php
//20120901 渉猟 modify
$cat_args['title_li'] = '';
wp_list_categories(apply_filters('widget_categories_args', $cat_args));
?>
③JavaScriptの追加(表示するところならどこでも良い?)
私はスキンのheader.phpに記載しました。
<script type="text/javascript">
//20120901 渉猟 add start
$(function(){
$(".accordion p").click(function(){
$(this).next("ul").slideToggle();
$(this).children("span").toggleClass("open");
});
})
//20110901 渉猟 add end
</script>
④CSSの追加(表示するところならどこでも良い?)
これは各サイトによって変わってくると思うので適宜変更願います。
/20120901 渉猟 add start/
ul.accordion a {display:block; padding:10px; background-position:95% center; background-repeat:no-repeat; text-decoration:none; color:#FFF;}
ul.accordion {padding 0px; border-bottom:0px;}
ul.accordion#accordion li {padding:0px 0;; border-bottom:0px;}
ul.accordion#accordion p {margin:0px;}
ul.accordion span {display:block; padding:10px; background-position:95% center; background-repeat:no-repeat; color:#FFF;}
/* 折り畳み部分を隠す /
ul.accordion ul {display:none;}
/ 背景 /
ul.accordion > li {background: -moz-linear-gradient(top, #666, #000); background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#000));}
ul.accordion > li > p {background: -moz-linear-gradient(top, #666, #000); background: -webkit-gradient(linear, left top, left bottom, from(#666), to(#000));}
ul.accordion > li > ul > li {background:#888; border-bottom:1px solid #444;}
ul.accordion > li > ul > li > p {background:#888;}
ul.accordion > li > ul > li > ul > li {background:#FFF; border-bottom:1px dotted #888;}
ul.accordion > li > ul > li > ul > li:last-child {border:none;}
ul.accordion > li > p span {background-image:url(img/a_close.png);}
ul.accordion > li > p span.open {background-image:url(img/a_open.png);}
ul.accordion > li > a {background-image:url(img/a_link.png);}
ul.accordion > li > ul > li > p span {background-image:url(img/b_close.png);}
ul.accordion > li > ul > li > p span.open {background-image:url(img/b_open.png);}
ul.accordion > li > ul > li > a {background-image:url(img/b_link.png);}
ul.accordion > li > ul > li > ul > li a {background-image:url(img/c_link.png); color:#333;}
/20120901 渉猟 add end*/
実際にやってみて親カテゴリーの判断がどこにやっているのか、最上層の<ul>
がどこに記載しているのかでものすごく時間がかかりました。
(array_rで値確認したり、表示位置を探したりなど……)
まさか<ul>がウィジェットに記載されているとは思いませんでした……
これで半日つぶれるとは思いませんでした。
とりあえず参考になればと思います。