akihiro kamijo: March 2006 Archives

« February 2006 | Main | April 2006 »

March 28, 2006

live! eclipse 2006

本日 Adobe PDF&Flash テクニカルセミナーにお越しいただいた皆様、どうもありがとうございました。

さて、明日 3/29 の午後6時から Live! Eclipse2006 による日食の中継があります。例によって一部 FMS (Flash Media Server) による配信も行われる予定です。今回は中継点が3箇所あるので、日食が3回見れるかもしれません。晴天率の高い地域からの中継ですし楽しみです。

中継サイトはこちらです。

Posted by ackie at 10:54 PM | Comments (1)

March 24, 2006

String と正規表現

String クラス (livedocs@lab) のいくつかのメソッドは正規表現と一緒に使うことができます。文字列の中から特定の表現を抜き出したり置き換えたりしたいときにはなかなか便利です。

では、早速具体的なメソッドを見ていきましょう。

split() メソッド

split() メソッドは引数に渡されたパターンを区切りとして文字列を分解します。結果は配列に格納されます。

vvar myStr:String = "Happy like a honeybee";
trace(myStr.split("a"));
// H,ppy like , honeybee が出力される

引数には正規表現も使えます。空白文字を区切りに指定してみます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /\s+/;
trace(myStr.split(myPattern));
// Happy,like,a,honeybee が出力される

正規表現に括弧が含まれると括弧内に一致した箇所も出力に含まれます。先ほどの正規表現に括弧を足してみます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\s+)/;
trace(myStr.split(myPattern));
// Happy, ,like, ,a, ,honeybee が出力される

オプションとして返す要素の最大数を指定できます。これは2つ目の引数に指定します。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\s+)/;
trace(myStr.split(myPattern, 3));
// Happy, ,like が出力される

select() メソッド

select() メソッドは引数のパターンに一致する箇所があればその先頭文字のインデックスを返します。見つからなかった場合は -1 を返します。パターンには String 型または RegExp 型のオブジェクトを使用できます。

var myStr:String = "Happy like a honeybee";
trace(myStr.search("li")); // 6 が出力される
 
var myPattern:RegExp = /(\w)\1/;
trace(myStr.search(myPattern)); // 2 が出力される

select() メソッドでは最初に見つかった箇所しか知ることができません。g フラグや lastIndex は無視されます。

ちなみに indexOf() メソッドと lastIndexOf() メソッドを使えば検索開始位置を指定できます。ただし、正規表現は使用できません。

var myStr:String = "Happy like a honeybee";
// 6 文字目から後ろへ検索する
trace(myStr.indexOf("a", 5)); // 11 が出力される
// 6 文字目から前へ検索する
trace(myStr.lastIndexOf("p", 5));; // 3 が出力される

lastIndexOf() はインデックス値を指定すると、指定された箇所から前に検索を行います。上の例では4文字目の p と先に一致するため返り値は 3 になっています。

match() メソッド

match() メソッドは引数のパターンに一致した箇所を配列として返します。パターンには文字列または正規表現を使用できます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/;
trace(myStr.match(myPattern)); // pp が出力される

上記のように正規表現に g フラグが無い場合最初に一致した箇所のみが返されますが、g フラグを付けると文字列全体を検索します。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/g;
trace(myStr.match(myPattern)); // pp,ee が出力される

いずれの場合も lastIndex の値は使用されません。

replace() メソッド

replace() メソッドは1つ目の引数で指定されたパターンに一致した箇所を2つ目の引数を使って置き換えます。置き換え済の文字列が戻り値になります。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/g;
trace(myStr.replace(myPattern, "xx")); 
// Haxxy like a honeybxx が出力される

パターンには文字列と正規表現が使えます。オリジナルの文字列は変更されません。

でも、これだといつも置き換えに使う文字列は同じものになってしまいますね。そのため、第2引数には関数を指定することもできるようになっています。関数は一致するごとに呼ばれ、最初の引数に一致した部分、最後から2番目の引数に一致した箇所の先頭のインデックス、最後の引数に元の文字列が渡されます。

var myStr:String = "Happy like a honeybee";
trace(myStr.replace("li", myFunc));
// Happy li6ke a honeybee が出力される
 
private function myFunc(...args):String {
  trace(args);
  // li,6,Happy like a honeybee が出力される
  return args[0] + args[1];
}

パターンに正規表現を使用した場合、正規表現が括弧を含むとそれぞれの括弧に一致した箇所も2つ目以降の引数として括弧の数だけ渡されます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/g;
trace(myStr.replace(myPattern, myFunc));
// Hapy like a honeybe が出力される
 
private function myFunc(...args):String {
  trace(args);
  // ee,e,19,Happy like a honeybee が出力される
  return args[1];
}

Posted by ackie at 05:18 PM | Comments (0)

March 23, 2006

AS3 と正規表現

AS3 では ECMAScript3 に定義されている正規表現が使用できます。これで文字列の操作もずいぶん便利になりました。おかげで前より普通にスクリプト言語らしくなった気がします。

RegExp クラス

正規表現は「数字だけから成る文字列」とか「<p> と </p> で囲まれた文字列」のようなパターンを記述するための表現です。ECMAScript3 の仕様では、先に挙げた2つの例であればそれぞれ \d+ と <p>.*</p> といった記述ができます。

これらの正規表現を AS3 で使用するには RegExp クラス (livedocs@lab) を使用します。対象となる具体的なパターンを / (スラッシュ)で挟むと RegExp のインスタンスの初期化ができます。

var myPattern1:RegExp = /\d+/;
var myPattern2:RegExp = /<p>.*</p>/g;

2行目の例ではパターンの後に g が付いています。このようにフラグを指定することも可能です。ちなみに g フラグは global の略で複数のマッチングをする際の指定になります。正規表現を使い慣れた人にはお馴染みですね。

オブジェクト指向好きならコンストラクタを使っても同様にインスタンスが生成できます。

var myPattern1:RegExp = new RegExp("\d+");
var myPattern2:RegExp = new RegExp("<p>.*</p>", "g");
 
trace(myPattern1.source); // \d+ が出力される

ちなみにインスタンスの持つパターンは source 属性から参照できます。この値は参照のみが可能です。

test() メソッド

RegExp クラスの test() メソッドは引数として渡された文字列に、あるパターンが含まれているかをチェックします。

var myStr:String = "0123456789";
var myPattern:RegExp = /12/;
var result:Boolean = myPattern.test(myStr);
trace(result); // true が出力される
trace(myPattern.lastIndex); // 3 が出力される

上の例では、myStr の2文字目と3文字目に myPattern (1と2の連続)が一致するため結果は true になっています。

また、結果が true のとき、lastIndex には一致した箇所の最後の文字のインデックス値が設定されます。

test() を呼ぶとき lastIndex 属性を使うとパターンマッチングを開始する文字を指定することができます。例えば lastIndex を 2 にすると最初の2文字はスキップされます。ただし、このとき正規表現に g フラグを設定する必要があります。

var myStr:String = "0123456789";
var myPattern:RegExp = /12/g;
myPattern.lastIndex = 2; var result:Boolean = myPattern.test(myStr); trace(result); // false が出力される

上の例は3文字目からチェックを開始するために結果が false になります。

exec() メソッド

exec() メソッドは引数の文字列内でパターンに一致した箇所の文字列を含むオブジェクトを返します。一致する箇所が無い場合の返り値は null です。

var myStr:String = "Happy like a honeybee";
// 小文字の a から z のみが連続するパターン
var myPattern:RegExp = /[a-z]+/;
var result:Object = myPattern.exec(myStr);
trace(result[0]); // appy が出力される
trace(result.index); // 1 が出力される
trace(result.input); // Happy like a honeybee が出力される

結果のオブジェクトには一致した文字列の他に、一致した箇所の先頭を示す index 属性と渡された文字列を保持する input 属性があります。

パターンが括弧を含む場合、結果のオブジェクトはそれぞれの括弧に一致した箇所も返します。配列の2番目以降のアイテムが括弧の登場する順番に一致した値になります。次の例では同じ文字が2回以上続くパターンを括弧を一つ使い指定しています。このため結果には (1) 一致した箇所全体と (2) 括弧の中と一致した部分が含まれます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/;
var result:Object = myPattern.exec(myStr);
trace(result[0]); // pp が出力される
trace(result[1]); // p が出力される - (\w) に一致した文字列
trace(result.index); // 2 が出力される
trace(result.input); // Happy like a honeybee が出力される

exec() メソッドも test() と同様に g フラグが設定されていれば lastIndex でマッチングを開始する箇所を指定できます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/g;
myPattern.lastIndex = 5; var result:Object = myPattern.exec(myStr); trace(result[0]); // ee が出力される trace(result.index); // 19 が出力される trace(result.input); // Happy like a honeybee が出力される

一致した文字列が見つかると lastIndex 属性に一致した箇所の最後の文字のインデックス値が設定されます。これも test() と一緒です。この仕様とループを組み合わせれば、文字列の最初から一つ一つ一致する箇所を探すこともできます。

var myStr:String = "Happy like a honeybee";
var myPattern:RegExp = /(\w)\1/g;
var result:Object = myPattern.exec(myStr);
while (result != null) {
  trace (result.index + ":" + result[0]);
  result = pattern.exec(str);
}
// 以下の2行が出力される
// 2:pp
// 19:ee

上のサンプルで g フラグを忘れると無限ループになります。間違えやすいので注意しましょう。

Posted by ackie at 06:20 PM | Comments (0)

March 21, 2006

Flex2 Beta2 開始です

まずは先週の話になりますが、Flash Player 8.5 パブリックベータ が公開されました。こちらは Labs のリリースとは独立したタイミングで更新されていきます。つまり、ベータ版の Flex SDK で開発したアプリとは整合性がなくなるケースが起き得ます。ですので、主に既存のコンテンツの表示/動作確認が目的のリリースと理解して頂くのがよろしいかと思います。

また、Mactel マシン用 Flash Player 8 プレビューリリースも公開されています。こちらは 8.5 がリリースされるまでのつなぎという位置づけです。正式対応は Flash Player 8.5 正式版までお待ちください。

さて、Adobe Labs では Flex2 パブリックベータ2がリリースされました。今回から Flex Enterprise services 2 が Flex Data Services 2 (FDS2)と名前が変わりました。その他、今までの記事に関連する主な変更点は以下のとおりです。

  • applicationDomain 属性が URLRequest クラスから削除されました。代わりに LoaderContext という新しいクラスが導入され、こちらの同名の属性を使用するようになります。LoaderContext のインスタンスは load() メソッドの第2引数にオプションとして指定できます。例えば myLoader.load(myURLRequest, myLoaderContext) のような使い方です。LoaderContext クラスついては別途記事を書くつもりですが、まだ最終仕様が決定されていないようですので少し先になるかもです。
  • メインの swf ファイルに自身の読み込み完了のイベントを処理するハンドラを登録できるようになりました。loaderInfo.addEventListener() を使用して登録します。
  • Stage クラスの frameRate 属性や addChild 等いくつかのメソッドが、最初に stage に読み込まれた swf からのアクセスのみに制限されるようになりました。ちなみに frameRate は書き込み可能な属性です。
  • securityDomain 間のイベント伝達やメソッド呼び出しが厳しく制限されるようになりました。影響箇所が多いため詳細は都度機会がある毎に触れたいと思います。

ベータ2から Flex Builder 2 にはチャートコンポーネントが含まれています。Flex Data Services 2 は従来どおり charts.swc を自分で配置する必要があります。

Posted by ackie at 03:00 PM | Comments (0)

March 12, 2006

Electrical Fantasista 2006

今日は Electrical Fantasista 2006 の Flash Fantasista Artist Talk に行ってきた話です。

展示物については ITmedia さんの記事に詳しく紹介されています。ちょっと見るだけでなくしばらく一緒にごろごろしているとだんだんと見えてくるような種類の展示です。Origami 登場の噂もあったのですが、残念ながら今日はまだありませんでした。14日(火)まで開催しているそうですので、運の良い人は明日以降見れるかもです。

肝心の Talk は前座の西村さん(右の写真)の Flash8 紹介に続いて、森山さん、程さん、今井さん、近森さんのお仕事のお話を聞くことができました。先日の @IT リッチクライアントセミナーのトークのテーマだったエクスペリエンスデザインとメディアアートって結構近い話のようなのに、どうしてこんなに違った空間になるんだろうとか、やっぱり作ること自体が目的化する罠ってあるなあとかいうことが引っかかった3時間でした。

Adobe と Macromedia の合併話をまだ知らない人がいたのはともかく、Flash8 の新機能もまだまだ伝えられていないのだなあということを改めて反省しております。

Posted by ackie at 01:54 AM | Comments (0)

March 09, 2006

Flex & Ajax アップデート

先日 Adobe Labs にて、Ajax 関連の発表が2件行われました。

一つ目は、FABridge (Flex Ajax Bridge) と呼ばれる Flex2 アプリケーションと Ajax アプリケーションを連携させるためのライブラリです。これを使うと、Ajax 側から Flex コンポーネントのメソッドを呼び出したり、あるいは逆に Flex 側から Ajax の関数を呼び出したりが簡単にできます。つまり、Ajax アプリケーションに Flex アプリケーションを埋め込むといったことが気軽にできるようになるわけです。現在はまだアルファ前の段階ということで、これからまだ変更などは多々ありそうですが、興味のある方は是非試してみてください。

もう一つは、ACFDS (Ajax Client for Flex Data Services) というちょっと長ったらしい名前を持つライブラリです。これは Ajax アプリケーションから Flex Data Service を利用するためのものです。例えば、パブリッシャー/サブスクライバー型メッセージング機能やリアルタイムデータシェアリング等の機能が Ajax アプリケーションからも使用できるようになります。こちらはまだダウンロードできるサンプルは提供されていません。現時点では年末を目処にフリーで提供できることを目指すという状況のようです。

Posted by ackie at 09:59 PM | Comments (0)

March 08, 2006

ApplicationDomain

Loader オブジェクトで (URLLoader ではありません) swf ファイルをロードするとき、ロード先のアプリケーションドメインを指定することができます。

アプリケーションドメインはクラス定義の単位になるため、実行時に swf をロードすることで動的にクラス定義を追加するといった使い方ができます。また、複数のアプリケーションドメインを持つことができるため、同じクラスの異なるバージョンを同時にアプリ内で使うことも可能です。

それでは、アプリケーションドメインの使い方について詳しく見ていきましょう。

アプリケーションドメインの階層

通常、アプリケーションドメインは階層構造をなしています。一番親のアプリケーションドメインはシステムドメインと呼ばれ、Flash Player 上に一つだけ存在します。その他のアプリケーションドメインはシステムドメインの子孫ということになります。

各アプリケーションドメインにはクラス定義が含まれますが、子のドメインは親のドメインのクラス定義を引き継ぎます。従って、下の階層になるほど多くのクラスが利用可能なわけです。

アプリケーションドメインは ApplicationDomain クラス (livedocs@lab) のインスタンスとして実装されています。ApplicationDomain のインスタンスを生成する際、親ドメインをコンストラクタの引数として指定することができます。何も指定されなければシステムドメインが親ドメインになります。

// システムドメイン下に新しいアプリケーションドメインを作成
new ApplicationDomain();
// 現在のドメイン下に新しいアプリケーションドメインを作成
new ApplicationDomain(ApplicationDomain.currentDomain);

ApplicationDomain.currentDomain は現在アプリケーションが実行されているドメインを示す静的変数です。

ロード時のアプリケーションドメインの指定

swf ファイルロード時に読込先のアプリケーションドメインを指定するには URLRequest オブジェクトの applicationDomain 属性を使用します。

var myReq:URLRequest = new URLRequest();
myReq.url = "myClasses.swf";
// 現在のドメインを設定する
myReq.applicationDomain = ApplicationDomain.currentDomain;
var myLoader:Loader = new Loader();
myLoader.load(myReq);

読み込み後は Loader の loadeeInfo 属性から myLoader.loadeeInfo.applicationDomain のようにして読み込まれた swf が属するアプリケーションドメインにアクセスすることができます。

読み込まれた側から自身の属するアプリケーションドメインを取得するには、読み込まれた swf 内のルート DisplayObject の loaderInfo から参照します。roo 以外の DisplayObject からであれば this.root.loaderInfo.applicationDomain で取得できます。

getClass() メソッドによる動的なクラス定義の利用

さて、getClass() メソッドを使うとアプリケーションドメインからクラス定義を取得することができます。つまり、アプリケーションドメインに新しく swf ファイルを読み込むことで、利用できるクラス定義を動的に追加できるわけです。

ただし既存のクラス定義を、新しくロードした swf 内の定義で上書きすることはできません。新規に見つかったクラス定義のみが追加されます。

var myReq:URLRequest = new URLRequest();
myReq.url = "myClasses.swf";
// 現在のドメインに読み込むよう指定
myReq.applicationDomain = ApplicationDomain.currentDomain;
var myLoader:Loader = new Loader();
myLoader.addEventListener(Event.COMPLETE, completeHandler);
myLoader.load(myReq);
 
private function completeHandler(event:Event):void {
  // まず読込先のドメインを取得
  var myDomain:ApplicationDomain = myLoader.loadeeInfo.applicationDomain;
  // ドメイン内のクラス定義を取得
  var myClassRef:Class = myDomain.getClass("myClass1");
  // 定義を取得したクラスのインスタンス生成
  var foo:Object = new myClassRef();
}

上記の例ではアプリケーションを実行中のアプリケーションドメインに swf をロードしています。この場合、一旦追加されたクラス定義はそのまま残り続けます。

ですが、子のドメインに swf をロードすれば swf をアンロードすることで追加されたクラス定義もガーベッジコレクションの対象とすることができます。(もちろんロードした swf への参照がないことが条件ですが)

つまり、下のように書き換えた場合にはクラス定義の追加と削除がコントロールできるようになるわけです。

...
myReq.url = "myClasses.swf";
// 新規に子ドメインを作るよう変更
myReq.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
var myLoader:Loader = new Loader();
myLoader.addEventListener(Event.COMPLETE, completeHandler);
myLoader.load(myReq);
 
...

別ドメインへのアプリケーションのロード

アプリケーションを読み込むときにアプリケーションドメインを使い分けることで、クラス定義への依存状況に柔軟に対応することができるようになります。

例えば、システムドメイン直下に新しいアプリケーションドメインを作成した場合、現在のドメインと新規ドメインのクラス定義は独立です。すなわち、アプリケーション固有のクラス定義は共有されません。

これを利用すると、同じアプリケーションの異なるバージョンを、クラス定義の違いなどを気にすることなく同時に実行することが可能です。

var myReq:URLRequest = new URLRequest();
// 別バージョンのアプリケーションを指定
myReq.url = "v2app.swf";
// システムドメイン下に新しいアプリケーションドメインを作成
myReq.applicationDomain = new ApplicationDomain();
var myLoader:Loader = new Loader();
// 独立した新規ドメインにアプリケーションをロード
myLoader.load(myReq);

また、複数の子ドメインにアプリケーションを分割すると、子ドメイン固有のクラス定義はそれぞれ独立させながら、親ドメインを共通のクラス定義の場として管理することができます。

例として、複数のパネルを持つポータル系のアプリケーションで、個々のパネル内を独立したアプリケーションとして実装した場合を考えてみます。

// パネル内のアプリケーションを指定
myReq1.url = "panel1.swf";
// 新規に子ドメインを作成
myReq1.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
myLoader1.load(myReq);
 
// 別パネル内のアプリケーションを指定
myReq2.url = "panel2.swf";
// もう一つ子ドメインを作成
myReq2.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
myLoader2.load(myReq);

このような構造だと panel1.swf に固有のクラス定義は例えば panel2.swf のような他のパネル内のアプリケーションには影響しません。そのため、共通部分(親のアプリケーションドメイン内のクラス定義)は管理しながら、かなり自由に個別の機能を開発/管理することができそうです。

Posted by ackie at 05:48 PM | Comments (2)

March 07, 2006

navigateToURL 関数

今回は、flash.net パッケージの関数2つを紹介します。

navigateToURL() 関数

AS3 アプリケーションからもう一つブラウザのウインドウを開きたい、あるいは今 AS3 アプリケーションを実行中のウインドウを他の HTML コンテンツで置き換えたいというときには navigateToURL() 関数 (livedocs@lab) を使います。以下が関数の定義です。

public function navigateToURL(request:URLRequest, window:String = null):void

1つめの引数には URLRequest オブジェクトを指定します。このオブジェクトには URLLoader クラスの記事内の例と同様に、リクエスト先の URL やヘッダ情報それから送信するデータと送信方法等を指定します。

2つ目の引数にはリクエストの結果を受信するウインドウを指定します。こちらはデフォルト値が定義されているため省略が可能です。省略した場合には新しいウインドウが開かれます。つまり "_blank" を指定したのと同等の結果になります。

下のサンプルでは navigateToURL() の第二引数を "_self" にしていますので AS3 アプリケーションを実行しているウインドウ自身のコンテンツを置き換えます。

import flash.net.navigateToURL;
 
var myVars:URLVariables = new URLVariables();
myVars.currentTime = new Date().getTime();
myVars.city = "Tokyo";
 
var myReq:URLRequest = new URLRequest();
myReq.url = "http://www.sample.com/weather";
myReq.data = myVars;
 
// 現在のウインドウのコンテンツを置き換える
navigateToURL(myReq, "_self");

navigateToURL() 関数を使うにはクラスを使用するときと同じ様にインポートします。

sendToURL() 関数

AS3 アプリケーションからサーバーにデータを送りたい、けれど結果は無視したいというときには sendToURL() 関数 (livedocs@lab) を使用します。使い方は上で紹介した navigateToURL() 関数とほぼ同じです。違いは2つ目の引数がないことくらいです。

public function sendToURL(request:URLRequest):void

あまり芸がないのですが、一応サンプルも。

import flash.net.sendToURL;
 
var myVars:URLVariables = new URLVariables();
myVars.user = "foo";
myVars.data = "hello";
 
var myReq:URLRequest = new URLRequest();
myReq.url = "http://www.sample.com/post";
myReq.data = myVars;
myReq.method = URLRequestMethod.POST;
// サーバーにデータを送信
sendToURL(myReq);

Posted by ackie at 05:32 PM | Comments (0)

March 06, 2006

URLLoader クラス

外部からの XML データ等を読み込むときは URLLoader クラス (livedocs@lab) を使うことができます。

以前紹介した Loader クラスは swf やイメージを主に表示目的でロードするためのクラスでした。Loader クラスの記事を書いていた頃は URLLoader は Loader のサブクラスでしたが、今は独立したクラスになっています。

URLRequest クラスとデータ要求の送信

URLLoader を使ってサーバーにリクエストを送るには、まず URLRequest クラス (livedocs@lab) のインスタンスを作ります。URLRequest のオブジェクトにはリクエスト先の URL やヘッダ情報等が指定できます。

次に、作成した URLRequest オブジェクトを引数として URLLoader の load() メソッドを呼び出します。

var myReq:URLRequest = new URLRequest();
myReq.url = "foo.xml";  // コンストラクタの引数としても指定可能
var myLoader:URLLoader = new URLLoader();
myLoader.load(myReq);

HTTP ヘッダに情報を追加する場合は、項目ごとに URLRequestHeader クラス (livedocs@lab) のインスタンスを作成し、 URLRequestHeader オブジェクトの requestHeaders 属性(Array 型です)に追加します。

var myReq:URLRequest = new URLRequest("foo.xml");
var myRH:URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
myReq.requestHeaders.push(myRH);
var myLoader:URLLoader = new URLLoader();
myLoader.load(myReq);

受信したデータの処理

load() を実行してからデータの読み込み処理が終わるまで ActionScript から読み込んだデータにアクセスすることはできません。URLLoader は受信処理を完了すると complete イベントを発生させるので、 complete イベントに対するイベントハンドラ内でデータ操作を行うようにします。読み込まれたデータは URLLoader の data 属性からアクセスすることができます。

myLoader.addEventListener(Event.COMPLETE, completeHandler);
myLoader.load(new URLRequest("foo.xml"));
 
private function completeHandler(event:Event):void {
  trace(myLoader.data);
}

参考までに、complete を含め URLLoader がディスパッチするイベントには以下のものがあります。

complete      : ダウンロード処理が完了した
httpStatus    : 返信の HTTP ステータスが判明した
ioError       : IO エラーによりロード処理が中断した
open          : ロード処理が開始した
progress      : ロードを実行中
securityError : 許可されない通信を行おうとした

さて、読み込まれただデータは DataFormat クラス (livedocs@lab) に定義されている3種類のフォーマットのどれかです。URLLoader オブジェクトの dataFormat 属性から値を知ることができます。

  • DataFormat.TEXT : String 型 (livedocs@lab) の文字列
  • DataFormat.BINARY : ByteArray 型 (livedocs@lab) のバイナリデータ
  • DataFormat.VARIABLES : URL エンコードされたフォーム変数を持つ URLVariables オブジェクト

3つ目の DataFormat.VARIABLES フォーマットの際に使用される URLVariables クラス (livedocs@lab) からは名前と値がペアになった連想配列として値を取り出すことができます。

データの送信

サーバにデータを送信する際も上記3種類のフォーマットが使用できます。送信するデータを URLRequest オブジェクトの data 属性にセットすれば、リクエスト時にセットしたデータが送られます。

下の例では変数&値のペアを定義した URLVariables オブジェクトを POST で送信しています。この場合、データは x-www-form-urlencoded フォーマットにエンコードされて送られます。

var myVars:URLVariables = new URLVariables();
myVars.userID = "guest";
myVars.password = "foo";
myReq.data = myVars;
myReq.url = "ww.sample.com/foo.jsp";
myReq.method = URLRequestMethod.POST;
myLoader.load(myReq);

送信方法 (GET/POST)は URLRequest オブジェクトの method 属性に URLRequestMethod クラス (livedocs@lab) に定義された値を使って指定します。デフォルトは GET です。POST する場合はデータの MIME タイプを URLRequest オブジェクトの contentType 属性に設定することができます。 ByteArray オブジェクトを送信する場合は GET は使用できません。

Posted by ackie at 05:42 PM | Comments (0)

March 03, 2006

Flex1.5 HotFix

先日 IE6 の仕様変更 (詳細はこちら) がありました。この IE6 の変更により Flash Player を含む ActiveX コントロールでコンテンツを HTML ページ内に表示する際にユーザが明示的に確認を求められるケースがあります。今回の HotFix はそれに対応したもので、Flex が生成する HTML ページの記述が IE の変更に対応したものになります。詳細およびダウンロードはこちらのページ(英文です)をご覧ください。日本語のページも近々できることと思います。

なお、本日 @IT リッチクライアントセミナーにお越しいただいた皆様やご協力いただいた皆様、どうもありがとうございました。この blog でもそろそろ Flex ネタも取り上げなくちゃですね。

Posted by ackie at 09:29 PM | Comments (0)

March 02, 2006

QName クラスの続き

もう少しだけ QName の話題を続けます。

QName と child() メソッド

child() や attribute() を呼ぶときに修飾名を使う必要があれば QName を引数として渡すことができます。以下のサンプルを使って具体的に見てみましょう。

var myOrder:XML =
<foo:order xmlns:foo="http://www.sample.com/foo/">
  <foo:item bar:id="1" quantity="1" xmlns:bar="http://www.sample.com/bar/">
    <name>fresh burger</name>
    <price>300</price>
  </foo:item>
</foo:order>;

まず foo:item に相当する QName のオブジェクトを作成します。これを引数にすることで child() を使っても foo:item を指定できるようになります。

var fooNS:Namespace = myOrder.namespace("foo");
var fooItemQN:QName = new QName(fooNS, "item");
trace(myOrder.child(fooItemQN).name());
// http://www.sample.com/foo/::item が出力される

ちなみに child() の箇所は以下のように書き換えることもできます。

// 以下の2行は同じオブジェクトを指す
myOrder.child(fooItemQN);
myOrder.fooNS::["item"];

QName と attribute() メソッド

attribute() も child() と同様に QName を使って修飾名を指定することができます。

var barNS:Namespace = myOrder.child(0).namespace("bar");
var barIdQN:QName = new QName(barNS, "id");
trace(myOrder.child(fooItemQN).attribute(barIdQN));
// 1 が出力される

attribute() も代わりになる書き方が幾つかあります。どれがお好みですか?

// 以下の3行は同じ属性を指す
trace(myOrder.child(fooItemQN).attribute(barIdQN));
trace(myOrder.fooNS::["item"].@barNS::["id"]);
trace(myOrder.fooNS::["item"].barNS::["@id"]);

Posted by ackie at 05:13 PM | Comments (0)

March 01, 2006

QName クラス

QName クラス

QName クラス (livedocs@lab) は XML の要素や属性の修飾名を扱うために使われます。QName のインスタンスは uri と localName という属性を持っています。それぞれ uri 属性は名前空間修飾子 localName 属性はローカル名の値を持ちます。

var qn:QName = new QName("www.sample.com/uri/", "myElementName");
trace(qn.uri);
// www.sample.com/uri/ が出力される
trace(qn.localName);
// myElementName が出力される

name() メソッドと localName() メソッド

name() メソッドは XML オブジェクト(またはXMLList オブジェクト)の修飾名を、localName() メソッドはローカル名を取得するのに使用します。対象が XMLList オブジェクトの場合はリスト内に一つだけアイテムを持つオブジェクトである必要があります。

var myOrder:XML =
<foo:order xmlns:foo="http://www.sample.com/foo/">
  <foo:item id="1" quantity="1" xmlns="http://www.sample.com/bar/">
    <name>fresh burger</name>
    <price>300</price>
  </foo:item>
</foo:order>;
// 修飾名とローカル名を取得する
trace(myOrder.child(0).name());
// http://www.sample.com/foo/::item が出力される
trace(myOrder.child(0).localName());
// item が出力される

name() メソッドの返す型は QName のため localName 属性を使用してもローカル名を取得できます。また名前空間の URI は uri 属性から取得できます。一方、プレフィックス(この場合は foo)情報は QName は持っていません。プレフィックスが必要な場合は namespace() メソッドを使用します。

trace(myOrder.child(0).namespace().prefix);
// foo が出力される
trace(myOrder.child(0).namespace().uri);
// http://www.sample.com/foo/ が出力される
trace(myOrder.child(0).name().uri);
// http://www.sample.com/foo/ が出力される
trace(myOrder.child(0).name().localName);
// item が出力される
trace(myOrder.child(0).localName());
// item が出力される

Qname および Namespace の uri 属性はプレフィックスがなくてもデフォルトの名前空間に属するオブジェクトには値が設定されます。例えば foo:item ノードではデフォルトの名前空間が宣言されています。そのため name ノードの QName を調べると以下のようになります。

trace(myOrder.child(0).child(0).name());
// http://www.sample.com/bar/::name が出力される

関連する名前空間がない場合 uri 属性は空文字になります。

setName() メソッドとsetLocalName() メソッド

setLocalName() メソッドはローカル名のみを引数の文字列と置き換えます。

trace(myOrder.child(0).name());
// http://www.sample.com/foo/::order が出力される
myOrder.child(0).setLocalName("purchase");
trace(myOrder.child(0).name());
// http://www.sample.com/foo/::purchase が出力される

setName() メソッドは引数が文字列の場合修飾名を置き換えますが引数はローカル名として扱われます。

myOrder.child(0).setName("purchase");
trace(myOrder.child(0).name());
// purchase が出力される

setName() に引数としてQName オブジェクトを渡すと名前空間の宣言付きで置き換えることができます。

var myQN:QName = new QName("http://www.sample.com/baz/", "title");
myOrder.child(0).child(0).setName(myQN);
trace(myOrder.child(0).child(0).toXMLString());
// <aaa:title xmlns:aaa="http://www.sample.com/baz/">fresh burger</aaa:title> が出力の変更分

aaa は自動的に振られたプレフィックスです。

Posted by ackie at 05:39 PM | Comments (0)