OpenLaszloと外部の連携5

ここまででかなりまともにFlashにデータを送信できるようになった訳ですが、実はまだonvalイベントが全然動いてなかったり。

OpenLaszloではタグで定義された属性は値が変更されたときに"on"+属性名で名づけられたイベントが発生します。例えば今回はvalという属性なのでonvalというイベントが起きるはずです。(といってもイベントが発生するのはSetAttributeメソッドを使用した場合ですが)

onidleのタイマーで監視というのもアレですから、も使えるようにしましょう。

まず、Laszloにはlps/include/embed.jsに定義されているlzSetCanvasAttributeメソッドというのがデフォルトで提供されていて、表向きこれを使ってデータをFlashへ送信することになっています。これはリファレンスあたりをみてもらうとして。

そのlzSetCanvasAttributeから呼ばれている_lzSetCanvasAttributeメソッドを見ると、このメソッドはFlashVarsをターゲットとなるswfファイルではなくlps/include/h.swfというファイルへ送信しています。h.swfにデータを送ったはずがターゲットのFlashファイルの変数に設定される訳です。

実はFlashにはLoacalConnectionという機能があってFlash間のデータをやり取りすることが可能です。実際h.swfはlps-3.3.1-src\lps-3.3.1\lps\includes\source\history.asというActionScriptで作られていて(これはソース付きのLaszloをDLしないと見れないかも)中身はこんな感じです。

outgoing_lc  = new LocalConnection();
if (_root.__lzevent != null) {
    outgoing_lc.send(_root.__lzhistconn, "receiveEvent", _root.n, _root.v);
} else {
    outgoing_lc.send(_root.__lzhistconn, "receiveHistory", _root.h);
}

sendの第一引数は__lzhistconnの部分がFlashのユニークなIDで、これで呼び出す先を特定します。第二引数は呼び出すメソッド名です。

呼び出される側のソースはlps-3.3.1-src\lps-3.3.1\WEB-INF\lps\lfc\services\LzHistory.asに定義されています。部分的に抜き出せば

LzHistory.receiveEvent = function(n, v){
    _root.canvas[n] = v;
    _root.canvas['on' + n].sendEvent(v);
}
LzHistory.makeConnection = function () {
    var lc = new LocalConnection();
    lc.receiveEvent = function(n, v) {
        _root.LzHistory.receiveEvent(n, v);
    };

このファイルはLZXファイルがコンパイルされるときにLZXの一部として出力されるSWFファイルに組み込まれるものです。つまりターゲットのSWFファイルはこのreceiveEventメソッドを持っていてh.swfから呼び出される準備があるわけです。

注目すべきは

_root.canvas['on' + n].sendEvent(v);

ですね。これでonvalイベントが呼び出せそうです。

いくつか注意点があります。まず__lzhistconnはFlashを特定するユニークなIDでなければなりません。複数のブラウザを開けることを考えるとjavascriptでランダムなIDを作ったほうがよさそうです。それから__lzeventはnullだとreceiveEventメソッドが呼ばれないのでこれも設定する必要があります。

ってことでターゲットswfファイルとh.swfファイルを使ってデータを送信するサンプルです。

http://www.asahi-net.or.jp/~ya5m-kwbr/hash4/useFlashVarsEncodeURIUnEscapeMultiGateway.html

下のボタンを押すとh.swfが埋め込まれて、そのタグも見れるようにしました。「onidle: い」の他に、ちゃんと「onval: い」が表示されてます。

ポイントはまずユニークなIDをつくり

connuid = Math.floor(Math.random() * 10000);

それを使ってターゲットのSWFファイルを読み込みます

fo = new SWFObject("unescape_hash.lzx.swf", "lzapp", "500", "150", "6", "#FF6600");
...
fo.addVariable("__lzhistconn",connuid);

そして値を渡すときにはh.swfを読み込みます。

gw = new SWFObject("h.swf", "gw", "1", "1", "6", "#FF6600");
gw.addVariable("n", encodeURI("val"));
gw.addVariable("v", encodeURI("い"));
gw.addVariable("__lzevent",encodeURI("1"));
gw.addVariable("__lzhistconn",connuid);
gw.write("gateway");

大きさは必要ないので1とかで構いません。また変数名はnで、値はvで送信します。それから__lzeventはnullにならないように適当な値を入れておきます。最後にターゲットに設定したユニークなIDと同じものを__lzhistconnに設定したら出来上がりです。

蛇足ですがFlash Java Script Integration KitのJavaScriptFlashGateway.swfもh.swfと同じような仕組みでLocalConnectionを使ってデータを渡しています。

http://www.ark-web.jp/blog/archives/2006/02/javascriptflash_1.html

という訳でJavaScriptからOpenLaszloのFlashへデータを送信するところについてはこんなところでしょうか。

あまり長くなったので、逆のOpenLaszloのFlashからJavaScriptへというパターンはまたにします。