こんにちは。E-kan株式会社の岡田です。
先日、20行以上あるtableタグで組まれているお客様の社内用データベース管理ページの改修を行ったのですが、地味に苦労したので備忘録。
やりたいこと
- デフォルトは最初の2行を見出しとして表示させ、残りの行はアコーディオンで折りたたむ
- tableの下に「詳細を表示する」というテキストを置き、クリックするとアコーディオンが開き、「詳細を閉じる」という文言に変える
- アコーディオンを閉じたら見出し行の位置に戻る
- テーブルは複数あるので、個別にアコーディオンが開くようにする
<section class="accordion">
<table>
<thead>
<tr>
<th>タイトル1</th>
<td>本文1本文1</td>
</tr>
<tr>
<th>タイトル2</th>
<td>本文2本文2</td>
</tr>
</thead>
<tbody class="accordion_body">
<tr>
<th>タイトル3</th>
<td>本文3本文3</td>
</tr>
〜〜〜 略 〜〜〜
<tr>
<th>タイトル20</th>
<td>本文20本文20</td>
</tr>
</tbody>
</table>
<span class="more">詳細を表示する</span>
</section>
jQuery
$(function(){
//アコーディオン部分を非表示にしておく
$('.accordion_body').hide();
//.more をクリックしたら実行
$('.more').on('click',function(){
//クリックした要素の兄弟要素内の子要素(開閉させたい箇所)を変数に格納する
var acBody = $(this).siblings(".accordion").children(".accordion_body")
if(acBody.is(':hidden')){ //アコーディオンが非表示だったら実行する内容
acBody.show(); //アコーディオンを表示させる
$(this).addClass('active').text('詳細を非表示にする'); //テキストを変えてclassを付与
} else { //アコーディオンが表示されていたら実行する内容
acBody.hide(); //アコーディオンを非表示にする
$(this).removeClass('active').text('詳細を表示する'); //テキストを戻してclassを取る
var offset = $(this).parent().offset().top; //ページ上部から親要素の頭の位置までを変数に格納
$(window).scrollTop(offset); //スクロール位置を見出し行に戻す
}
});
});
こんな感じの、クリックした直下の要素を開閉させる単純なアコーディオンなら
<dl>
<dt class="more">タイトル</dt>
<dd class="accordion_body">本文</dd>
</dl>
nextとslideToggleを使ってサクッと実装出来るのですが、
$('.more').click(function(){
$(this).toggleClass('active');
$(this).next('.accordion_body').slideToggle();
});
今回は既存のtable要素の一部をアコーディオンとして開閉させたいという事と、開閉のトリガーになる要素が兄弟要素ということで地味に苦労しました。(siblingsメソッドを初めて知った。勉強になった。)
あと、最初はアコーディオンをslideDown・slideUpにしていたのですが何故かアニメーションにならず、調べたところtableタグではアニメーションをサポートしていないとのことでした。
まぁ、最近はtableを使うこともそんなに無いかと思いますが、アニメーションさせたいのなら最初からtableで組んじゃだめということですね。