jQueryのTablesorterを複数行のヘッダに対応させる方法
JavaScriptライブラリのjQueryには、テーブルをソートするためのTablesorterというプラグインがあります(デモ)。これを複数行にまたがるヘッダに対応させる方法を紹介します。
複数行のヘッダというのは、2つ以上のtr要素やrowspan/colspan属性付きのth要素を含むthead要素のことです。Tablesorterの紹介にはSupport for ROWSPAN and COLSPAN on TH elements
とありますが、自動的に対応してくれるわけではないようです(あるいは、将来的にサポート予定なのか)。
解決の糸口となったのはjQueryグループの「jquery tablesorter 2.0.1 with tr in thead」というスレッドです。他にも似た質問がいくつか見つかったので、同じようなことで躓いている人は多いようです。
tablesorterオブジェクトにはheaderListというそれっぽいプロパティがあるのですが、上手くいかなかったので今回の方法を採用しました。
前提となるXHTML
ここでは、次のような複数行(colspan, rowspan属性付き)のth要素を含むテーブルを例にします。
製品名 | 価格 | |
---|---|---|
新規 | アップグレード | |
製品A | 49800 | 26000 |
製品B | 39690 | 12390 |
- index.html(抜粋)
<table> <caption>製品価格一覧</caption> <thead> <tr> <th scope="col" rowspan="2">製品名</th> <th scope="col" colspan="2">価格</th> </tr> <tr> <th scope="col">新規</th> <th scope="col">アップグレード</th> </tr> </thead> <tbody> <tr> <th scope="row">製品A</th> <td>49800</td> <td>26000</td> </tr> <tr> <th scope="row">製品B</th> <td>39690</td> <td>12390</td> </tr> </tbody> </table>
単純にTablesorterを呼び出すだけでは、このようなテーブルは正しくソートできません。「製品名」・「新規」・「アップグレード」の各th要素をソートのトリガーにしようというのが今回の目的です。
必要なもの
この方法でTablesorterを複数行のヘッダに対応させるには、次のものが必要になります。
jQuery本体とTablesorterプラグインはもちろん必要です。Metadataプラグインは、属性値に埋め込んだメタデータ(JavaScriptのオブジェクトリテラルと同じ書式)をオブジェクトに変換してくれるプラグインです。ソートのトリガーとなるth要素を手動で指定するために使います。
Tablesorterプラグインの修正
まず、jquery.tablesorter.js内のbuildHeaders()メソッドを次のコードに入れ替えます。
- jquery.tablesorter.js buildHeaders()メソッド
function buildHeaders(table) { if (table.config.debug) { var time = new Date(); } var meta = ($.metadata) ? true : false, tableHeadersRows = []; for (var i = 0; i < table.tHead.rows.length; i++) { tableHeadersRows[i]=0; }; $tableHeaders = $("thead th",table); $tableHeaders.each(function(index) { var sortIndex; if ($.metadata && $(this).metadata().sortIndex) { sortIndex = $(this).metadata().sortIndex; } else { sortIndex = index; } this.count = 0; this.column = sortIndex; this.order = formatSortingOrder(table.config.sortInitialOrder); if (checkHeaderMetadata(this) || checkHeaderOptions(table,sortIndex)) this.sortDisabled = true; if (!this.sortDisabled) { $(this).addClass(table.config.cssHeader); } // add cell to headerList table.config.headerList[sortIndex] = this; }); if (table.config.debug) { benchmark("Built headers:", time); log($tableHeaders); } return $tableHeaders; };
これは、Metadataプラグインを使ったソートインデックスの指定に対応させるものです。
ソートインデックスの指定
Tablesorterを呼び出すためのJavaScriptファイルを作成します(ここではわかりやすいようにベタ書きにします)。
次に、各th要素に手動でソートインデックスを割り振ります。ソートインデックスは、ソートのトリガーとして使うth要素を指定するためのものです。XHTMLの任意の属性値に{ sortindex: 数字 }
という書式で埋め込みます。
今回は、ソートインデックスをclass属性として埋め込むことにします。また、直に埋め込むのはよくないので、jQueryを使って動的に埋め込むことにします。
sortindexにはth要素に対応するテーブルの列を指定します。例えば、XHTML上で3番目に出現するth要素をテーブルの2列目に関連付けるには、3番目のth要素に{ sortindex: 1 }
を指定します(インデックスは0から始まります)。ソートのトリガーとして使わないth要素には、余ったsortindexを指定しておきます。
- my.js
$(document).ready(function() { // 1番目のth要素: 1列目をソート $('table.data thead th:eq(0)').addClass('{ sortIndex: 0 }'); // 2番目のth要素: 4列目をソート // 使わないので余ったインデックスを割り振る $('table.data thead th:eq(1)').addClass('{ sortIndex: 3 }'); // 3番目のth要素: 2列目をソート $('table.data thead th:eq(2)').addClass('{ sortIndex: 1 }'); // 4番目のth要素: 3列目をソート $('table.data thead th:eq(3)').addClass('{ sortIndex: 2 }'); });
Tablesorterの呼び出し
続けて、Tablesorterを呼び出します。
このとき、ソートのトリガーとして使わないth要素(ソートインデックス)には、sorterプロパティにfalseをセットして無効化しておきます。
- my.js
$(document).ready(function() { // 1番目のth要素: 1列目をソート $('table.data thead th:eq(0)').addClass('{ sortIndex: 0 }'); // 2番目のth要素: 4列目をソート // 使わないので余ったインデックスを割り振る $('table.data thead th:eq(1)').addClass('{ sortIndex: 3 }'); // 3番目のth要素: 2列目をソート $('table.data thead th:eq(2)').addClass('{ sortIndex: 1 }'); // 4番目のth要素: 3列目をソート $('table.data thead th:eq(3)').addClass('{ sortIndex: 2 }'); $('table.data').tablesorter({ headers: { 3: { sorter: false } // 2番目のth要素: 4列目のソートを無効化 } }); });
JavaScriptファイルへのリンク
後は、XHTMLのhead要素内でJavaScriptファイルを読み込ませれば完成です。
- index.html(抜粋)
<script src="jquery.js" type="text/javascript"></script> <script src="jquery.metadata.js" type="text/javascript"></script> <script src="jquery.tablesorter.js" type="text/javascript"></script> <script src="my.js" type="text/javascript"></script>
これで、複雑な表組みの場合にもTablesorterが使えるようになりました。便利です 😀
コメント (2)
こちらですが、行方向に結合したテーブルだけではなく、列方向に結合したテーブルだったとしても有効でしょうか。
トラックバック (1)
[…] jQueryのTablesorterを複数行のヘッダに対応させる方法 関連記事 […]
おかげさまで、ソートができるようになりました。ありがとうございます。