JavaScriptライブラリのGrid.jsを使って簡単な表を作る方法のメモです。
※Grid.js v.5.1.0を使用
サンプルのコードは、こちらの記事を書くときに作った5つの表です。
完成したコードはこちら: https://codepen.io/kaz_hashimoto/pen/WNJvOej
まずはGrid.jsを使うためのHTMLファイルの記述。
<link rel='stylesheet' href='https://unpkg.com/gridjs/dist/theme/mermaid.min.css'>
<script src='https://unpkg.com/gridjs/dist/gridjs.umd.js'></script>
表を埋め込む先のdivを用意します。
<div id="table1" class="table"></div>
<div id="table2" class="table"></div>
<div id="table3" class="table"></div>
<div id="table4" class="table"></div>
<div id="table5" class="table"></div>
表のスタイリングに関して、Grid.jsのデフォルト設定から変更したい部分のみCSSファイルに記述します。Grid.jsが定義するclass名には接頭辞gridjs-
が付いています1。
.gridjs-td {
text-align: right;
white-space: nowrap;
}
.gridjs-td:first-child,
#table3 .gridjs-td:nth-child(-n+2) {
text-align: left;
}
Grid.jsが生成した表の<th>
要素には、CSSプロパティのtext-overflow: ellipsis
が設定されているのですが、Firefoxで表示した場合、見出しがセル幅に収まっているにもかかわらず、文字列右側に省略記号"..." が付いてしまいます。この現象はChromeやSafariでは発生しません。
そこで、回避策としてtext-overflow: initial
に設定し省略記号を表示させないようにしました。ブラウザー側で見出しをセル幅に収まるように調整するためこれで問題ありません。
th.gridjs-th .gridjs-th-content {
text-overflow: initial; /* for Firefox */
}
次にJavaScript。説明の流れをわかりやすくするため、本文のコードブロックはサンプル完成版のものとは異なる順序で載せています。
先に5つの表を生成する部分のコードから。表の生成はとても簡単で、new gridjs.Grid().render()
の引数に表の列とセルのデータを渡すだけでターゲットのdivに<table>
要素のツリー構造が埋め込まれます。
forループでnew gridjs.Grid().render()
を呼び出し、5つの表を書き出します。処理をループにまとめるため、各表の列とセルのデータはMapオブジェクトtables
に格納しておき(詳細は省略)、divのidをキーにデータを取り出せるようにしました。
for (const [id, t] of tables) {
new gridjs.Grid({
width: '100%',
columns: t.columns,
data: t.data
}).render(document.getElementById(id));
}
gridjs.Grid()
の引数に指定したwidth: '100%'
は、<table>
要素が含まれるコンテナーの幅になります。
※デフォルトが100%なので今回の場合省略可
セルのデータの定義
表"table1"のセルのデータを定義する配列です。配列の要素が表の1行分のデータです。表"table1"の左から6番目の列については計算式で値を算出するため、この配列の要素には定義しません。
let tab = tables.get('table1');
tab.data = [
['Chrome', 1024, 1200, 1024, 1],
['Firefox', 1024, 1024, 1024, 1],
['Safari', 2560, 1024, 1024, 1],
['Edge', 1024, 1200, 1024, 1]
];
列の定義
表"table1"の列を定義する配列です。
tab.columns = [
'Browser',
{id: 1, name: br('screen.width'), attributes: marker},
{id: 2, name: br('window.innerWidth'), attributes: marker},
{id: 3, name: br('visualViewport.width'), attributes: marker},
{id: 4, name: br('visualViewport.scale')},
{id: 5, name: br('visualViewport.width x scale'),
formatter: (_, row) => multiply(row.cells[3].data, row.cells[4].data)},
{id: 6, name: '', width: '100%'}
];
形式1: 配列の要素を文字列で指定した場合は、そのまま列見出しの文字列になります。(例: 'Browser'
)
形式2: 列見出しにHTML要素を含めたい場合は、配列の要素をオブジェクトにしてidとnameプロパティに分けて設定します。
{id: 4, name: br('visualViewport.scale')},
この例では、列見出しに<br>
タグを挿入するためにbr()
関数(後述)を呼び出して戻り値のHTML文字列をname
プロパティに設定しています。
id
は列を識別するための任意の文字列です。数値で指定しても文字列として扱われるようです。
形式3: 列の幅はwidthプロパティで指定します。
各表の右端の列は、コンテナーの幅に合わせて伸縮する空の列にしたいので、name
の値を空文字列にしてwidth
に100%
を設定します。これでセル幅が残りスペースに合わせて調整されます。
{id: 6, name: '', width: '100%'}
列見出しを文字列で配列要素に直接指定するのとid
とname
に分けて指定するのとの違いは、生成された<table>
要素の構造を見るとわかります。下図のdata-column-id
属性とdiv.gridjs-th-content
の内容に注目。
形式4: セルの値によってセルのスタイルを変えたいときは、attributesプロパティにハンドラの関数を設定します。
この例では、セルの背景を青色で塗りつぶすためにmarker()
関数(後述)を呼び出すように設定しています。
{id: 1, name: br('screen.width'), attributes: marker},
形式5: セルに数式を定義し、計算結果をセルの値にするには、formatterプロパティにハンドラの関数を設定します。
この例では、cells[3]
とcells[4]
のセルの値を乗算した結果をこのセルの値とするように設定しています。乗算を行う関数は後述のmultiply()
で定義してあります。なお、配列cells
では同じ行のセルのみ参照できます。
{id: 5, name: br('visualViewport.width x scale'),
formatter: (_, row) => multiply(row.cells[3].data, row.cells[4].data)},
セルの書式設定
attributes
プロパティやformatter
プロパティに指定したハンドラの関数です。
最初に関数br()
。呼ばれると列見出しに<br>
タグを挿入します。パラメーターcell
はセルの内容(文字列)です。戻り値はHTML文字列です。HTML文字列への変換はgridjs.htmlを呼び出して行います。
今回のサンプルの表では、列見出しに含まれる最初のピリオド"."の前に<br>
を挿入しています。
function br(cell) {
cell = cell.replace(/\./, '<br>.');
return gridjs.html(cell);
}
次に関数marker()
。呼ばれるとセルの値が1024より大きい場合にセルの背景色を設定します。戻り値はCSSのstyleを記述したオブジェクトです。
function marker(cell) {
let d = +cell;
if (d > 1024) {
return {
'style': {
'background': '#a5d8ff'
}
};
}
}
marker()
が呼ばれると<td>
要素のインラインstyleにbackground
プロパティが設定されます。
最後に関数multiply()
。パラメーターとして2つのセルの内容(文字列)を受け取り、それらを数値として乗算した結果の値を四捨五入して返します。
function multiply(c1, c2) {
if ((c1 == 'n/a') || (c2 == 'n/a')) {
return 'n/a';
}
let v = Number(c1) * Number(c2);
return Math.round(v);
}
今回のサンプルの表には一部のセルに文字列"n/a"を入れてあるので、それらがパラメーターで渡された場合は"n/a"を返します。
-
スタイルの設定はGrid.jsのAPIを通じてもある程度可能ですが、それらは要素のインラインstyleに設定されます。今回は一部のセルだけclassを使ってスタイルを変えられるようにしたいので、APIは使わずにCSSファイルに直接記述しました。 ↩