業務アプリ開発講座

外部CSVファイルを読み込んで一覧を生成する

ちょっとここで、スタッフ一覧から脱線して、一覧HTML生成をJavascriptを用いてプログラミングしてみます。動的に一覧を生成するわけです。静的HTMLのサンプルを作る際にいちいちすべての行やセルのタグを打ち込むのは面倒ですね。静的HTMLとは言え、少しでも楽をしたいものです。そこで、あらかじめ表示データをExcel等でCSVファイルを作っておき、それを読み込んで一覧タグを生成します。

データを外部ファイル化しておき、Javascriptで動的に一覧を生成する最大のメリットは、「変更が容易である」にあります。ですので、静的HTMLとはいえ、積極的に利用することをお勧めします。

CSVファイルを用意

まず、サンプルデータです。10件分です。このようなデータを例えば300件ほど作っておけば、ページネーションもできるでしょう。各データは前回紹介しました、データ生成サイト等を利用してExcel等にまとめると簡単に用意することができます。

ID (スタッフカード),氏名 (編集),メールアドレス,スタッフ,管理,有効,Pwd登録,入社日,退社日,スタッフカード画像
2458888137476,横溝 陽菜乃,otoha8924@axgmdhlga.ko,0,0,1,1,2012-04-01,,2458888137476.png
1421796793525,芦田 美佳,toshiyuki7646@rwur.qc.yc,0,1,1,1,2012-04-02,,2458888137476.png
8700658187221,永野 哲朗,hanako631@ebnuk.edop.ktm,0,1,1,0,2012-04-03,,2458888137476.png
9742872250359,豊島 栞,ifgtoves-ckouji62485@gviqtgv.er,0,2,1,1,2012-04-04,,2458888137476.png
4232330128357,西谷 克子,toshiko3712@aiqib.ob.nz,1,2,1,1,2012-04-05,,2458888137476.png
7465834321761,成瀬 美沙,kanon2714@tcmcpu.tz,1,2,1,1,2012-04-06,,2458888137476.png
1243437341898,岩城 啓之,yasuyuki12182@uurbcwfqq.rxj.cwh,1,2,1,0,2012-04-07,2015-10-30,2458888137476.png
8827720663855,深谷 喜晴,eiji_fujioka@bfjnfhysqf.gw,1,2,0,0,2012-04-08,2015-10-31,2458888137476.png
8854866550457,加藤 力男,amna5019@wpddkpovln.augf.ai,1,2,0,1,2012-04-09,2015-11-01,2458888137476.png
3496325764842,大高 玲,oishii@brvlketga.ets,1,2,0,1,2012-04-10,2015-11-02,2458888137476.png

これをJavascriptで分解しつつTableタグに変換して、一覧を生成します。
ページヘッダーのところで作成した方法で、CSVファイルを取り込みます。
CSVファイルはassets/template/staff-list.csvとして作成しておいて下さい。

このようなデータは必ずしもCSVファイルでなくても構いません。例えば、jsonファイルで用意できればJavascriptでとても扱いやすくなります。しかし、CSVの作成より手間がかかりますので、ここではCSVを用いた生成方法を示します。

読み込むJavascriptファイルを整理

まず、読み込む.jsファイルを整理します。下記のように書き換えます。

<script src="../assets/js/jquery-2.1.4.js" type="text/javascript" charset="utf-8"></script>
<script src="../assets/js/bootstrap.js" type="text/javascript" charset="utf-8"></script>
<script src="../assets/js/bookmin.js" type="text/javascript" charset="utf-8"></script>
<script src="../assets/template/template.js"></script>
<script src="../assets/template/config.js"></script>

bookmin.jsconfig.jsの読み込みを追加しています。jsファイル自体も追加作成しておきます。

bookmin.js

Bookmin全体で使用する関数をまとめたものにします。ここでは、HTMLの雛形を指定の文字で変換する関数を追加します。

config
設定情報やHTMLの雛形などを記述します

CSVファイルの読み込み

さて、まずCSVファイルを読み込むところから作成しましょう。下記ソースをstaff-list.php
<script src="../assets/template/config.js"></script>の直下に書き足します。

<script type="text/javascript">
$(function(){
	bindGrid();
});
function bindGrid(){
	return $.ajax({
		async:false,
		url:"../assets/template/staff-list.csv",
		dataType:"text"
	});
}
bindGrid().done(function(csv) {
	alert(csv);
}).fail(function(result) {
	alert(result.resposeText);
});
</script>
1行目
javascriptのブロックであると宣言します。この中に記述されたものがjavascriptとして解釈実行されます。
2行目

$(function(){});は、DOMがロードされて操作・解析が可能になったタイミングで関数を実行するという意味でJQueryの機能です、このブロックの中で様々な設定処理を記述します。ここでは、bindGrid()を呼び出しています。({})の記述漏れに注意しましょう。カッコが複雑に見えるかもしれませんが、下記を縮めて記述しているだけです。

$(
	function(){
		bindGrid();
	}
);
5行目 bindGrid()

3行目で呼び出されているbindGrid()本体です。ここではajaxを使ってstaff-list.csvを読み込んでいます。ここで注意したいのがasync:falseです。これは非同期通知を無効にする、つまり同期通信とするという意味です。あとで追記する氏名項目にクリックイベントをを正しく動作させるためにあえて同期通信としています。非同期に関してはJavascriptの項で詳しく解説します。

9行目 dataType

dataTypeの値をtextとしています。JQueryのdataTypeにcsvは用意されていません。csvと言っても単に文字列の羅列であるとも言えますので、読み込んだデータを文字列として扱います。

12行目 .done()

bindGridが正しく処理結果を返したら実行するという意味です。英語のリファレンスを直訳すると「状態が解決(resolved)したら実行する」となってます。ここではCSVファイルが読み込めたかを確かめるだけにし、読み込んだCSVファイルの中身をアラートで表示しています。
bindGrid()関数が返した値は、この行のfunctionの引数csvに格納されます。

14行目 .fail()

bindGridが正しく処理結果を返さなかったら実行するという意味です。英語のリファレンスを直訳すると「状態が拒否(rejected)だったら実行する」となってます。functionに引数にエラー情報がオブジェクト形式で格納されます。result.responseTextとはエラーオブジェクトを文字列に変換するという意味です。

一覧生成のためのHTML雛形と表示文字列データの生成

続いて用意するのはconfig.jsです。この中に、HTMLの雛形とコードから文字列へ変換するためのデータを記述します。

var gridTemplate = {
	staff : {
		rowHead	: '<tr>\
	<th class="col-xs-2">{0}</th>\
	<th class="col-xs-2">\
		<a href="master/staff-list.html">{1}<i class="fa fa-sort fa-pull-right"></i></a>\
	</th>\
	<th class="col-xs-3">{2}</th>\
	<th class="col-xs-1">\
		<a href="master/staff-list.html">{3}<i class="fa fa-sort fa-pull-right"></i></a>\
	</th>\
	<th class="col-xs-1">\
		<a href="master/staff-list.html">{4}<i class="fa fa-sort fa-pull-right"></i></a>\
	</th>\
	<th class="col-xs-1">\
		<a href="master/staff-list.html">{5}<i class="fa fa-sort fa-pull-right"></i></a>\
	</th>\
	<th class="col-xs-1">\
		<a href="master/staff-list.html">{6}<i class="fa fa-sort fa-pull-right"></i></a>\
	</th>\
	<th class="col-xs-1">作業履歴</th>\
</tr>',
		rowBody	: '<tr>\
	<td employDate="{9}" leavingDate="{10}">\
		<a href="../assets/images/staff-card/{11}" target="blank">{0}</a>\
	</td>\
	<td><a href="javascript:void()" class="staff-name" data="{0}">{1}</a></td>\
	<td>{2}</td>\
	<td>{3}</td>\
	<td>{4}</td>\
	<td data="{5}"><i class="fa {6}" /></td>\
	<td data="{7}"><i class="fa {8}" /></td>\
	<td><a href="master/staff-work-log.html?StaffId={0}">作業履歴</a></td>\
</tr>'
	}
}
var viewText = {
	staffType		: ['社員', 'アルバイト'],
	managementType	: ['管理者', '管理補佐', 'レジ']
}
var iconCss = {
	valid : ['fa-remove', 'fa-circle-o'],
	check : ['', 'fa-check']
}

JSON形式で書かれています。JSONは階層化してかけますので、データの関係を表すことができます。
上記で言えば、gridTemplate.staff.rowHeadは「一覧雛形内のスタッフ内のヘッダー行」という意味になり、その値が取得できます。取得したい値に名前を適切に表現できるところがJSONの利点でしょう。

中身の解説です。

gridTemplate

var で宣言されていますので、これは変数です。そして値がJSONオブジェクトということになります。
一覧のHTML雛形を格納しています。

gridTemplate.staff

スタッフ一覧の雛形を格納しています。このように中分類とてstaffを宣言することで、この子供のノードがstaffに関連する何かであると明示できるわけです。

gridTemplate.staff.rowHead
スタッフ一覧の内、ヘッダー行のHTML雛形です。
gridTemplate.staff.rowBody
スタッフ一覧の内、ボディ1行分のHTML雛形です。

JSONの注意点

  • コメントを記述できません。
  • 値を複数行で記述できません。

    例えば、gridTemplate.staff.rowHeadは複数行を値としているように見えます。ところがよく見ると、各行末に\が付加されています。これは改行をエスケープするという意味で、改行コードを無効として、値全体を1行としているのです。このように改行コードをエスケープすれば複数行で書くことができます。

config.jsの概要を解説しました。

続いて値の解説です。

rowHeadrowBodyよく見ると{数字}の箇所が複数見つかります。
ここに動的に値を入れ込むわけです。同じ番号の箇所には同じ値で変換されます。変化しない箇所はHTMLが直に書かれています。この雛形を編集すると最終的に生成される一覧全体が変化しますので、後で列の順番を変えるなどの変更することがとても楽にできるようになります。列の順番を変更するくらいならこの雛形上で列の順番を変えるだけで済みます。

viewText

表示文字列変換データです。値が[]で囲まれています。これは値が配列であることを示しています。配列にはインデックス番号(添字)が付いています。つまり配列[番号]で対応する値が取得できます。
この例では、viewText.staffType[0]とすると「社員」が取得されます。
そして、このインデックス番号がデータベースに格納される値になります。ですのでデータベースの値と関連づけられるようにこの配列データも整える必要があります。

iconCss

有効、Pwd登録で使用する、WebFont用のCSS名データです。viewTextと同じように作られてます。

さて、これで、データは揃いました。ここで、Javascriptの汎用性のある関数を一つ作っておきたいと思います。bookmin.jsに下記を追記します。

String.format = function() {
	var s = arguments[0];
	for (var i = 0; i < arguments.length - 1; i++) {
		var reg = new RegExp("\\{" + i + "\\}", "gm");
		s = s.replace(reg, arguments[i + 1]);
	}
	return s;
}

String.format()という関数を作っています。 
この関数は第1引数に雛形に対し、第2以降の引数で{数字}部分を変換します。中身を見ていきましょう。

使いかた:

var temp	= "姓は{0}、名は{1}である。";
var replaced	= String.format(tmp, "猿飛", "佐助");

変数replacedには「姓は猿飛、名は佐助である。」が格納されます。

argument

いきなり飛び出してきてびっくりしますが、Javascriptに初めから備わっている機能で、引数の配列オブジェクトになります。Javascriptはfunctionに引数名を明示的に書く必要がないのです。引数の数をチェックすることもしません。全てargumentオブジェクトに引数として渡された分だけ格納されます。
2行目のvar s = argument[0]は最初の引数を取得しています。
3行目以降は2つ目以降の引数が、存在する分だけ文字変換をし、変換された文字列を戻り値として返しています。

RegExp

正規表現オブジェクトです。文字列を正規表現パターンを生成しています。第1引数にパターン、第2引数にflagを指定しています。

ちなみに、ここで指定しているflagの意味は、下記のとおりです。

g : 同じパターンが複数回出現した場合、すべてを対象とする
m : 複数行に対し対象とする

そして、次の5行目で、この正規表現パターンを以って第1引数の雛形文字列と第2以降の引数を変換しています。

これで、事前準備が整いました。
staff-list.phpに戻ります。