本記事は、Firefox OS Advent Calendar 2013 の12/19(木)の記事になります。
みなさまこんばんは。@tsuyogoroと申します。 今年(2013年)ひょんなことから勉強会などに参加させて頂くようになりました。 普段はAndroidのアプリケーションエンジニアをしておりまして、「これからはWebだよね!」と騒がれた2013年、 ワタクシにもWeb化の波が押し寄せてきました (個人的に) 。
「Androidのアプリ開発を始めよう」と動き出したあの頃、 Googleが提供しているAndroid Developersを一生懸命眺めたのと同じように、 Mozillaが提供しているリファレンスサイトを見てみる訳です (凄い、日本語だ…!!)。 しかし(多分65%くらいの)エンジニアの皆さんが思う訳です。
「どうやって画面を切り替えるんだ (Activityとか無いじゃん) 」
「どうやってボタンを配置してユーザ操作をhandlingするんだ (Buttonクラスとか何処?) 」
「どうやってオプションメニュー設置すんの?」
と。残念ながら、Androidのアプリ開発とはかなり色々違います。
今日は、そんな「AndroidアプリケーションエンジニアがWebアプリ開発へ移行する際の素朴な (?) 疑問」を解決してくれる、「Gaia層のコード」リーディングに関して書かせて頂こうと思います。ぶっちゃけ初歩的な内容ばかりですが、皆さんの学習の最初の一歩となれば幸いです。
ソースコードが公開されている github (mozilla-b2g/gaia) によりますと、
Gaia is Mozilla's Phone UX for the Boot to Gecko (B2G) project
だそうです。ソースコードを見てみると、アプリケーション、アプリ用の共通ライブラリ、UIフレームワーク (Building blocks) などが入っています。 testコードやtest用のアプリも入っていますね。
まぁそんな訳でソースコードが公開されていますので、git cloneすれば取れます。
$ git clone https://github.com/mozilla-b2g/gaia
Firefox OSが動く端末も手元にある (と勝手に仮定) 、ソースコードも持ってきた (持ってきましょう) 、 SublimeTextもインストールした (使ってる人多し) 。
じゃあGalleryでも見てみましょう。
- 画面もたくさんありますし
- オプションメニューもある
- タッチ操作 (Flickやピンチインアウトもある)
- ファイル操作もあるし…
と、色々な要素がありますよね。 この中で行われている事が「正解」という訳では無いと思いますが、 一つのリファレンスにはなるかなと思います (何をやるにも色々な実装の仕方があって、そもそも正解が存在するのかと感じる) 。
galleryのコードは下記のパスです。
cd gaia/apps/gallery
galleryアプリは、まず起動するとgridの形でコンテンツの一覧が表示されます。 コンテンツをタップするとフルスクリーンでコンテンツが表示され、 infoアイコンをタップするとコンテンツの情報が見れたり…、そして左上の矢印 (?) をタップすると前画面に戻ったりと、 画面を切り替えながら使っていくアプリですね。
さて、この画面を構成しているファイル (Androidで言うところのlayout用xml) は何処にあるのか探します。
まずgalleryフォルダの直下にあるmanifest.webappを見てみます。 そこに "launch_path" というフィールドがありまして、index.html というファイルが最初に読み込まれる事が分かります。 その辺のサイトと同じでhtmlファイルをまずは読むんですね…と中身を見てみると、なんか結構大きなファイルである事に気づきます。 どうやらこの中にすべての画面に関しての記述があるようで、
<section role="region" id="thumbnail-list-view" class="skin-organic">
<header id="thumbnails-list-top">
<h1 id="thumbnail-list-title" data-l10n-id="gallery">Gallery</h1>
</header>
<footer id="thumbnails-bottom">
<a id="thumbnails-camera-button" class="button"></a>
<a id="thumbnails-select-button" class="button"></a>
</footer>
</section>
例えば上記は、起動直後に表示されるGridリストに関する記述の様です。
では、素朴な疑問その1、Buttonの配置に関して見ていきましょう。
index.htmlの中をもう少し見てみると、"button"というキーワードが出てきます。 "button html"などでググってみると、どうやらhtmlにはbuttonというタグがあるようです (さすがにこれはみんな知ってるか…汗) 。 buttonタグを一つ拾って、どのように使っているか見てみましょう。
<button id="edit-cancel-button"><span class="icon icon-close"></span></button>
ここで、ワタクシのようにAndroidから流れてきた方々はお気付きになるかと思います。 「id使ってfindViewById的なメソッド呼べばいいんじゃねーの?」と。はい、その通りです。 "edit-cancel-button" でgrepしてみると 'js/ImageEditor.js' というファイルの下記箇所が引っかかります。
$('edit-cancel-button').onclick = function() { exitEditMode(false); };
Androidとはちょっと違い、listenerを登録するのではなく「ボタンが押されたときに呼ばれる関数を登録」します。
findViewByIdっぽい'$('edit-cancel-button')' は、jQueryというライブラリの関数の呼び出しで、
$
という名前の関数です。
jQuery は、いわば超有名ライブラリですので、
これからWebアプリ開発を始めるのであれば、学んでいかなくてはいけない事の一つになるかと思います。
(Mozillaがプロダクトの中で利用するくらいのシロモノですからね)
さて、次に画面の切り替え方法を見てみましょう。
gallery.jsというファイルを見ていると、下記のような箇所が見つかります。 これは、FirefoxOSのWebActivitiesという、Androidで言うところのIntentをhandlingしている箇所です。
// Register a handler for activities. This will take care of the rest
// of the initialization process.
navigator.mozSetMessageHandler('activity', function activityHandler(a) {
var activityName = a.source.name;
switch (activityName) {
case 'browse':
// The 'browse' activity is the way we launch Gallery from Camera.
// If this was a cold start, then the db needs to be initialized.
if (!photodb) {
initDB(); // Initialize the media database
setView(LAYOUT_MODE.list);
}
コメントから察するに「Cameraアプリから起動されて、コンテンツの一覧を表示する」というユースケースのための実装の様です。
どうやら setView(LAYOUT_MODE.list);
というコードが画面切り替えに関与しているようで、
パラメータの LAYOUT_MODE.list
がコンテンツ一覧画面に関連しているようです。では LAYOUT_MODE
をgrepしてみます。
// These are the top-level view class which are defined in
// gallery_tablet.css
// This object is used by setView()
// Layout Mode Transition:
// list <-> selection
// list <-> fullscreen <-> edit/crop
// (activity) pick <-> crop
const LAYOUT_MODE = {
list: 'thumbnailListView',
select: 'thumbnailSelectView',
fullscreen: 'fullscreenView',
edit: 'editView',
pick: 'pickView',
crop: 'cropView'
};
なるほど、LAYOUT_MODE.list
とはgallery_tables.cssに定義されているclassの一つの別名だったのですね。
下記は「classの値がthumbnailListViewであるbodyの配下にある、idが"thumbnails"の要素 のスタイル (ちょっと厄介) 」についての記述です。
/* Thumbnails */
body.thumbnailListView #thumbnails {
top: 5rem;
}
では次に、先ほど出てきた setView()
をgrepして、中身を見てみます。gallery.jsがヒットしました。
function setView(view) {
if (currentView === view)
return;
// define each view's layout based on data-view of body
document.body.classList.remove(currentView);
document.body.classList.add(view);
おお、bodyのclassの値が動的に変えられている事が分かりますね。 つまり、galleryの場合「画面の切り替え=body要素のclass切り替え」だったのですね。
要点をまとめると、
- 登場人物をhtmlに記述
- アプリの状態 (どの画面に居るか) ごとの登場人物の状態をcssに記述
- 状態の切り替えをJavaScriptで制御
という感じですね (無理があるかな…) 。
gaia層のgalleryアプリを例に、AndroidアプリエンジニアがWebアプリを始める際、気になりそうなポイント (独断&偏見) を見ていきました。 (オプションメニューの設置、タッチ操作なども書こうと思ったのですが、めちゃくちゃ長くなりそうなのでご勘弁頂きたく)
最後まで読んで頂いた方には何となく伝わったのではないかと思いますが、「なんだかゴチャゴチャしてて難しい…」訳です。 しかし大丈夫です、世の中にはそんな難しさをどうにか解決しようと知恵を絞ってらっしゃる方がたくさんいらっしゃいまして、 様々なアプリケーションフレームワークや便利ツールが公開されています。Webアプリの世界には、 これまで以上に効率の良い開発ができる可能性がたくさん散らばっているのです (なのでまずはそれを集めるところからスタート…) 。
もし興味がありましたら、過去の勉強会のプレゼンなどを参考されると良いと思います。ワタクシもいくつかの講演を聞いて触発され、調べたりしました (AngularJS、KnockoutJs、yeoman...etc) 。
gaiaのコードで基本的にこのようなアプリケーションフレームワークは使われていませんが、 だからこそ敢えて読んでみて自分の学習の素材にするというのもアリかもしれませんね。
長くなりましたが、お付き合いありがとうございましたー。