[ページ遷移しないWebシステム] JavaScriptでWindowsライクなListViewの実装

# 1．Windowsライクなリストビューを作ろう

　Webシステムでデータを表示しようと思ったとき、ヘッダを固定しつつデータを表示したいと思ったことは無いだろうか？実際にやってみるとヘッダ部分を固定する程度は造作も無く実装可能だ。ではさらに条件を付け加えていく。データ項目は複数あり、項目ごとにヘッダを分割し、さらにサイズは可変にする。

　イメージするものはWindowsのExplorerのリスト部分だ。ヘッダを固定しつつ縦横のスクロールに対応し、ヘッダの端を引っ張るとサイズを変更できるあれだ。この処理は簡単なように見えて、JavaScriptとCSSを駆使してやろうとすると無茶苦茶面倒くさい。だからExplorer並の実装をしているWebインタフェイスはほぼ見かけない。似たようなものを見かけたとしても横方向のスクロールに対応していなかったりと、どこかしら足りていないのだ。

　無いものは作れば良い、もしあったとしても車輪の再発明を恐れない、なぜなら自分が作ったものが最もカスタマイズ出来るからだ。欲しい機能があったら他人が作ってくれるのを待たず、自分でバンバン実装していけるのだ。

# 2．Windowsの真似をするんだからもちろんウインドウ表示するよ

　基本設計はWin32APIでウインドウを操作するライブラリを自作した状態に近い。それにC#のクラシックデスクトップアプリのWindowsFormsを混ぜたものになる。Webアプリの作成をネイティブ環境に近づけるのだ。ライブラリをとことんそろえていけば、いずれHTMLは一切書かずに済むだろう。

　そしてWin32APIの設計思想通り、あらゆるコンポーネントはWindowの基本クラスを継承する。TreeViewや今回作成したListViewも全てWindowクラスを継承して作った。

# 3．完成状態


#　3.1 動作サンプル
　[https://javascript-windowframework.github.io/JSW/](https://javascript-windowframework.github.io/JSW/)

#　3.2 スクリーンショット

　これだ見たらWebアプリだとは気づかれないかもしれない
![Desktop 2018.12.30 - 18.31.56.04_1.gif](https://qiita-image-store.s3.amazonaws.com/0/267629/d39cd307-a703-fca4-8301-80099a33ab04.gif)

　※[https://randomuser.me/](https://randomuser.me/)のサンプルユーザデータを使用
　　Ajaxの実装をテストする場合に便利

#　3.3 ライブラリ利用者が書く部分のソースコード

　・今回使っている全ソース
　　[https://github.com/JavaScript-WindowFramework/JSW](https://github.com/JavaScript-WindowFramework/JSW)

　下のソースコードはフレームワーク利用者が作成する部分となる
　フレームワーク自体のソースは結構な量があるのでGithubの方で確認して欲しい
　TypeScriptを利用しているため、.tsが本体となる


```Main.ts
class UserList extends JSW.JListView{
	//Ajaxのデータ取得元URL
	static URL = 'https://randomuser.me/api?results=100'

	constructor(){
		super({frame:true})				//フレーム有りのウインドウを作成
		this.setSize(800,600)			//ウインドウサイズの設定
		this.setTitle('ユーザリスト')	//タイトルの設定
		//リストビューのヘッダを設定
		this.addHeader([['画像', 35], ['ID', 80], 'EMail','Password','LastName','FirstName'],150)
		this.load()						//データの取得要求
	}

	//データ取得処理
	load(){
		//Ajaxによるデータ要求処理
		let xmlHttp = new XMLHttpRequest()
		xmlHttp.onreadystatechange = function () {
			if (xmlHttp.readyState == 4) {
				let results = JSON.parse(xmlHttp.responseText).results
				for (let i = 0; i < results.length;i++){
					let value = results[i]
					//顔イメージ用
					let pic = document.createElement('img')
					pic.style.height='100%'
					pic.src = value.picture.thumbnail;
					//リストビューにアイテムを追加
					this.addItem([pic, value.id.name, value.email, value.login.password, value.name.last, value.name.first]);
				}
			}
		}.bind(this)
		xmlHttp.open('GET', UserList.URL,true)
		xmlHttp.send()
	}
}

//ページ読み込み時に実行する処理を設定
addEventListener("DOMContentLoaded", Main)
//ページ読み込み後に実行される内容
function Main() {
	//ユーザリスト
	let list = new UserList()
	//位置を真ん中に設定
	list.setPos()
}
```

　JavaScriptを呼び出す部分は最低限必要だ

```index.html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8"/>
	<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/>
	<link rel="stylesheet" href="css/JSWindow.css"/>
	<script type="text/javascript" src="js/JSWindow.js"></script>
	<script type="text/javascript" src="js/JSWTreeView.js"></script>
	<script type="text/javascript" src="js/JSWButton.js"></script>
	<script type="text/javascript" src="js/JSWListView.js"></script>
	<script type="text/javascript" src="js/Main.js"></script>
	<title>JSWindowTest</title>
</head>
<body>
</body>
</html>
```

# 4　まとめ

　現在フロントエンドのフレームワークをリメイクすること3回目となっている。そのたびにListViewを作り直してはいるのだが、あらゆる部分の中で最も面倒な存在がコイツである。見た目に派手な部分が無いにもかかわらず、TreeView等とは比較にならないほどやるべきことが多い。とにかく一番面倒なものの面倒な部分の実装は今回、終わらせることが出来た。

　今回作った部分まででWindowの基本機能、TreeView、ListView、ウインドウ分割用のSplitter、Button等の見た目の実装が完了した。まだまだ足りない機能があるので、開発を続けていかなければならない。

　この手のフレームワークを使ったWebシステムを作る場合、バックエンド側の役割は最初にJavaScriptのソースを渡すこと、そしてその後はAjaxのデータの入出力だけで済むようになる。つまりAPIサーバとしての役割に特化すればいいのだ。

　今までの開発手法のようなViewを作るのに、バックエンド側でHTMLを生成し、フロントエンド側のJavaScriptとの辻褄を合わせる必要は無い。バックエンド側は利用者の権限を把握してデータの入出力をするだけで良いのだ。Viewに関する処理はJavaScriptと付随するCSSを管理するだけとなり、それぞれの役割が明確に切り分けられる。

　最近作ったWebシステムはbodyタグの中身は空っぽのものばかりだ。
 　　[https://croud.jp](https://croud.jp)
　ここもbodyタグの中身は空っぽで作ってある。全てJavaScriptで生成しているのだ。そしてJavaScriptここまで作ってもGoogleBotが認識出来る仕様の範囲内で収まっている。GoogleBotに限定すればSSRしなくても大丈夫なのだ。

　こんな形でSPA(SinglePageApplication)を普及させていけば、ユーザの利便性だけで無く開発の効率化にも繋がる。SPAは高い技術がいると言われているが、それはバックエンドほど便利なフレームワークやライブラリが揃っていないだけなのだ。

　この手のライブラリはとにかく実装が面倒なだけで、高度な技術は必要としない。本当に必要なのは技術では無く根気なのだ。