アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

Mojitoでビューを作る!

MojitoYUI3ライブラリ(Yahoo! User Interface Library)上に構築されたJavascriptフレームワークです。YUI3自体がハイスタックなライブラリであるため、Mojitoでも独自拡張なしに様々なことを実行可能です。

前回の記事でMojitoを触ってみました。今回は、Mojito(とYUI3)の各種機能を使ってみたいと思います。Mojitoを初めて触る方、インストール方法やプロジェクト構成を知らない方は、前回の記事も読んでみて下さい。

今回は、以下の機能を触り、ビューを作ってみます。

  • テンプレート
  • HTMLFrameMojit
  • binder
  • クライアントへのdeploy



初期設定


まずは適当なディレクトリに移動し、サンプルプロジェクトを作成し、サンプルmojitを作成します。



$ mojito create app sampe_app
$ cd sample_app
$ mojito create mojit Sample


sample_appディレクトリ直下にあるapplication.jsonを以下のように編集し、Sample mojitをiアプリ内でインスタンスとして登録します(使えるようにする)。application.jsonを次のように編集します。



[
    {   
        "settings": [ "master" ],
        "specs": {
            "sample": {
                "type": "Sample"
            }   
        }   
    },  
    {   
        "settings": [ "environment:development" ],
        "staticHandling": {
            "forceUpdate": true
        }   
    }   
]


ついでに、ルーティングの設定も行います。まずは、Sample mojitのindexメソッドへのルートを設定しておきます。routes.jsonを次のように編集します。



[{
    "settings": [ "master" ],
    "sample-index": {
        "verbs": ["get"],
        "path" : "/",
        "call" : "sample.index"
    }   
}]


sample_appディレクトリ直下に戻り、サーバを起動します。



$ mojito start


この時点で、http://localhost:8666へアクセスすると、Mojitoが作成した画面が表示されます。ここに表示されている内容は、mojits/Sample/controller.server.js内のindexメソッドを実行した結果です。ちなみに、表示されているテンプレートは、mojits/Sample/views/index.mu.htmlです。


表示内容の変更


表示内容を変更しましょう。変更するには、ロジック部分(mojits/Sample/controller.server.js)とビュー部分(mojits/Sample/views/index.mu.html)の両者を変更します。ここでは、繰り返し構造を表示してみたいと思います。

まずは、mojits/Sample/controller.server.jsを次のように編集します。ここでは、アシアルを紹介してみます。



YUI.add('Sample', function(Y, NAME) {

    Y.mojito.controllers[NAME] = {

        init: function(config) {
            this.config = config;
        },

        index: function(ac) {
            // ビューに渡す内容を設定する
           var data = { 
                'company'    : 'アシアル株式会社',
                'company_uri': 'http://www.asial.co.jp',
                'logo_uri'   : 'http://www.asial.co.jp/images/common/company_logo.png',
                'exectives'  : [ 
                    {'name': '田中正裕', 'position': 'CEO', 'blog_id': 3}, 
                    {'name': '森川穣'  , 'position': 'CTO', 'blog_id': 9}, 
                    {'name': '小林有佳', 'position': 'CFO', 'blog_id': 6}
                ],  
                'employees'  : [ 
                    {'name': '井川数志', 'blog_id': 28},
                    {'name': '松田淳'  , 'blog_id':  4}, 
                    {'name': '海原才人', 'blog_id': 10},
                    {'name': '中川善樹', 'blog_id':  7}  
                ]   
            };

            data['logo_html'] = '<a href="https://www.asial.co.jp' + data['logo_uri'] + ' &mode=1" class="popupimg"><img src="https://www.asial.co.jp' + data['logo_uri'] + '"></a>';

            // ビューに値を渡す
            ac.done(data);
        }
    };
}, '0.0.1', {requires: ['mojito']});


次にビューを編集します。mojits/Sample/views/index.mu.htmlを次のように編集します。会社名、URL、ロゴ、取締役、社員や各々のブログへのリンクを表示します。Mojitoでは様々なテンプレートエンジンを使用可能です。デフォルトでは、Mustacheが使われています(マニュアルはこちら)。



<div id="{{mojit_view_id}}">
    <h2>{{company}}</h2>
    <div class="info">
        <a href="{{company_uri}}">Home</a><br>
        <a href="https://www.asial.co.jp{{logo_uri}} &mode=1" class="popupimg"><img src="https://www.asial.co.jp{{logo_uri}}"></a>
        {{{logo_html}}}
    </div>
    <div class="executives">
        <h3>取締役</h3>
        <ul>
            {{#exectives}}
            <li>
                {{position}}: <span class="name">{{name}}</span>
                <a href="http://blog.asial.co.jp/{{blog_id}}">Blog</a>
            </li>
            {{/exectives}}
        </ul>
    </div>
    <div class="employees">
        <h3>社員</h3>
        <ul>
            {{#employees}}
            <li>
                <span class="name">{{name}}</span>
                <a href="http://blog.asial.co.jp/{{blog_id}}">Blog</a>
            </li>
            {{/employees}}
        </ul>
    </div>
</div>


ファイルを編集したので、サーバを再起動します。サーバの止め方は単純にプロセスを止めればOKです(単に「Ctrl + c」)。再度、sample_appディレクトリでサーバを起動します($ mojito start)。すると、次のような画面が表示されます。



ビューの使い方はいたって簡単です。テンプレートファイル内では、controllerでActionContext(controller内のac変数)のdoneメソッドに渡したオブジェクト内の変数(プロパティ)を表示できます。上記の例で使用した表示方法は次の通りです。

  • 変数名を波括弧2つでくくる
    例えば、companyを使いたいなら、{{company}}とします。この場合、変数を自動的にエスケープしてくれます。XSS対策にはもってこいの機能です。

  • 変数名を波括弧3つでくくる
    エスケープなしで表示します。つまりHTMLタグを表示できます。上記の例では、img_htmlを{{{img_html}}}として出力しています。

  • 繰り返し構造を使用する
    波括弧2つと、#と/を使います。例えば、employees配列を表示する場合、{{#employees}}〜{{/employees}}の間では、各要素の変数を順番に使用できます(forやforeachと同じ)。



ビュー切替


ビューをかなり簡単に作れることが分かったと思います。さらに、Mojitoではデバイス毎のビュー切替にも対応しています。index.mu.hmlをコピーしてindex.iphone.mu.htmlを作ってみましょう。これでiPhoneからアクセスすると、index.iphone.mu.htmlが使用されます。

早速確認してみます。Mojitoでは、デバイスの認識に2つの方法を提供しています。すなわち、ユーザエージェントとGETクエリです。ブラウザから確認する場合には後者の方法を使います。GETクエリにdevice=iphoneと入れると、iphoneのテンプレートを使用してくれます。

index.iphone.mu.htmlとindex.mu.htmlを区別するために、何らかの文字(iPhoneなど)を追加しておきます。http://localhost:8666?device=iphone にアクセスしてみましょう。iPhoneという文字が表示されていると思います。実際にiPhoneで接続できるなら、接続してみましょう。

このビュー切替はファイル名により制御されています。ファイルの命名規則は次の通りです。



{コントローラのメソッド名}.[{デバイス名}].{レンダリングエンジン名}.html


index.mu.htmlのmuはMustasheの頭文字2つです。また、デバイス名は省略可能です。指定できるデバイス名は現在のところ以下の通りです(サポートデバイス)。

バイス・ブラウザファイル名の例
Opera Miniindex.opera-mini.mu.html
iPhoneindex.iphone.mu.html
iPadindex.ipad.mu.html
Androidindex.android.mu.html
Windows Mobileindex.iemobile.mu.html
Plamindex.palm.mu.html
Kindleindex.kindle.mu.html
Blackberryindex.blackberry.mu.html



HTMLFrameMojit


上記のテンプレートでは、HTMLの一部のみを記述し、実際にそれだけを出力しています。実際にHTMLのソースを見ると、DIVタグとその中身だけが表示されます。



<div id="yui_3_4_1_2_1340068746787_6">
    <h2>アシアル株式会社</h2>
    <div class="info">...</div>
    <div class="executives">...</div>
    <div class="employees">...</div>
</div>


HTMLタグ、BODYタグ、必要なJavascriptファイルなどをテンプレートに記述することも可能です。しかし、Mojitoではもっと便利な機能を提供してくれています。HTMLFrameMojitを使えば、HTMLの大枠や、javascriptファイル、clientへのスクリプトファイルのデプロイなどを実行できます。HTMLFrameMojitとは、Mojitoにデフォルトで組み込まれているmojitの1つです。HTMLの大枠を提供するという意味で、Frameという単語を使用しています(frameやiframeタグは使っていません、念のため)。

実際に使ってみます。applicationでHTMLFrameMojitを使用する際には、application.jsonでHTMLFrameMojitをインスタンスとして登録します。そして、HTMLFrameMojitの子インスタンスとして、他のmojitを登録します。実際に、Sample mojitをHTMLFrameMojitの子として登録してみます。



[
    {   
        "settings": [ "master" ],
        "specs": {
            "sample": {
                "type": "HTMLFrameMojit",
                "config": {
                    "title": "Sample App",
                    "child": {
                        "type": "Sample"
                    }   
                }   
            }   
        }   
    },  
    {   
        "settings": [ "environment:development" ],
        "staticHandling": {
            "forceUpdate": true
        }   
    }   
]


routes.jsonや他のファイルは一切編集しません。サーバを再起動し、再度http://localhost:8666ヘアクセスします。出力内容は表面上は変化しませんが、HTMLソースを確認するとずいぶんと異なります。



<!DOCTYPE HTML>
<html>
<head>
    <script type="text/javascript">var MOJITO_INIT=new Date().getTime();</script>
    <meta name="creator" content="Yahoo! Mojito 0.2">
    <title>Sample App</title>
</head>
<body>    
    <div id="yui_3_4_1_3_1340085944832_6">
        <h2>アシアル株式会社</h2>
        ...
    </div>
</body>
</html>


また、HTMLFrameMojitを使うことにより、client側へJavascriptファイルをダウンロードさせることも可能になります。Mojitoではデプロイといいます。デプロイの設定には、application.jsonでdeployプロパティをtrueとします。
application.jsonの一部を抜粋します。



            "sample": {
                "type": "HTMLFrameMojit",
                "config": {
                    "title": "Sample App",
                    "deploy": true,
                    "child": {
                        "type": "Sample"


これでcontrollerなどもclient側へダウロードされるようになります。実際にHTMLソースを確認すると、多数のJavascriptファイルを読み込ませるようになっています。



<!DOCTYPE HTML>
<html>
<head>
    <script type="text/javascript">var MOJITO_INIT=new Date().getTime();</script>
    <meta name="creator" content="Yahoo! Mojito 0.2">
    <title>Sample App</title>
    <script type="text/javascript" src="http://yui.yahooapis.com/combo?3.4.1/build/yui/yui-debug.js &..."></script>
</head>
<body>    
    <div id="yui_3_4_1_3_1340086591104_7">
        <h2>アシアル株式会社</h2>
        ...
    </div>
    <script type="text/javascript" src="/static/mojito/autoload/perf.client.js"></script>
    <script type="text/javascript" src="/static/mojito/autoload/mojito.common.js"></script>
    ...
    <script type="text/javascript" >
        ...
    </script>
</body>
</html>


作り方によっては、危険にもなりますが(セキュリティホールがある場合)、アプリの軽量化に資する仕組みでもあります。


Binder機能


HTMLFrameMojitを使うと、binder機能も楽に使用できます。Mojitoでは、DOMへのイベントリスナー登録や、DOMを変更する仕組みを、controllerやviewから切り離す構造があります。これがbinderです。mojits/Sample/binder/index.jsを編集し、アシアル取締役、社員をクリックすると、各々「取締役:名前」「社員:名前」と表示してみます。



UI.add('SampleBinderIndex', function(Y, NAME) {

    Y.namespace('mojito.binders')[NAME] = { 

        init: function(mojitProxy) {
            this.mojitProxy = mojitProxy;
        },  

        bind: function(node) {
            var me = this;
            this.node = node;

            node.all('.executives li').on('click', function(e) {
               var name = e.currentTarget.one('.name').get('text'); 
                alert('取締役:' + name);
            });

            node.all('.employees li').on('click', function(e) {
               var name = e.currentTarget.one('.name').get('text');
                alert('社員:' + name);
            });
        }
    };
}, '0.0.1', {requires: ['event-mouseenter', 'mojito-client']});


このファイルでは、bindメソッド内に必要な処理を記述します。bindメソッドに渡されるnodeオブジェクトはYUINodeオブジェクトです。YUIでDOMをラッパーしたものとなります。ご覧の通り、使い方は結構簡単です(通常のDOMやjQueryなどに似ているので)。


まとめ


アプリの作り方を工夫すれば、最初の画面のみWeb上から表示し、残りはclient側で実行させることも出来そうです。ユーザ体験を向上させ、使いやすいアプリを実現できると、なお面白いですね。

Mojitoを触ってみる!

Mojito(モヒート)は、Javascriptで記述されたWebアプリケーション用のフレームワークです。米Yahoo!オープンソースとして公開しました(2012/4/1)。

Javascriptを使う機会が増えてきた昨今、非常に興味深いフレームワークです。MojitoはMVC構造を採用しており、コードのきり分けを明確にしています。また、1つのソースで複数のデバイスへ対応させるなど、挑戦的な試みも行っています。

今回は、Mojitoを使ってHello worldアプリを作成してみます。

OSはLinux系(ここではMac OS X使用)、Node.jsが入っていることを前提とします。インストールには、npmコアマンド(Node.jsのパッケージ管理ツール)を使います。



$ sudo npm install mojito -g


ちなみに、今回使用したMojitoのバージョンは0.3.26です。バージョンは以下のコマンドで確認できます。



$ mojito version


早速、Hello worldアプリを作成してみましょう。mojitoでのアプリケーション作成は次の手順となります。

① アプリの生成
② 機能単位の生成(mojit)
③ 各種機能の実装
④ デバイス毎の実行

ここではサーバ側で稼働するアプリを作成します。

① アプリの生成


適当なディレクトリを作成・移動し、以下のコマンドを実行します。Mojitoの処理は、このmojitoコマンドで実行します(詳しくは、YahooのドキュメントMojito Command Line)。



$ mojito create app sample_app


これでカレントディレクトリの中にsample_appディレクトリが作成されます。このsample_appディレクトリ内に、mojitoアプリ用のファイルやディレクトリが生成されています。ディレクトリを移動しましょう。



$ cd sample_app


ディレクトリ中を見てみると以下のようになっています。



├── application.json   [アプリ全体の設定]
├── assets             [アプリ共通のリソース]
│   └── favicon.ico
├── index.js           [アプリをサーバ上で起動するスクリプト]
├── mojits             [アプリの各種機能]
├── package.json       [デプロイ時の設定]
├── routes.json        [ルーティング設定]
└── server.js          [Mojitoサーバ生成スクリプト]


この段階では、サーバ側で表示する内容が何もありません。各種設定ファイルは後ほど編集します。次に実行することは、実際に表示する内容を作成することです。

② 各種機能(mojit)の生成


アプリを生成した後は、必要な機能を生成していきます。Mojitoでは、機能単位としてmojitを生成します。名前が紛らわしいのですが、mojit(最後の"o"がありません)であり、mojitoではありません。mojitとは、モジュールのようなものです。公式サイトによると、mojitという単語は、モジュール(module)とウィジェットwidget)を組み合わせて作られたそうです。

実際に作ってみます。以下のコマンドでHelloWorld mojitを生成します。



$ mojito create mojit HelloWorld


mojitはmojitsディレクトリ内に生成されます。実際に、mojitsディレクトリを確認すると次のようになっています。



mojits
└── HelloWorld                [mojitのルートディレクトリ]
    ├── assets                [mojit内のリソース]
    │   └── index.css
    ├── binders
    │   └── index.js
    ├── controller.server.js  [サーバ用のコントローラ]
    ├── definition.json
    ├── models                [モデルディレクトリ]
    │   └── foo.server.js
    ├── tests                 [ユニットテスト用ディレクトリ]
    │   ├── binders
    │   │   └── index.common-tests.js
    │   ├── controller.server-tests.js
    │   └── models
    │       └── foo.server-tests.js
    └── views                 [ビューディレクトリ]
        └── index.mu.html


mojit(ここではHelloWorld)はその内部にMVC構造を持っています。ここからコントローラ、モデル、ビューや各種設定を編集していきます。

③ 各種機能の実装


単純にHello Worldと表示する機能を実装します。mojits/HelloWorld/controller.server.jsを以下のように編集します。実際には、index: function(ac) {...}の部分を変更しただけです(コメント部分は割愛しています)。

mojit/HelloWorld/controller.server.js


YUI.add('HelloWorld', function(Y, NAME) {

    Y.mojito.controllers[NAME] = { 

        init: function(config) {
            this.config = config;
        },  

        index: function(ac) {
            ac.done('Hello world');
        }
    };
}, '0.0.1', {requires: ['mojito', 'HelloWorldModelFoo']}); 


Javascriptファイルの編集はこれだけです。後は、アプリケーションの設定を行います。アプリのルートディレクトリにある、2つの設定ファイル(application.json、route.json)を編集します。まずは、application.jsonに、インスタンス(アプリ内で使用するmojit)を設定します。

application.json


[
    {   
        "settings": [ "master" ],
        "appPort": 8666, 
        "specs": {
            "hello": {
                "type": "HelloWorld"
            }
        }   
    },  
    {   
        "settings": [ "environment:development" ],
        "staticHandling": {
            "forceUpdate": true
        }   
    }   
]


appPortで使用するポート番号を設定できます。また、specsで指定したオブジェクトにインスタンス名("hello")とその内容("HelloWorld" mojitを使用)を記述します。これでHelloWorld mojitを使用する準備が整いました。

次に、URLとインスタンスを紐づけるルーティングの設定を行います。route.jsonを次のように編集します。

route.json


[{
    "settings": [ "master" ],
    "hello-world": {
        "verbs": ["get"],
        "path" : "/",
        "call" : "hello.index"
    }
}]


hello-worldルートを作り、対象メソッドにGET、パスに"/"を指定しています。そして"call"部分で、このルートに紐付けるmojitとメソッドを設定します。ここではhello.indexと記述することで、helloインスタンス(HelloWorld mojit)のindexメソッドを指定しています(localhost:8666/にアクセスされると実行)。

④ デバイス毎の実行


最後に、サーバを起動してブラウザからアクセスしてみます。サーバの起動は、sample_appディレクトリ直下にて次のコマンドを実行します。



$ mojito start


ブラウザから、localhost:8666にアクセスすると、Hello worldと表示されます。もし、何らかのエラーが発生したら、コンソール画面に表示されます(console.logもコンソール画面に表示されます)。

ちなみに、ここまでで作成したコードからHTML5アプリを生成することもできます(Hello worldではあまり意味ないですけど)。



$ mojito build html5app


すると、sample_app内にartifactsディレクトリが生成され、この中のhtml5appディレクトリ内にHTML5アプリが作成されます。内部を少し見ると、以下のようになります。route.jsonの中で、"/"パスに指定した画面がindex.htmlとして生成されています。



├── application.json
├── artifacts
│   └── builds
│       └── html5app
│           ├── cache.manifest
│           ├── index.html
│           ├── index.js
│           └── static
│               ├── HTMLFrameMojit
│               │   └── definition.json
│               ├── HelloWorld
│               │   ├── assets
│               │   │   └── index.css
│               │   ├── binders
│               │   │   └── index.js
│               │   ├── controller.server.js
│               │   ├── definition.json
│               │   ├── models
│               │   │   └── foo.server.js
│               │   └── views
│               │       └── index.mu.html
...



今回は、サーバ側の単純なアプリ作成の紹介でした。実際には、モデルやビューを作成して画面を作ることになり、もっと本格的なアプリを作ることも可能です。また、mojitoからxcodeプロジェクトを作成することもできるようです。