アプリケーションの構築に Ajax を使う方法は、魅力的なアプリケーションを提供するための着実な方法であることが実証されています。しかし Adobe Flex の爆発的な人気を無視することはできません。私達は常に最高のユーザー・エクスペリエンスを実現するよう迫られる中で、Flash ベースの資産を Ajax アプリケーションに組み込んで統合するという、困難な課題に直面することがよくあります。この記事では、まさにこの統合処理のために Adobe が開発したコード・ライブラリーである FABridge を使って、Flash コンテンツと既存の Ajax コンテンツを統合する方法について説明します。
今日、Ajax 開発者であることは非常に特別なことです。私達は常に最前線に立ち、私達が作成するアプリケーションにユーザーを迎え、最高の第一印象を与えようとしています。Web の標準が進歩し、そうした標準を実装しようと決断するベンダーが多くなるにつれ、私達にとって作業は容易になり、ユーザー・エクスペリエンスに集中できるようになっています。また Ext JS や jQuery、Prototype といった JavaScript フレームワークがさらに進歩したことによって、サポートするよう依頼されたプラットフォーム全体にわたってコードが動作することを確認するのに費やす時間は減り、新しいことを取り入れるためにより多くの時間を費やせるようになっています。
今日私達が利用できるツールや手法、リソースが以前よりも多くなっているのはもちろんですが、同時に開発の方法も変化しており、それも Flash 開発というリッチな世界に向かう上での後押しとなっています。多くの作業現場において、開発のワークフローには UI (User Interface) グループが関わっており、サーバー・サイドで生成されるアプリケーションをサポートするためのデザインを作成しています。現在すでにある JavaScript フレームワークによってですら、私達はクライアント・サイド用のアプリケーション開発という方向へと向かっていっているわけですが、Flash アプリケーションを作成するためのフリーのオープンソース・フレームワークである Flex プラットフォームが登場したことによって、私達はさらに深くアプリケーション開発の領域に入り込むこととなります。この種のイノベーションはクライアント・サイドの作業を行う私達にとっては歓迎すべきことですが、現在のアーキテクチャーとの統合プロセスを、十分に考えて注意しながら行う必要があります。
Ajax 資産と Flex 資産をどのように扱うかを示すコード・サンプルを紹介する前に、この記事で必要とされるツールとスキルを理解しておく必要があります。
- この記事の Ajax サンプルは Ext JS JavaScript ライブラリーを使って作成されています。そのため、このライブラリーとそのサポート文書を含んだ .zip ファイルをダウンロードする必要があります。
- 次に、Adobe Flex 3 SDK と、デバッグ機能を持つ Adobe Flash Player 9 の無料コピーをまだ入手していない場合には、これらを入手します。
- この記事を読み進めるためには必要ありませんが、Adobe Flex Builder 3 の少なくとも試用版を調べてみることをお勧めします。Adobe Flex Builder 3 は Eclipse ベースの IDE (統合開発環境) であり、Flex アプリケーションの開発を迅速に行うことができる他、優れたデバッグ機能やプロファイリング機能を持っています (「参考文献」を参照)。
- 最後に、PHP に関する実用的な知識があると役立ちます。
すべての Ajax コンテンツを Flex 資産で置き換えようとするのであれば、作業はずっと簡単かもしれません。しかしそれはあまり現実的でない上に、多くの場合は不適切な方法です。なぜなら、従来の Ajax 機能を残した方がよい理由は多々あるからです。幸い、両方の環境の最高の部分を保持しながらも、リッチでまとまりのあるアプリケーションを作成できないという理由はありません。
Flash コンテナー (HTML/JavaScript コード) から ActionScript コードにデータを渡すための単純な方法は、クエリー・ストリングや <param> タグを使う方法を含めて、非常に数多くあります。しかしこうした方法では、コンテナーの中にデータを渡すことしかできません。もっと強力な手法として、ActionScript 言語と JavaScript 言語の間の通信の仲介に使われる API (Application Program Interface) である、ExternalInterface クラスを使う方法があります。ExternalInterface の使い方は、リスト 1 の例を見るとよくわかります。
リスト 1. ExternalInterface の例
// ActionScript code
function exposed():String
{
return "Hello, JavaScript!";
}
ExternalInterface.addCallback( "getActionScript", exposed );
// HTML/JavaScript code
<script language="JavaScript">
var result = flashObject.getActionScript();
</script>
<object id="flashObject" ...>
<embed name="flashObject" ... />
</object>
|
リスト 1 は、ExternalInterface クラスを使って ActionScript 関数を登録し、その関数を JavaScript コードで呼び出せるようにするための方法を、必要最低限の形で示した例です。これを行うためには、まず ActionScript 関数を定義し、次に addCallback() メソッドを使ってその関数を JavaScript に公開してそこから実行できるようにします。HTML 側では単純に Flash コンテナーに対するハンドルを取得して、この関数を呼び出します (この関数の名前は addCallback() メソッドの最初のパラメーターを使って付けられます)。この例では JavaScript コードに関数を公開することに焦点を当てていますが、この逆も、ExternalInterface クラスの call() メソッドを使うことで容易に行うことができます。
ExternalInterface クラスは非常に強力かもしれませんが、このクラスを実装しようとすると大きな難題が出てきます。ExternalInterface を使うためには、ActionScript 環境と JavaScript 環境の両方を実装するコードを作成できなければなりません。そのためには追加のスキルが要求されるだけではなく、作業量も倍増します。そうした状況では、コードを管理し、さらに非常にしっかりとした 2 つのスキルを維持することは困難になる可能性があります。
Flash の外部 API を使用して開発を行う際の制約に対応するために、Adobe は FABridge をリリースしました。FABridge は Flex SDK に含まれている小さなライブラリーであり、Flash コンテンツをブラウザーのスクリプト機能に公開するために使われ、また主なブラウザー・プラットフォームのほとんどで動作します。FABridge によって、Flash の外部 API を直接実装するために必要な基盤を成すコードが実質的に不要になりました。また FABridge を実装するためのスキルは、それほどしっかりしたものである必要はなくなりました。JavaScript 開発者は、ActionScript のプロパティーやメソッドに関してどんなものが利用できるのかを理解できさえすれば十分です。では、FABridge でどんなことができるのかを示すいくつかの例を見てみましょう。
FABridge を使い始める前に、ここで扱う開発環境と構成要素を示しましょう。最新の Flex SDK をダウンロードしたら、リスト 2 のようにディレクトリー構造を構成します。
リスト 2. FABridge のチュートリアルのためのディレクトリー構造
/ +--- bridge | +--- fabridge.js | +--- fabridge.as | +--- index.html |
このディレクトリー構造は単純です。index ページがあり、また FABridge のスクリプトが bridge という名前の独自のディレクトリーに入れられているだけです。FABridge のライブラリー・ファイルの場所は環境に依存します。ここでは Mac OS X で Flex Builder 3 Professional を使っているため、ライブラリー・ファイルは install_root/sdks/frameworks/3.0.0/javascript/fabridge/ の中にあります。
これで適切なアーキテクチャーを構成できたので、HTML/JavaScript の側と ActionScript の側の両方でスケルトンの作成を始めることができます。リスト 3 のコードを使って HTML/JavaScript のスケルトンを作成します。
リスト 3. HTML/JavaScript のスケルトン
<html> <head> <title>FABridge Tutorial</title> <script type="text/javascript" src="bridge/FABridge.js"></script> <script type="text/javascript"> // ... </script> </head> <body> </body> </html> |
これを見るとわかるように、FABridge の JavaScript ライブラリーをコードで指定するだけで、FABridge の機能を即座にすべて利用できるようになります。次に、リスト 4 のコードを使って ActionScript 側で FABridge を実装します。
リスト 4. アプリケーションのスケルトン
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:bridge="bridge.*"
layout="absolute"
width="300"
height="142">
<bridge:FABridge bridgeName="flex" />
<mx:TextInput x="70" y="54" id="txt_test" text="FABridge rocks!"/>
</mx:Application>
|
このコードの方が、先ほどのコードよりもなじみが薄く思えるかもしれません。txt_test という ID と FABridge rocks! というデフォルト値を持つ 1 つのテキスト入力コントロールを定義することで、UI は簡潔で単純なものに保たれています。bridge という名前空間が定義されており、bridge ディレクトリーの中のすべてのクラスがインポートされています。最後に、この Flex アプリケーションには、FABridge がこのアプリケーションにアクセスするために使用する名前、flex が与えられています。この Flex コードを正常に動作する SWF 文書にコンパイルするためには、Flex 3 SDK の mxmlc ユーティリティーを使います。最も基本的なコンパイル・コマンドをリスト 5 に示します。
リスト 5. MXML をコンパイルする
path_to_flex_bin_folder/mxmlcpath_to_mxml file |
リスト 5 のコマンドによってソース・ファイルがコンパイルされ、同じディレクトリーの中にある MXML と同じファイル名を持つ SWF ファイルが出力されます。コンパイルが成功すると、出力された SWF を HTML ファイルに取り込むことができます (リスト 6)。
リスト 6. 出力された SWF ファイルにリンクする
<embed src=”main.swf” /> |
注意: リスト 6 のコードは FABridge の説明に集中できるように意図的に簡単にしてあります。特定の環境をターゲットにするのでない限り (リスト 6 は Mozilla をターゲットにしています)、オブジェクト・タグや他のロード・スクリプトなどの形で、もっと情報を追加する必要があります。
すべてがうまくいったとすると、このアプリケーションは図 1 のように表示されるはずです。
図 1. サンプル・アプリケーション
これで、Flex アプリケーションをコンパイルし、それを HTML コンテナーにリンクすることができましたので、皆さんにとって最初の FABridge 関数を呼び出し、この Flex アプリケーションへの参照を取得します。リスト 7 のコードを使って、HTML のスケルトン・ファイルの中にある空の <script> タグの中を埋めていきます。
リスト 7. Flex アプリケーションへの参照を取得する
// global variable, holds reference to the Flex application
var flexApp;
var initCallback = function() {
flexApp = FABridge.flex.root();
return;
}
// register the callback to load reference to the Flex app
FABridge.addInitializationCallback( "flex", initCallback );
|
リスト 7 のコードはまず、JavaScript のグローバル変数を定義します。この変数は、FABridge が Flex アプリケーションへの参照を取得した際に、その参照を保持するためのものです。続いて、このグローバル変数の値を設定するコールバック関数が定義されており、この関数は、FABridge の addInitializationCallback() メソッドによって呼び出されます。このコードを使うにあたってのポイントは、Flex アプリケーションの中で構成した FABridge の名前と一致させるということだけです。それ以降は、ActionScript のあらゆる機能を JavaScript コードから利用できるようになります。
これで Flex アプリケーションへのグローバル参照を取得できたので、FABridge が提供する一連のインターフェースを使って ActionScript オブジェクトにアクセスすることができます。ActionScript の世界では通常、object.id のようなドット表記を使ってオブジェクトにアクセスします。しかし FABridge では ActionScript オブジェクトをドット表記で公開するのではなく、これらのオブジェクトを関数呼び出しによって利用できるようにしています。最初は少し変わった方法に思えるかもしれませんが、従うべきテンプレートさえ把握していれば問題ありません。ActionScript で従来は object.id と表記されていたオブジェクトは、今度は object.getId() という形でアクセスされます。これは例を見るとよくわかります。リスト 8 のコードを HTML のスケルトンに入力して試してみてください。
リスト 8. ID によってActionScript オブジェクトを取得する
// get the text input control var txt = flexApp.getTxt_test(); |
txt という変数は、txt_test という ID を持つテキスト入力コントロールを表す、Flex アプリケーションのオブジェクトです。これを見ると、ID によって他の ActionScript オブジェクトにアクセスするためにはどんなテンプレートに従う必要があるのかがわかります。この宣言は Flex アプリケーションへのグローバル参照で始まり、次にメソッド呼び出しがあります (このメソッド名は必ず get ストリングで始まり、その後にターゲット・オブジェクトの ID が続きます)。この宣言では ID の名前が大文字で始まる必要があることに注目してください。
ActionScript オブジェクトのプロパティーの取得と設定のプロセスは、たった今使用したプロセスと似ています。ここでもテキスト入力コントロールを操作する例を使うことにし、リスト 9 のコードを使って text プロパティーを取得して設定します。
リスト 9. ActionScript のプロパティーを取得して設定する
alert( "old: " + txt.getText() ); txt.setText( "Reset!" ); alert( "new: " + txt.getText() ); |
リスト 9 のコードはまず、Flex アプリケーションのテキスト入力コントロールが持つ元々の値をアラートとして表示します。先ほど説明したテンプレートに従うと、関数呼び出しによって text プロパティーを取得すること、その前には get ストリングが付加されること、そしてプロパティーの名前がラクダ記法で付けられることがわかります。set() メソッドも同じプロセスを使いますが、こちらはオブジェクトの新しい値を構成するために使われるパラメーターを受け付けます。リスト 9 のコードを実行すると、図 2 のような画面が表示されるはずです。
図 2. ActionScript オブジェクトのプロパティーを設定する
今度は、最も操作が容易な部分、つまり ActionScript オブジェクト・メソッドの呼び出しに移りましょう。このプロセスでは、皆さんが何か特別なことを考慮する必要はありません。JavaScript コードの中での ActionScript オブジェクト・メソッドの使い方は、ActionScript コードの中での使い方とまったく同じです。リスト 10 のコードは、テキスト入力コントロールのメソッドを呼び出す方法を示しています。
リスト 10. ActionScript メソッドを呼び出す
txt.setVisible( false ); |
リスト 10 のコードによって、Flex アプリケーションの中のテキスト入力コントロールは見えなくなります。ただしこのオブジェクトを参照したり操作したりすることは相変わらず可能であり、物理的に見えないということにすぎません。ActionScript の世界と JavaScript の世界の間で、メソッドの呼び出し方法に関しては何も変わることはありません。
FABridge のさらに強力な機能の 1 つとして、JavaScript コードと ActionScript コードの間で関数を渡すことができるということが挙げられます。リスト 11 のコードをよく見てください。ここでは Flex でのテキスト入力の値を HTML/JavaScript 側の <div> に動的にコピーしています。
リスト 11. 関数を渡す
// define a function used as a callback to JavaScript
var txtCallback = function( event ) {
// get the object which fired the event
var swf_source = event.getTarget();
document.getElementById( "copy" ).innerHTML = swf_source.getText();
return;
}
txt.addEventListener( "change", txtCallback );
|
リスト 11 のコードは、Flex アプリケーションのテキスト入力コントロールの値が変化するたびに呼び出される JavaScript のコールバック関数です。値が変化すると、その値は ID のコピーによって <div> タグにコピーされます。この種の機能は、特に Ajax コンテンツと Flex コンテンツの間で何らかの統合作業をしようとする際には、非常に強力な働きをします。どちらの環境もイベントに大きく依存しているため、両方の環境を協調動作させられることが非常に重要です。
この記事で説明する最後の機能が、例外の処理です。デフォルトでは、JavaScript コードの中で try...catch ブロックを使う際には少なくともエラー・コードにアクセスできるはずであり、そうすればそのエラー・コードをオンライン資料で調べて、ActionScript のエラーを見つけられるはずです。この方法でも悪くはありませんが、開発を行う際には、できるだけ多くの情報に、前もってアクセスできることが望ましくなります。FABridge を利用する場合、この情報は、デバッグ機能を持つ Flash Player 9 をインストールするだけで簡単に得ることができます。デバッグ機能をインストールすると、行番号やファイル名、エラー・タイプ、スタック・トレースなどにアクセスすることができます。この一例をリスト 12 のコードを使って見てみましょう。
リスト 12. 例外の処理
try {
alert( flexApp.throwsAnError() );
}
catch( e ) {
var msg = "";
for( var i in e ) {
msg += i + " = " + e[i];
}
alert( msg );
}
|
リスト 12 のコードによってエラーがスローされる理由は、throwsAnError() メソッドが存在しないためです。catch ブロックのコードによって図 3 のようなアラートが出力されます。
図 3. 例外データ
これを見るとわかるように、このデータの方が単なる 1 つのエラー・コードよりも遥かに有用であり、トラブルシューティングの作業がずっと少なくてすみます。JavaScript と ActionScript のように異なる技術の間で統合に関する複雑な問題を扱う場合には、こうした追加情報は非常に役立ちます。
この記事ではここまで、チュートリアルの形式で FABridge の機能を紹介してきました。今度は現実的なシナリオを使って FABridge の有用性を示すことにしましょう。先ほど触れたように、Ajax の世界と Flex の世界を統合して、両方の最も良い部分を利用できるようにする必要があります。Flex 側で特筆に値するコンポーネントの 1 つがグラフ機能です。この機能は無料のライブラリーではありませんが、クライアント・サイドの本格的なアプリケーション・プログラミングを行おうとする場合には、追加のコストに見合うだけの価値があります。ここで扱う例は、ある PHP サービスの組み合わせです。このサービスは、あるカテゴリーにおける、特定ユーザー達のメッセージの受信数を含むダミー・データを提供します。この PHP サービスから提供されるデータは Ext JS JavaScript フレームワークを使ってグリッド・コントロールの中にロードされます。さらに、その同じデータが、Flex の円グラフに対するデータ・プロバイダーとして FABridge を介して渡されます。まず、リスト 13 の PHP サービスを見てみましょう。
リスト 13. PHP サービス
<?php
$users = array();
array_push( $users, "Paul" );
array_push( $users, "Nancy" );
array_push( $users, "Ned" );
array_push( $users, "Lucy" );
$email = array();
$email[ "email" ] = array();
$email[ "totalCount" ] = count( $users );
for( $i = 0; $i < count( $users ); $i++ ) {
$tmp = array();
$tmp[ "user" ] = $users[$i];
$tmp[ "friends" ] = rand( 0, 100 );
$tmp[ "family" ] = rand( 0, 100 );
$tmp[ "spam" ] = rand( 0, 100 );
array_push( $email[ "email" ], $tmp );
}
echo json_encode( $email );
?>
|
注意: このサービスのデータはハードコーディングされており、単に概念を示すためのものにすぎません。
次に、リスト 14 を見てください。これは円グラフを生成するための MXML です。
リスト 14. Flex による円グラフ
<?xml version="1.0"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:bridge="bridge.*"
width="600"
height="800">
<bridge:FABridge bridgeName="flex" />
<mx:Script>
<![CDATA[
[Bindable]
public var email:Object;
private function displaySpam( data:Object,
field:String,
index:Number,
percentValue:Number ):String {
var temp:String= (" " + percentValue).substr(0,6);
return data.user + ": " + '\n' + "Total Spam: " + data.spam + '\n' + temp + "%";
}
]]>
</mx:Script>
<mx:Panel title="Spam E-mail">
<mx:PieChart id="chart"
height="100%"
width="100%"
paddingRight="5"
paddingLeft="5"
showDataTips="true"
dataProvider="{email}">
<mx:series>
<mx:PieSeries nameField="user"
labelPosition="callout"
field="spam"
labelFunction="displaySpam">
</mx:PieSeries>
</mx:series>
</mx:PieChart>
<mx:Legend dataProvider="{chart}"/>
</mx:Panel>
</mx:Application>
|
このコードは Adobe の資料から引用したものですが、このシナリオに合うように変更してあり、また FABridge を使うように構成してあります。ここで 1 つ着目すべき点は、email という名前の変数がバインド可能であることです。つまりこのデータ・セットに対する参照は、すべて自動的に更新されるということです。この動作は非常に有効です。なぜなら、FABridge を介してこの変数にデータを送ると、それが円グラフへのデータ・プロバイダーとして使われるからです。
このパズルの最後のピースは、リスト 15 に示す JavaScript コードです。
リスト 15. グリッドを作成し、グラフにデータを追加する
<link rel="Stylesheet"
type="text/css"
href="../global/ext-2.0.2/resources/css/ext-all.css" />
<script type="text/javascript" src="bridge/FABridge.js"></script>
<script type="text/javascript" src="../global/ext-2.0.2/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../global/ext-2.0.2/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.onReady( function() {
// global variable, holds reference to the Flex application
var flexApp;
var initCallback = function() {
flexApp = FABridge.flex.root();
// load the data store, grid, populate the pie chart from JavaScript
initUI();
return;
}
// register the callback to load reference to the Flex app
FABridge.addInitializationCallback( "flex", initCallback );
function initUI() {
// create a data store using the PHP service
var ds_email = new Ext.data.JsonStore(
{
url: "service.php",
root: "email",
fields: [ "user", "family", "friends", "spam" ]
}
);
// when the data store loads, update the pie chart
ds_email.load(
{
callback: function( r, o, s ) {
// send an array of objects over the bridge to fill in the pie chart
var arr_email = new Array();
for( var i = 0; i < r.length; i++ ) {
var tmp = new Object();
tmp.user = r[i].data.user;
tmp.family = r[i].data.family;
tmp.friends = r[i].data.friends;
tmp.spam = r[i].data.spam;
arr_email.push( tmp );
}
flexApp.setEmail( arr_email );
}
}
);
// create a populate the grid.
var grid_email = new Ext.grid.GridPanel(
{
title: "E-mail Count",
store: ds_email,
columns: [
{ header: "User", dataIndex: "user" },
{ header: "Family", dataIndex: "family" },
{ header: "Friends", dataIndex: "friends" },
{ header: "Spam", dataIndex: "spam" }
],
height: 300,
width: 450,
renderTo: "grid-email"
}
);
}
} );
</script>
|
このコードで最初に気付くことは、このコードを動作させるために必要な Ext JS リソースへのリンクがあることです。Ext のデフォルト・スタイルとデバッグ・スクリプトを指定した後、onReady ブロックが構成されています。このブロックは完全な DOM (Document Object Model) が準備されるまで実行されません。Flex アプリケーションへの参照を flexApp グローバル変数に設定するためのコードは、皆さんにもすでにおなじみのはずです。そのコールバックの後に 1 つ追加されているのが、initUI 関数の実行です。この関数は、PHP サービスを使って Ext のデータ・ストアを作成し、さらにそのデータ・ストア内のデータを使って Ext のグリッド・コントロールにデータを追加するためのものです。Ext のデータ・ストアがロードされるとデータ構造が作成され、円グラフのデータ・プロバイダーとしてバインドされるように、そのデータが FABridgeを介して渡されます。最終的な出力は図 4 のようなものになります。
図 4. 最終的な出力
グリッドの中のデータに目をとおすと、これらのデータが円グラフの中に表されているデータと対応していることがわかるはずです。これは非常に強力な概念であり、それによりもたらされる可能性を理解できるはずです。
これは FABridge の実装方法を示す現実的な例の 1 つですが、このライブラリーには他にもいくつか一般的な使い方があります。FABridge の最適な使用例のごく一部として、リモート・サービスの認証用にセキュリティー情報を同期させたり、一貫性のある方法でアプリケーションをブランド化したりパーソナライズしたりする手法などがあります。
Adobe Flex は真の潜在能力を示し始めたばかりの、素晴らしい技術です。しかし、さまざまな開発者やユーザーのあらゆる要求やニーズを 1 つの製品によって満たすことはできません。そのため、私達は柔軟性を持って、FABridge を活用した統合の可能性を探ってみることが重要です。
学ぶために
- Adobe Flex Resources には Adobe Flex に関するさまざまな資料が用意されています。
- Ext JS のサイトには Ext JS JavaScript フレームワークに関するさまざまな資料やチュートリアルが用意されています
- developerWorks の「Ajax をマスターする」シリーズの記事では、Ajax の包括的な概要を学ぶことができます。
- technology bookstore には、この記事や他の技術的な話題に関する本が豊富に取り揃えられています。
- developerWorks の Technical events and webcasts で最新情報を入手してください。
- developerWorks の Open source ゾーンをご覧ください。オープンソース技術を使った開発や、IBM 製品でオープンソース技術を使用するためのハウ・ツー情報やツール、プロジェクトの更新情報など、豊富な情報が用意されています。
製品や技術を入手するために
- Adobe Flex の製品ページを訪れてください。
- Ext JS のサイトから Ext JS JavaScript フレームワークをダウンロードしてください。
議論するために
- Flex のディスカッション・フォーラムで Flex に関する議論に参加してください。
- Ext JS のディスカッション・フォーラムで Ext に関する議論に参加してください。
- developerWorks blogs から developerWorks のコミュニティーに加わってください。
