Cordovaのチュートリアルをやってみる 第九回

# 使用したもの(環境)
 1. cordova
 1. visualStudioCode
 1. windows10
 1. Android
 

---

# チュートリアルを訳しながらやってみる
チュートリアルのページは下記。

[Module 10: Implementing View Routing](http://ccoenraets.github.io/cordova-tutorial/routing.html)

前回のチュートリアル。

[Cordovaのチュートリアルをやってみる 第八回](https://qiita.com/tokky_se/items/2ebaeeb31c634e9c12f3)

環境構築については別途まとめてあるので下記参照。

[cordova&VSCodeで環境を構築するまでの右往左往メモ。](https://qiita.com/tokky_se/items/346429d234c91bece11d)

---


# Module 10: Implementing View Routing
In this section, we add an employee details view. 
このセクションでは従業員の詳細ビューを追加します。

Since the application now has more than one view, we also add a simple view routing mechanism.
アプリケーションには複数のビューが存在するため、単純なビュールーティングメカニズムも追加します。

Step 1: Create the employee template
ステップ1 従業員テンプレートを作成する

index.htmlを開き、 renderに詳細な従業員ビューを追加するテンプレートを追加する。


```html 
    <script id="employee-tpl" type="text/template">
      <header class="bar bar-nav">
          <a class="btn btn-link btn-nav pull-left" href="#">
              <span class="icon icon-left-nav"></span>
          </a>
          <h1 class="title">Employee</h1>
      </header>
      <div class="content">
          <div class="card">
              <ul class="table-view">
                  <li class="table-view-cell media">
                      <img class="media-object pull-left emp-pic" src="assets/pics/{{pic}}">
                      <div class="media-body">
                          {{ firstName }} {{ lastName }}
                          <p>{{ title }}</p>
                      </div>
                  </li>
                  <li class="table-view-cell media">
                      <a href="tel:{{ officePhone }}" class="push-right">
                          <span class="media-object pull-left icon icon-call"></span>
                          <div class="media-body">
                              Call Office
                              <p>{{ officePhone }}</p>
                          </div>
                      </a>
                  </li>
                  <li class="table-view-cell media">
                      <a href="tel:{{ cellPhone }}" class="push-right">
                          <span class="media-object pull-left icon icon-call"></span>
                          <div class="media-body">
                              Call Cell
                              <p>{{ cellPhone }}</p>
                          </div>
                      </a>
                  </li>
                  <li class="table-view-cell media">
                      <a href="sms:{{ cellPhone }}" class="push-right">
                          <span class="media-object pull-left icon icon-sms"></span>
                          <div class="media-body">
                              SMS
                              <p>{{ cellPhone }}</p>
                          </div>
                      </a>
                  </li>
                  <li class="table-view-cell media">
                      <a href="mailto:{{ email }}" class="push-right">
                          <span class="media-object pull-left icon icon-mail"></span>
                          <div class="media-body">
                              Email
                              <p>{{ email }}</p>
                          </div>
                      </a>
                  </li>
              </ul>
          </div>
      </div>
  </script>
```

Step 2: Create the EmployeeView class
ステップ2 従業員ビュークラスの作成

1\. jsディレクトリにEmployeeView.jsという名前のファイルを作成し、次のように定義します。

```js 
var EmployeeView = function(employee) {

  this.initialize = function() {
      this.$el = $('<div/>');
  };

  this.render = function() {
      this.$el.html(this.template(employee));
      return this;
  };

  this.initialize();

}
```

2\. index.htmlのapp.jsのscriptタグの直前にEmployeeView.jsを含めるスクリプトタグを追加します。

```html
<script src="js/EmployeeView.js"></script>
```

Step 3: Implement View Routing
ステップ3 ビュールーティングの実装

1\.index.htmlのjquery.jsのscriptタグの直後にrouter.jsを含めるスクリプトタグを追加します。

```html
<script src="lib/router.js"></script>
```

2\. app.jsを開き、コンパイル済みの従業員テンプレートをEmployeeViewのプロトタイプに追加します。

```js
EmployeeView.prototype.template = Handlebars.compile($("#employee-tpl").html());
```

3\. アプリケーションで使用される2つのルートを定義します。

```js
service.initialize().done(function () {
  router.addRoute('', function() {
      $('body').html(new HomeView(service).render().$el);
  });

  router.addRoute('employees/:id', function(id) {
      service.findById(parseInt(id)).done(function(employee) {
          $('body').html(new EmployeeView(employee).render().$el);
      });
  });

  router.start();
});
```

4\. アプリケーションをテストします。
![test.gif](https://qiita-image-store.s3.amazonaws.com/0/196422/c61ce708-eff6-9baa-637c-35a17c0efeda.gif)


ちょっとrouter.jsについての解説。
ここで使用しているrouter.jsは特にライブラリとして提供されているものではなさそう？です。(違ったら教えてください…)  
router.jsを見ると、特にコメントにてバージョンや作成者などの表記がないことと、同様の名前を持つライブラリはいくつかGitHubにあるみたいですが、  
実際のソースは違うようです。
ex.
https://github.com/haithembelhaj/slim-router/blob/master/src/router.js
https://github.com/ramiel/router.js/blob/master/src/router.js

実装の内容を見てみると、コンストラクタ関数から始まっていて、
* addRoute:キーと表示する処理の即時関数を引数にしてrouter内部で保存する。
* load:window.location.hashを使用して#以降のURLに引数の文字列を設定する。
* start:window.location.hashの変化を検知して呼び出される。

というメソッドを提供します。
startの具体的な中身はコメントで補足したコードを以下に示します。

```js
    function start() {

        // 要するにemployees/8みたいなものが取れる。
        var path = window.location.hash.substr(1),
        // [employees,8]などがparts
            parts = path.split('/'),
        // partsLengthは2か0
            partsLength = parts.length;

        // addRouteされたhandlerを走査していく
        for (var i = 0; i < routes.length; i++) {
            var route = routes[i];

            // 現在のURLから取得したpartsLengthは捜査対象のrouteのpartsLengthと一致するか？
            if (route.parts.length === partsLength) {
                
                // パラメータ保存の変数
                var params = [];

                // 登録されたpartsを走査していく
                for (var j = 0; j < partsLength; j++) {
                    
                    // 1文字目は:か？
                    if (route.parts[j].substr(0, 1) === ':') {
                        // yesの場合はparamsに保存しておく。
                        // employees/8の場合は8が格納される。
                        params.push(parts[j]);
                    // addRouteで登録されたpartsと今現在のURLから取得したpartsは一緒か？
                    } else if (route.parts[j] !== parts[j]) {
                        // 一緒でない場合はループから抜ける
                        // employees/8の場合はここには入らない想定。
                        break;
                    }
                }

                // ここまででparamsには1文字目が:のpartsだけが集まっている
                // 末尾まで走査していればj === partsLengthは成り立つはず
                if (j === partsLength) {
                    // 引数をparamsとしてhandlerを呼び出す。
                    // handlerは画面表示する処理をまとめた関数。
                    route.handler.apply(undefined, params);
                    return;
                }
            }
        }
    }
```

---

# 参考URL


[Module 10: Implementing View Routing](http://ccoenraets.github.io/cordova-tutorial/routing.html)

[Cordovaのチュートリアルをやってみる 第八回](https://qiita.com/tokky_se/items/2ebaeeb31c634e9c12f3)

[cordova&VSCodeで環境を構築するまでの右往左往メモ。](https://qiita.com/tokky_se/items/346429d234c91bece11d)

https://github.com/haithembelhaj/slim-router/blob/master/src/router.js

https://github.com/ramiel/router.js/blob/master/src/router.js