jQuery DataTables プラグインの開発手記
DataTables は、HTML のテーブルに、ページ切り替え、ページ当たりの件数設定、ソート、フィルタなどの機能を簡単に追加できるライブラリです。セクション テーブル(後述)と機能が似ていますが、個人的に DataTables の方がテーブル全体を眺めやすい気がしています。
最近の私は、TeamPage でこの DataTables を利用できるようにするためのプラグイン開発に取り組んでいます。いろいろなサイトに掲載されている DataTables についての資料を参考にしたおかげで、ずいぶんと作業が進み、形になってきました。
そこで、今回は、DataTables の基本や TeamPage に組み込む際の工夫などを紹介いたします。私にとっては、開発中に学んだことを備忘録としてまとめたに過ぎませんが、これから DataTables を使ってみようと考えている方や、TeamPage のプラグイン開発に興味のある方の参考になれば嬉しく思います。
開発の経緯
TeamPage には、セクションに集められた記事をテーブル(スプレッドシート)として表示する、セクション テーブルという機能が備わっています。テーブルの列として表示する内容のカスタマイズや、ソート、絞り込みもできます。
下図は、日報プラグインのセクションテーブルの例です。
セクションテーブルの最も便利な機能は、各行をその場で広げて、記事全体や段落ごとにタグ付け、コメント、タスクやスケジュール登録など、次のアクションを起こせることです。アクションをどんどん繋げていけるのは TeamPage の素晴らしいところなので、セクションテーブルは、正に「TeamPage らしいテーブル」と言えるでしょう。
さて、セクションテーブルがまだ TeamPage に搭載されていない頃、あるプロジェクトでソート可能なテーブルを実装する必要があり、私はそのプロジェクト用のプラグインに tablesorter を組み込んだことがあります。その後、この DataTables を見つけ、こちらの方が便利そうだったので、以降、商談メモ プラグインなど、いくつかのプラグインに組み込んで使用してきました。
下図は、商談メモで使用した DataTables の例です。
これまでは、DataTables を使用するプラグインを作る度に DataTables を使うためのコードを書いていたのですが、プラグインの数が増えるに従って何度もコードを書くのが面倒になってきました。新しいプラグインに DataTables を組み込むには、既存のプラグインから必要な部分をコピペして少し編集するだけなので、開発時の手間はそれほどかからないといえばかからないのですが、今後、プラグインの数が増えるにつれてメンテナンスが大変になるのは明らかです。
そこで、すべてのプラグインや TeamPage 本体から利用できる、共有ライブラリとして設計し直すことにしました。これなら、何か問題が発生したとき、共有ライブラリを修正するだけで、DataTables を使用するすべてのプラグインや本体機能に修正を反映できます。
DataTables の使い方
DataTables の使い方や組み込み方については、さまざまなサイトで解説されているので、今更このブログで紹介する必要もないかもしれません。しかし、DataTables は、バージョン 1.10 になってオプション等の書き方が変わりました。Web を検索するとバージョン 1.9 以前向けの内容が数多くヒットし、混乱します。ここでは、バージョン 1.9 と 1.10 との違いなどを中心に紹介します。
基本的な書き方
HTML の <head>...</head>
内で jQuery と DataTables のライブラリを読み込みます。ここでは、手軽な CDN を利用していますが、このページからダウンロードもできます。jQuery のバージョンは 1.7 以上ならOKです。
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" href="//cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css">
</head>
HTML の <table>
を使ってテーブルを作成します。
<table id="datatable-example">
<thead>
<tr><th>記事 ID</th><th>タイトル</th><th>投稿日</th><th>投稿者</th></tr>
</thead>
<tbody>
<tr><td>Exec100</td><td>役員会議事録</td><td>2016/03/16 17:30</td><td>山田 太郎</td></tr>
<tr><td>Sales265</td><td>営業資料作成</td><td>2016/03/20 12:45</td><td>畑林 花子</td></tr>
<tr><td>Quality74</td><td>不適合の解決</td><td>2016/03/22 16:15</td><td>武藤 進</td></tr>
</tbody>
</table>
そのテーブルの ID を指定して .DataTable() を実行します。
$(document).ready( function () {
$('#datatable-example').DataTable({
// Options
});
});
バージョン 1.9 と 1.10 での書き方の違いについては、公式サイトのこのページで詳しく解説されています。細かなところに違いがあるので注意が必要です。
例えば、テーブルに DataTables を適用する書き方は、バージョン 1.9 までは .dataTable()
でしたが、 1.10 では .DataTable()
に変更されています。(初めのアルファベットの「D」の文字が大文字になった)
オプションの書き方
オプションの書き方(オプションの名前)も変更されています。
例えば、あるプラグインでは、バージョン 1.9 の書き方に基いて次のようなオプション指定をしていたのですが、
"bFilter": true,
"bInfo": true,
"aoColumns": [
"columnDefs": [
{
"bSortable": false, "aTargets": [ 17 ]
}
]
],
"oLanguage": {
"sSearch": "フィルター: ",
"sLengthMenu": "表示件数: _MENU_",
"oPaginate": {
"sNext": "次のページ",
"sPrevious": "前のページ"
},
"sInfo": "全 _TOTAL_ 件中の _START_ から _END_ を表示"
}
…バージョン 1.10 の書き方に基いて、次のように変更する必要があります※。
"searching": true,
"info": true,
"columns": [
"columnDefs": [
{
"orderable": false, "targets": [ 17 ]
}
]
],
"language": {
"search": "フィルター: ",
"lengthMenu": "表示件数: _MENU_",
"paginate": {
"next": "次のページ",
"previous": "前のページ"
},
"info": "全 _TOTAL_ 件中の _START_ から _END_ を表示"
}
※ bFilter
や oLanguage
のオプションは、バージョン 1.9 の書き方でも動作しました。ただ、すべてのオプションが古い書き方で動作するかどうかは未確認です。
TeamPage での DataTables
Proteus スキンと Ajax ロード
TeamPage の標準スキンである「Proteus (プロテウス)」は、ページを一度だけ読み込み、ユーザーによる画面操作が行われたときに、コンテンツ(内容)だけを AJAX で読み込む仕組みになっています。このため、<head>
タグ内に書かれた $(document).ready
は、コンテンツが読み込まれてない段階で一度だけ実行され、<body>
タグ内に書いた JavaScript は、Ajax によってスクリプトそのものが後から読み込まれ、読み込み時には実行されません。
これは、すなわち、(1) ページの読み込み完了時には、DataTables を適用する HTML のテーブルはまだ読み込まれてない、(2) $(document).ready
で DataTable()
を実行しても適用対象のテーブルが(まだ)存在しない、(3) Ajax によって後から DataTable()
を読み込んでも実行されない、ということを意味します。
端的に言うと、「Proteus スキンで DataTables を使うのには工夫が必要」ということです。
工夫: iframe を使う
そこで、テーブルや DataTable()
を Proteus スキンではない別のページに作成し、Proteus スキンのコンテンツとして<iframe>
タグを使って読み込むことにします。
こんなイメージです。
親ウィンドウに <iframe>
による「窓」を開け、テーブルを作成した子ウィンドウを「窓」と同じ大きさにして、窓の向こう側に表示します。子ウィンドウは、昔ながらの HTML ページで、Ajax で後からコンテンツが読み込まれるページではありません。親ウィンドウの <iframe>
からリクエストされて生成されるので、子ウィンドウ内の DataTable() は子ウィンドウが生成される際に子ウィンドウ内で実行されます。
工夫: 高さの自動調整
テーブル右上の「フィルター」欄(デフォルトでは「Search」と表示されています)にテキストを入力すると、入力されたテキストを含む行だけが絞り込み表示されます。軽快に動作するので、目的の行を見つけるのにとても便利です。
このとき、表示された行に合わせてテーブルの高さが変化するわけですが、親ウィンドウの「窓」の高さは固定されているので、行数が少なくなった分だけ「窓」の中に空白が生じてしまいます。
この問題を回避するため、「子ウィンドウのテーブルの高さが変化したら、親ウィンドウの窓の高さを変化させる」という工夫を施すことにしました。具体的には、次のコードを子ウィンドウに挿入しました。
function resizeParentDIV() {
setTimeout(function(){
var bodyHeight = $('#datatable-${id}').height();
// Set the height of the DIV container in the parent document.
$('#datatables-iframe-container-${id}',parent.document).css({height:(bodyHeight+72)});
// Set the height of the IFRAME in the parent document.
$('#datatables-iframe-${id}',parent.document).css({height:(bodyHeight+72)});
},0);
};
$(document).ready(function(){
resizeParentDIV();
$(document).on('DOMSubtreeModified propertychange', "#datatable-${id}", function(){
resizeParentDIV();
});
});
コード中の ${id} は、「id」という名前の変数の値の参照を意味します。(SDL では、${変数名}
と書いて値を読み出せます)
まず、resizeParentDIV
という関数を定義しました。この関数は、テーブルの高さを ID: datatable-${id}
を元に調べ、マージンの高さを追加して、親ウィンドウの <iframe>
とそれを囲む <div>
の高さに反映させます。
そして、テーブルの内容が変化したことを DOMSubtreeModified propertychange
イベントとして感知し、resizeParentDIV
関数を実行します。
これにより、テーブルの高さの変化に親ウィンドウの <iframe>
の高さが追従するようになり、空白が生じないようにできました。
SDL 関数としての DataTables
この「子ウィンドウを呼び出すコード」は、TeamPage の開発言語である SDL で定義されています。この部分を関数とすることで、テーブルに表示する記事の種類、列の種類、行数など、表に表示する内容や細かな設定をパラメーターとして渡して簡単に指定できるようにしました。
下図は、動作テストのための画面で、上部にパラメーターの種類と対応する値、下部に実行結果(親ウィンドウの <iframe>
内に表示された、子ウィンドウのテーブル)が表示されています。
TeamPage 開発者は、DataTables のプラグインをお使いの TeamPage に組み込むだけで、この DataTables 用の SDL 関数を利用できるようになり、さまざまな記事を DataTables を使ってスプレッドシート表示できるようになります。例えば、タスクの一覧や問い合わせの一覧などを表示すれば、特定の条件のもの(例えば、「山田さんが担当するもの」など)を素早く見つけることができます。
また、開発者だけでなく、一般ユーザーがより簡単に利用できるように、将来的にはウィジェットや CSV ダウンロード機能も追加する予定です。ご期待ください。(2016/06/09 追記: ウィジェットとして利用できるようにした DataTables プラグイン をリリースしました。)
関連記事
チーム パフォーマンス向上を目的としたタスク トラッキング ... 仕事を効率化してチームワークを高めるための、タスクやプロジェクト管理機能の紹介です。
チームのコラボレーションを促進するタスクトラッキング ... 自分やチームメンバーのアクション プラン、状況、仕事量、各メンバーの進捗、チーム全体の進捗を簡単に確認することで、共通のゴールに向けた各種活動をスムーズに進められます。
プラグインやアプリの紹介 ... TeamPageで利用できるいろいろなプラグイン/アプリの一部を紹介します。
ソーシャルグラフ、インタレストグラフ、そしてワークグラフ ... 投稿内容やユーザー情報などの「仕事に必要な情報」が、どのように結びつき、活用できるのかを紹介します。