MojitoはYUI3ライブラリ(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 Mini | index.opera-mini.mu.html |
iPhone | index.iphone.mu.html |
iPad | index.ipad.mu.html |
Android | index.android.mu.html |
Windows Mobile | index.iemobile.mu.html |
Plam | index.palm.mu.html |
Kindle | index.kindle.mu.html |
Blackberry | index.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オブジェクトはYUIのNodeオブジェクトです。YUIでDOMをラッパーしたものとなります。ご覧の通り、使い方は結構簡単です(通常のDOMやjQueryなどに似ているので)。
まとめ
アプリの作り方を工夫すれば、最初の画面のみWeb上から表示し、残りはclient側で実行させることも出来そうです。ユーザ体験を向上させ、使いやすいアプリを実現できると、なお面白いですね。