Monaca / OnsenUI を使ってハイブリッドアプリ開発を簡単に！

※本ドキュメントは、2015年10月に開催するハンズオンワークショップ向けのドキュメントです。
※本内容は、ドキュメント作成時において有効なAPIやライブラリを利用しています。
※2016年9月時点の仕様に修正しました。
#1.はじめに
**Monacaとは**
Monacaは、アシアル社が提供する、スマートフォン向けアプリの開発環境の呼称です。アプリの開発は、MonacaクラウドIDE(Web経由)を使用して行います。
開発環境の提供だけではなく、だれでも簡単にスマートフォン向けのアプリ開発ができるように、その仕組みとサポートを提供してくれています。

![057.png](https://qiita-image-store.s3.amazonaws.com/0/81226/0541bf6d-d36e-1b99-923c-1586bae5cbdd.png)



**OnsenUIとは**
OnsenUIは同じくアシアル社が提供する、フロントエンド開発用のツールです。OnsenUIが提供するUIを使用すると、PhoneGap/Cordovaアプリを非常に簡単に綺麗で見映えの良い、使いやすいUIを実現できます。JQuery-MobileやSencha-Touchなんかと似たようなものと思ってもらえれば良いです。
ハイブリッドアプリにおいても、ネイティブ並みの外観と操作性を、すべてのプラットフォーム上で実現できます。Monacaと共に使用すれば、バックエンドとデバイスのサポート機能を追加でき、公開可能なアプリを簡単に作成できます。Monacaが提供するテンプレートには標準でOnsenUIが使用されています。

**詳しくは**
[Monaca Docs](http://docs.monaca.mobi/cur/ja/)をご覧ください。

#2.開発準備
**Monacaにアカウントを作成**
Monacaのサイトへアクセスします。
https://ja.monaca.io/

「今すぐ試す（無料）」をクリックします。
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/a00d994c-72bf-7783-e8a3-a0f1b7c71c4e.png)

メールアドレス、パスワードを入力し、利用規約同意のチェックボックスをONにし、「今すぐ登録（無料）」をクリック。
![051.png](https://qiita-image-store.s3.amazonaws.com/0/81226/1585acb5-b04a-7919-1862-5d58c4a03358.png)

確認メールを送信した旨を告げる画面が表示されます。
もし、メールが届かないようなら、「確認メールを再送する」ボタンをクリックし、再度メール受信を試みてください。
![053.png](https://qiita-image-store.s3.amazonaws.com/0/81226/b067926e-3e0a-74ce-d9fe-2ed57895f073.png)

メールを確認し、リンクをクリックします。
![054.png](https://qiita-image-store.s3.amazonaws.com/0/81226/9793b598-d162-8dbc-eb79-c5d8ca268d1d.png)

アカウントの登録が完了しました。
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/a2f58a48-2435-ec0b-751a-6619da4c9717.png)

自動的にダッシュボードへ遷移します。
![001.png](https://qiita-image-store.s3.amazonaws.com/0/81226/423164bf-9454-8efb-eaf1-0f2d24984fd1.png)


**IDEを使ってみる**
ダッシュボード画面の左側に、作成したプロジェクトがリスト表示されます。デフォルトで「Hello Worldアプリ」が作成されています。
新規に開発をスタートする場合は、同じペインの上部「新規プロジェクトの作成」をクリックします。
![002.png](https://qiita-image-store.s3.amazonaws.com/0/81226/96d092a5-bfaa-f98d-fc23-b5e6e9be1a8c.png)


monacaは用途に応じた沢山のテンプレートを用意してくれています。
テンプレート選択のリボン上にある「Onsen UI」がデフォルトで選択されているので、この中から今回は「Onsen UI V2 JS Minimum」を選択します。
![003.png](https://qiita-image-store.s3.amazonaws.com/0/81226/cb4253f7-7943-ac78-2632-18bab3aa1472.png)


プロジェクト名は任意の名称でOKです。ここでは「kawaseapp_monaca」とします。
プロジェクトを作成するボタンをクリック。
![060.png](https://qiita-image-store.s3.amazonaws.com/0/81226/240922aa-5bed-7276-59e8-278d101cd9db.png)

左ペインの最上部に新しく「kawaseapp_monaca」が追加されたことが確認できます。
開くボタンをクリック。
![061.png](https://qiita-image-store.s3.amazonaws.com/0/81226/4a64dbe8-204f-83b9-a277-71428deede4f.png)


IDEが開き、READMEが表示されます。READMEは閉じてOKです。
既にお気づきの通り、IDEの右ペインにはデフォルトでプレビューが表示されます。
このまま表示させておいても良いですし、邪魔でしたら消してもOKです。
再表示させたい場合はツールバー上の「プレビュー」をクリックします。
![065.png](https://qiita-image-store.s3.amazonaws.com/0/81226/b13f85dc-da06-3cf0-cc78-dba0ba498d03.png)

#3.実装
**実際にアプリを作成する**
今回は[Cordovaで始めるハイブリッドモバイルアプリ（for Windows）](http://qiita.com/taipon_rock/items/63f7103d681c2263ad40)をMonacaで焼きなおします。
環境構築からコーディングまでを手作業したものと比べてもらえれば、と思います。

さて、今回の為替レートアプリ向けにファイルを編集していきます。
先ず、index.htmlを編集します。
下記の通りコーディングしてください。差分を書き加えるのは面倒だと思うので、下記コードで上書きして頂いてOKです。
ここではメインはJS処理の記述です。

```lang:index.html
<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <script src="components/loader.js"></script>
    <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script>
        ons.bootstrap();

        var b_amount = 0;   // 変換前の通貨額
        var b_unit = "";    // 変換前の通貨単位
        var a_unit = "";    // 変換後の通貨単位
        var e_late = 0;     // APIから取得する為替レート
        var url = "";       // API呼び出しのURL

        function getExchageRate(beforeCurrency){
            console.log("変換前の金額は"+(document.getElementById("my-input").value)+beforeCurrency+"だよー");

            // 変換前の金額
            b_amount = document.getElementById("my-input").value;

            if (beforeCurrency == "usd") {
                // USDからJPYへ変換
                // 変換前はUSD
                b_unit = "ドル";    
                // 変換後はJPY
                a_unit = "円";
                
            } else if (beforeCurrency == "jpy") {
                // JPYからUSDへ変換   
                // 変換前はJPY
                b_unit = "円";    
                // 変換後はUSD
                a_unit = "ドル";
    
            }
            
            // 為替レート取得APIのURLを設定
            if (_isDebugger()){
                console.log("デバッガーから実行");
                url = "";
            } else {
                url = "http://api.aoikujira.com/kawase/json/"+beforeCurrency;
            }

            // 為替レート取得APIを呼出し
            $.getJSON(url, parseJson);
        }

        function parseJson(json) { 
            console.log("コールバック関数が呼ばれたよー");
            
            // 為替レートを取得
            if(a_unit=="ドル"){
                // JPYからUSD
                e_late = json.USD;
            }else if(a_unit=="円"){
                // USDからJPY
                e_late = json.JPY;
            }else{
                // 今後対象通貨を増やす場合は適宜追加
            }
    
            console.log("為替レートは"+e_late);

            // 計算の為にFloat型へパース
            b_amount = parseFloat(b_amount);
            e_late = parseFloat(e_late);
    
            // 変換前の値×取得した為替レート
            var resaultval = e_late*b_amount;
    
            // 結果表示
            alert(b_amount+b_unit+"は"+resaultval+a_unit);
        }

        /**************************************************** 
        * [機能] Monaca Debuggerから実行されているか調べる
        * [引数] なし
        * [戻値] True：Monaca Debugger / False：Native App
        *****************************************************/
        function _isDebugger(){
            return (location.hostname != "");
        }
    </script>
</head>
<body>
    <ons-navigator var="myNavigator" page="page1.html">
    </ons-navigator> 
</body>
</html>
```


次に、page1.htmlを作成します。
ツリーのwwwを右クリックして「新規ファイル」を選択します。
![004.png](https://qiita-image-store.s3.amazonaws.com/0/81226/84af3cb4-5251-cd5a-83d9-944fd2c492b4.png)

ファイル名に「page1.html」と入力しOKボタンを押します。
![005.png](https://qiita-image-store.s3.amazonaws.com/0/81226/2c5f2dbd-f3bd-4276-9ed6-d7e5cec3d735.png)



page1.htmlには、下記の通りコーディングしてください。こちらも下記コードで上書きして頂いてOKです。
こちらは、ボタンやテキストボックスなどのフォームコントロールの配置やレイアウトを行います。

```lang:page1.html
<ons-page>
    <ons-toolbar>
        <div class="center">Exchange Rate</div>
    </ons-toolbar>

    <div style="text-align: center">
        <br/><br/>
        <input class="text-input" id="my-input">
        <br/><br/>
        <ons-button
            onclick="getExchageRate('usd')">
            USD to JPY
        </ons-button>
        <ons-button
            onclick="getExchageRate('jpy')">
            JPY to USD
        </ons-button>
    </div>

</ons-page>
```

![image](https://qiita-image-store.s3.amazonaws.com/0/81226/fe7c834f-5651-eb2a-9cfe-5a3f472d50b7.png)

Onsen UIを使う為に、コンポーネントをインストールします。
ツリーのwwwを右クリックして「JS/CSSコンポーネント設定」を選択します。
一覧から「Onsen UI (Monaca Version)」を選択し追加ボタンを押します。
![006.png](https://qiita-image-store.s3.amazonaws.com/0/81226/2c90e044-2097-6591-1833-aa2bf3b6f9c8.png)

設定ボタンを押すと、ローダーの設定画面が開きます。
好みのテーマを選択し、OKを押します。
何でも良いのですが、今回は一番上のブルーベーシックテーマを選択しました。
![007.png](https://qiita-image-store.s3.amazonaws.com/0/81226/92fbea46-a35c-b952-364b-3479565a8c6d.png)


編集が終えたらツールバー上の保存ボタンをクリック。（Ctrl+SでもOK）
右ペインのプレビューに変更が反映されます。
ちなみに、本アプリケーションはくじらはんど様のAPIをRESTで呼び出しているので、クロスドメインとなりプレビューでは動作確認はできません。
![066.png](https://qiita-image-store.s3.amazonaws.com/0/81226/9868a33f-91ee-edf3-6980-16eb6f463a7e.png)


**動作確認**
自分の端末にデバッガーをインストールします。
App StoreまたはPlay Storeからmonacaを検索します。
![071.png](https://qiita-image-store.s3.amazonaws.com/0/81226/dac7fc7a-c443-60b8-e5e4-b0b3bd095fdd.png)

インストールします。Asial社が提供しているアプリですのでお間違えなく。
![072.png](https://qiita-image-store.s3.amazonaws.com/0/81226/feb49ace-cc25-ac4c-0201-9c073e72e5d9.png)

インストールが完了したらアプリを起動します。図のアイコンです。
![073.png](https://qiita-image-store.s3.amazonaws.com/0/81226/66fd33aa-a6e8-dcd4-2800-9906fe96bd8c.png)

本投稿の第二章で作成したアカウントでログインします。
![074.png](https://qiita-image-store.s3.amazonaws.com/0/81226/fded8dcc-d5f6-2638-a3a0-02670471b677.png)

WEBの左ペインに表示されていたプロジェクト一覧と同じリストが表示されます。
今回作成した「kawaseapp_monaca」を選択します。
![075.png](https://qiita-image-store.s3.amazonaws.com/0/81226/3393a0eb-8c52-9967-a505-935372895d8e.png)

アプリが起動するので、金額を入力しボタンをタップします。
試しにテキストボックスへ「100」と入力し「USD to JPY」をタップします。
これは、100USDをJPYへ変換する事を意味します。
![077.png](https://qiita-image-store.s3.amazonaws.com/0/81226/2ca4a815-e15d-4167-3105-ea2acb313b83.png)

結果が表示されれば成功です！
![078.png](https://qiita-image-store.s3.amazonaws.com/0/81226/88940058-5829-332a-5c05-15240e9ba070.png)


**ソースコード**
今回のソースコードは[私のGitHub](https://github.com/taijihagino/kawaseapp_monaca)からダウンロード頂けます。


#99.おまけ
**Webで使う場合**
参考出展：[AsialBLOG](http://blog.asial.co.jp/1370)

bowerのインストール
`$ npm install -g bower`

新たに作ったプロジェクトのディレクトリへ移動
`$ cd C:\Users\hagino_taiji\Documents\monaca\onsenui_for_website`

OnsenUIのインストール
`$ bower install onsenui`

品質向上へのレポートはYesでもNoでも
`? May bower anonymously report usage statistics to improve the tool over time? Yes`

Gulp使うために初期化（Package.jsonの生成）
Gulpはグローバルとローカルがある
`$ npm init`

パラメーターは任意の値を設定
> name: (onsenui_for_website)　　　*※サイト名称(今回は指定なし)
> version: (1.0.0) 0.0.1　　　　*※アプリのバージョン*
> description: Web site that use the Onsen UI　　　*※説明文*
> entry point: (index.js)*　　　　※webアクセス時。最初に開始されるファイル*
> test command: 　　　*※テストコマンド(今回は指定なし)*
> git repository: 　　　*※Gitリポジトリ(今回は指定なし)*
> keywords:　　　　*※キーワード(今回は指定なし)*
> author: Atsushi Nakatsugawa　　　　*※Author名(今回は各自の氏名)*
> license: (ISC) MIT　　　　*※該当するライセンス形態(MIT・ISC・BSD)*
> "name": "onsenui_for_website",
> "version": "0.0.1",
> "description": "Web site that use the Onsen UI",
> "main": "index.js","scripts": {
    "test":



package.json というファイルが作成される
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/a9f11585-d847-28ae-b4d5-7f94bb1f2564.png)

下記をすべてインストールする。
`$ npm install --save-dev -g gulp`
--- 以下Gulpのプラグイン ------------------------------
`$ npm install --save-dev gulp-changed`
`$ npm install --save-dev gulp-concat`
`$ npm install --save-dev gulp-coffee`
`$ npm install --save-dev gulp-uglify`
`$ npm install --save-dev gulp-sourcemaps`
`$ npm install --save-dev gulp-webserver`
`$ npm install --save-dev del`


ローカルにもGulpをインストール
ここでいうローカルは前述のとおり「プロジェクトごと」という意味
プロジェクトのディレクトリで下記のコマンドを実行
`$ npm install gulp --save-dev`

バージョンを確認で、グローバルとローカル両方のバージョンが表示されればOK
`gulp -v`
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/51fa1011-8551-1efc-745e-ab7f44835779.png)

gulpfile.jsをプロジェクトディレクトリの直下に作成

```lang:gulpfile.js
// gulpfile.js
var gulp = require('gulp');
var coffee = require('gulp-coffee');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var webserver = require('gulp-webserver');
var sourcemaps = require('gulp-sourcemaps');
var del = require('del');
 
var paths = {
  scripts: ['app/js/**/*.coffee', '!app/external/**/*.coffee']
};
 
// Webサーバの機能です
gulp.task('webserver', function() {
  gulp.src('./')
    .pipe(webserver({
      livereload: true,
    }));
});
 
// スクリプトの結合と配置を行っています
gulp.task('scripts', function() {
  return gulp.src([
      './bower_components/onsenui/build/js/angular/angular.min.js',
      './bower_components/onsenui/build/js/onsenui_all.min.js'
  ])
    .pipe(concat('all.js'))
    .pipe(gulp.dest('./javascripts/'));
});
 
// ファイルの変更を監視しています（今回は使っていません）
gulp.task('watch', function() {
  gulp.watch(paths.scripts, ['scripts']);
});
 
gulp.task('default', ['webserver', 'scripts', 'watch']);
```

下記のコマンドを実行すると、AngularJSとOnsen UIのJavaScriptファイルがくっついた状態で javascripts/all.js として生成される
`$ gulp scripts`

テンプレートのCSSを実際のhtmlが読み込む場所へコピー
プロジェクトルート/bower_components/onsenui/build/css/
を
プロジェクトルート／stylesheets/
としてコピー

index.htmlを作成

```file:index.html
<!DOCTYPE html>
<html class="">
  <head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex">
    <link rel="stylesheet prefetch" href="stylesheets/onsenui.css">
    <link rel="stylesheet prefetch" href="stylesheets/onsen-css-components.css">
  </head>
  <body>
  <script src="javascripts/all.js"></script>
  <script>
      ons.bootstrap();
      //@ sourceURL=pen.js
    </script>
	<ons-page>
	  <ons-toolbar>
	    <div class="center">Checkboxes</div>
	  </ons-toolbar>
	  <ons-list>
	    <ons-list-header>Favorite Sports</ons-list-header>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--list-item">
	        <input type="checkbox">
	        <div class="checkbox__checkmark checkbox--list-item__checkmark"></div>
	        Baseball
	      </label>
	    </ons-list-item>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--list-item">
	        <input type="checkbox">
	        <div class="checkbox__checkmark checkbox--list-item__checkmark"></div>
	        Soccer
	      </label>
	    </ons-list-item>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--list-item">
	        <input type="checkbox" checked="checked">
	        <div class="checkbox__checkmark checkbox--list-item__checkmark"></div>
	        Basketball
	      </label>
	    </ons-list-item>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--list-item">
	        <input type="checkbox" checked="checked">
	        <div class="checkbox__checkmark checkbox--list-item__checkmark"></div>
	        Golf
	      </label>
	    </ons-list-item>
	 
	    <ons-list-header>Favorite Food</ons-list-header>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--noborder checkbox--list-item">
	        <input type="checkbox" checked="checked">
	        <div class="checkbox__checkmark checkbox--noborder__checkmark checkbox--list-item__checkmark"></div>
	        Hamburger
	      </label>
	    </ons-list-item>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--noborder checkbox--list-item">
	        <input type="checkbox">
	        <div class="checkbox__checkmark checkbox--noborder__checkmark checkbox--list-item__checkmark"></div>
	        Beefsteak
	      </label>
	    </ons-list-item>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--noborder checkbox--list-item">
	        <input type="checkbox" checked="checked">
	        <div class="checkbox__checkmark checkbox--noborder__checkmark checkbox--list-item__checkmark"></div>
	        Spaghetti
	      </label>
	    </ons-list-item>
	 
	    <ons-list-item modifier="tappable">
	      <label class="checkbox checkbox--noborder checkbox--list-item">
	        <input type="checkbox">
	        <div class="checkbox__checkmark checkbox--noborder__checkmark checkbox--list-item__checkmark"></div>
	        Natto
	      </label>
	    </ons-list-item>
	  </ons-list>
	</ons-page>
  </body>
</html>
```

gulp コマンドを実行
`$ gulp`

8000番ポートでWebサーバが立ち上がるので、 http://localhost:8000/ にアクセス
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/4bef6d51-8de6-f6c2-0b3e-534fbb88c901.png)




プロフィール画面サンプル

```file:index.html
<!DOCTYPE html>
<html class="">
  <head>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex">
    <link rel="stylesheet prefetch" href="stylesheets/onsenui.css">
    <link rel="stylesheet prefetch" href="stylesheets/onsen-css-components.css">
    <link rel="stylesheet prefetch" href="stylesheets/profile.css">
  </head>
  <body>
  <script src="javascripts/all.js"></script>
  <script>
      ons.bootstrap();
      //@ sourceURL=pen.js
    </script>
	<ons-page>
	  <ons-toolbar>
	    <div class="left"><ons-back-button>Back</ons-back-button></div>
	    <div class="center">Profile</div>
	    <div class="right">
	      <ons-toolbar-button><ons-icon icon="ion-gear-a" style="vertical-align: -4px; font-size: 28px;"></ons-icon></ons-toolbar-button>
	    </div>
	  </ons-toolbar>
	 
	  <div class="profile-card">
	    <img src="images/profile-image-01.png" class="profile-image">
	    <div class="profile-name">Taiji HAGINO</div>
	    <div class="profile-id">@taipon_rock</div>
	    <div class="profile-desc">web designer, software engineer and guitarist</div>
	  </div>
	 
	  <ons-list>
	    <ons-list-item>
	      <ons-row>
	        <ons-col class="info-col">
	          <div class="info-num">87</div>
	          <div class="info-unit">Comments</div>
	        </ons-col>
	        <ons-col class="info-col">
	          <div class="info-num">40</div>
	          <div class="info-unit">Following</div>
	        </ons-col>
	        <ons-col class="info-col">
	          <div class="info-num">38</div>
	          <div class="info-unit">Followers</div>
	        </ons-col>
	      </ons-row>
	    </ons-list-item>
	  </ons-list>
	 
	  <ons-list modifier="inset" style="margin-top: 10px">
	    <ons-list-item modifier="chevron">
	      Write a comment
	    </ons-list-item>
	    <ons-list-item modifier="chevron">
	      See details
	    </ons-list-item>
	    <ons-list-item modifier="chevron">
	      Save to the list
	    </ons-list-item>
	  </ons-list>
	  <br>
	</ons-page>
  </body>
</html>
```

gulp コマンドを実行
`$ gulp`

8000番ポートでWebサーバが立ち上がるので、 http://localhost:8000/ にアクセス
![image](https://qiita-image-store.s3.amazonaws.com/0/81226/a4906086-6c90-0921-e489-5d5ac4bf6a16.png)