TypeScript Sampleをやってみるその１０


## はじめに
ToDoアプリのサンプルの備忘録です。
[MVC(Model, View, Controller)](https://qiita.com/s_emoto/items/975cc38a3e0de462966a)モデルのアプリになります。
Web上の[ajax](https://ja.wikipedia.org/wiki/Ajax)ライブラリを参照する本格的なつくりになっています。
技術的にはTypeScriptのクラスを使用して[バックボーン](https://ja.wikipedia.org/wiki/Backbone.js)モデルとビューを作成します。
[DOM](https://qiita.com/hththt/items/cc047e326994f440a17a)操作に関しては[JQuery](https://ja.wikipedia.org/wiki/JQuery)を使用しています。
ローカルで実行するためにPythonの簡易サーバを使用します。
ハイレベルな世界への突入感は否めませんが、必ずどこかに攻略するポイントがあることを信じて、「やってみましょう！」

## 前提
* [Visual Studio Code](https://code.visualstudio.com/download)がインストール済み
* [Node.js/npm](https://qiita.com/taiponrock/items/9001ae194571feb63a5e)がインストール済み
* gitから[Sampleをダウンロードして](https://github.com/Microsoft/TypeScriptSamples/archive/master.zip)任意のディレクトリに解凍済み
* [pythonがインストール](https://qiita.com/taiponrock/items/f574dd2cddf8851fb02c)済み
* OSはWindows7/10を想定

## サンプル todomvc
Backbone.jsを使用したToDoサンプル。
## ディレクトリ構成

```
./
├─css/
└─js/
```
## ファイル構成
|パス|ファイル名|説明|
|:--|:--|:--| 
|.|index.html|ToDo画面html|
|.|README.md|このサンプルの説明と使用方法|
|.|server.py|Python簡易サーバスクリプト(新規追加)|
|.|tsconfig.json|TypeScriptのコンパイルコンフィグファイル|
|css|destroy.png|×ボタン画像ファイル|
|css|todos.css|スタイルシート|
|js|todos.js|todos.tsのコンパイルにて作成されたJavaScriptファイル|
|js|todos.js.map|todos.tsのコンパイルにて作成されたmapファイル|
|js|todos.ts|ToDoサンプルTypeScriptファイル|
### 新規追加
#### server.py

``` Python
import http.server
import socketserver

PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()
```

## クラス図
![TS_047.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/4fd8d852-e421-e4e1-2deb-27e1e40aa480.jpeg)

## 実行
```
cd ./todomvc
tsc --sourcemap js\todos.ts
python server.py
```

## 結果
![TS_048.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/53c259f1-7c9e-3be2-a5ab-adace82f8317.jpeg)
ブラウザでURL http:/127.0.0.1:8000/ を指定します。
![TS_049.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/7c184d8b-85d7-77f1-3a98-a1cb818668c4.jpeg)
What needs to be done?のテキストボックスにcar washを入力<kbd>Enter</kbd>
ca washがリストに追加されます。
![TS_050.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/ed3bfba2-823d-62bd-2cae-b9adf2274a33.jpeg)
 Mark all as completeのチェックボックスを選択します。
Clear 1 completed itemと出力したコマンドボタンが表示されます。
![TS_051.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/007c2480-0293-3ee5-4434-87340718f539.jpeg)
コマンドボタンを押下すると追加したcar washが削除されます。
![TS_052.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/97d9a7df-3652-1010-d0c0-6677033781d3.jpeg)
>
ToDo（するべきこと）リストを作成して、完了したアイテムを削除し、ToDoアイテムの残を管理する単純なアプリです。
>

## ポイント
この複雑な動作をどのように実現しているのか？
index.htmlを参照してみましょう。
scriptで指定している外部参照のJavaScriptが５つあります。

``` html:index.html抜粋
<head>
    <title>Backbone.js</title>
    <link href="css/todos.css" media="all" rel="stylesheet" type="text/css"/>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js"></script>
    <script src="js/todos.js"></script>
  </head>
```

|ライブラリ|ファイル名|機能|
|:--|:--|:--| 
|json2|[json2.js](http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js)|jsonライブラリ|
|jquery|[jquery.min.js](http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js)|jQueryライブラリ(軽量）|
|underscore|[underscore-min.js](http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js)|配列処理ライブラリ(軽量)|
|backbone|[backbone-min.js](http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js)|MVCフレームワーク(軽量)|
|backbone.localStorage|[backbone.localStorage-min.js](http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js)|MVCクライアントフレームワーク(軽量)|
※軽量-コメント、改行コード、インデントなどロジック外のコード全てを削除してファイルサイズを小さくしたもの。

ToDoアプリの骨格はMVCを実現している[backbone](http://backbonejs.org/#)にあります。backbone.jsのサイトから抜粋。
>
## 入門
>
・・・
Backboneでは、データをモデルとして表現し、作成、検証、破棄してサーバーに保存することができます。 UIアクションによってモデルの属性が変更されると、モデルは「変更」イベントをトリガします。モデルの状態を表示するすべてのビューに変更が通知されるので、それに応じて応答し、新しい情報で自分自身を再描画することができます。完成したBackboneアプリケーションでは、特定のIDを持つ要素を見つけて、手動でHTMLを更新するためにDOMを調べるグルーコードを書く必要はありません。モデルが変更されたとき、ビューは単に更新されます。
Backboneは、ビジネスロジックをユーザーインターフェイスから切り離します。ロジックがUIに依存しないため、インターフェイスが使いやすくなります。
・・・
### Models and Views
![intro-model-view.png](https://qiita-image-store.s3.amazonaws.com/0/239597/3cbc04f4-00e4-ca26-c7dc-d65be083389b.png)
### Model
◦データとビジネスロジックを調整します。
◦サーバからロードして保存します。
◦データが変更されたときにイベントを終了します。
### View
◦変更を待ち受け、UIを表示します。
◦ユーザー入力とインタラクティブ機能を扱います。
◦取り込まれた入力をモデルに送信します。
### Collections
![intro-collections.png](https://qiita-image-store.s3.amazonaws.com/0/239597/d55e297b-adf2-7c58-81c6-ca36679a5179.png)
>
◦Modelのサーバーへのロードと保存を実行します。
◦Modelのリストに対して集計や計算します。
◦Modelで発生したすべてのイベントを管理します。
>

と説明を見てもピンときませんよね。
[TypeDoc](https://qiita.com/ConquestArrow/items/eb4a0dfb13497be4d6a3)で `todos.ts`のドキュメントを作成してみます。
TypeDocのインストール下記参照（ローカルにインストールの場合は-gを省略）

```
npm install -g typedoc --save
 ```
`todos.ts` のドキュメント出力。
コマンド : `typedoc --out 出力ディレクトリ 対象ソース.ts`

```
cd ./todomvc/js
typedoc --out ./doc/ todos.ts
```
typedocは出力ディレクトリ./doc/を作成してくれます。
./doc/に出力された`index.html`ブラウザーで表示。
![TS_053.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/084880f1-e077-e718-933c-b7ae4c4fffcc.jpeg)

`todos.ts`のメンバーを整理すると下記表になります。
ピンクの<font color="HotPink">AppView</font>は`todos.ts`の最後でインスタンスを作成しています。
この<font color="HotPink">AppView</font>が`todos.ts`のメイン処理です。あとはすべて従属するメンバーになります。

|module|interface|class|Varibles|
|:--|:--|:--|:--|:--|
|Backbone||Model||
|||Collection||
|||View||
||JQuery||
||||$|
||||_|
||||Store|
||||todos|
|||Todo||
|||ToDoList||
|||ToDoView||
|||<font color="HotPink">AppView</font>||
とりあえず登場人物は一覧化しました。
この登場人物の関係は`todos.tsのAppViewクラス`に<font color="HotPink">ヒント</font>があります。

``` TypeScript:todos.tn抜粋
   // Delegated events for creating new items, and clearing completed ones.
    events = {
        "keypress #new-todo": "createOnEnter",
        "keyup #new-todo": "showTooltip",
        "click .todo-clear a": "clearCompleted",
        "click .mark-all-done": "toggleAllComplete"
    };
```
`events`にindex.htmlのidに対応するAppViewクラスのメッソドがjson形式で定義されています。
`index.html`のイベントドリブンでAppViewのメッソドが処理されます。

|event|id|AppView.method|
|:--|:--|:--|
|keypress|new-todo|createOnEnter|
|keyup|new-todo|showTooltip|
|click|todo-clear|clearCompleted|
|click|mark-all-done|toggleAllComplete|
これから、`todos.ts`のイベントドリブンなシーケンス図を作成します。

![TS_054.jpg](https://qiita-image-store.s3.amazonaws.com/0/239597/243c5a30-9d78-7b6c-0e60-3f6687a82f7e.jpeg)
`todos.ts`とBackboneの混沌とした関係がやっと見える化できました。
## ノート
### TypeScriptソースハッキング
- ドキュメントツールTypeDocで登場人物を抽出
- 主人公の特定
- 登場人物をイベントドリブンに見える化（シーケンス図）

## まとめ
Backbone.jsのサンプルです。Backbone.jsサイトのサンプルでも今回取り上げたサンプルが紹介されています。
Hello world!からこのサンプルのレベルでは天と地の差感が否めません。
こんなアプリを作りたい、でもどうやって実装しているのか？
今回のノートにヒントがあります。

以上、おそまつ