--- layout: old_post title: JavaScript → ActionScript なオブジェクトブリッジを作ってみた permalink: /tatsuya/show/359-javascript-actionscript ---
最近、絶賛ActionScript勉強中なのですが、どうもたまにJavaScriptを叩きたいときがある。というかActionScriptからJavaScriptのオブジェクトを触れると色々便利そうなので、オブジェクトブリッジ的な物を作ってみた。ネタ元は
ActionScript → JavaScript オブジェクトブリッジを作ってみた : IT戦記
これ。AS→JSがあるなら、JS→ASも必要だろうということで逆方向を作ってみた。
動作
こんな感じでJavaScriptのオブジェクトをActionScriptから触れる。alert("Hoge")なんかのグローバル関数は window.alert("Hoge") でOK。
以下ActionScriptで
var window:AS2JS = AS2JS.register("window"); window.alert("Alert from ActionScript!!"); //アラート表示を普通に
var document:AS2JS = AS2JS.register("document"); document.getElementById("title1").innerHTML="Hello World from ActionScript with normal"; //DOM操作も普通に var element:AS2JS = AS2JS.register("Element"); var title2:AS2JS = window.$("title2"); element.update(title2, "Hello World from ActionScript with prototype.js"); //prototype.jsを使ってのDOM操作も普通に var Comic:AS2JS = AS2JS.register("Comic = new Base('Comic')"); var comicDiv:AS2JS = window.$("comic"); comicDiv.innerHTML = String(Comic.find(3).title); //最近マイブームのJesterを使ってサーバからデータを取ってくる
デモページは今日夜作る、かも。
>追記:デモページ作った。FireFoxで動作確認中
コードも貼っておきます、まだ色々改良の余地ありですが。
ActionScript
ActionScript 1.0時代しかやったことなかったので、3.0は違和感ありあり。コード変な書き方あるかも。
package tkmr{ import flash.utils.*; import flash.external.ExternalInterface; public dynamic class AS2JS extends Proxy { private var _attributes:Array; private var _item:Array; public function AS2JS(id:String){ _attributes = new Array(); _attributes["_JSObjectID"] = id; } public static function register(generateScript:String):*{ var id:String = ExternalInterface.call("AS2JS.Register", String(generateScript)); return (new AS2JS(id)); } //private method.... public static function callJS(args:*):*{ var result:Array = ExternalInterface.call("AS2JS.Call", args); if(result[0]=="JSObject"){ var new_js:AS2JS = new AS2JS(result[1]); return new_js; }else{ return result[1]; } } override flash_proxy function getProperty(name:*):* { trace(String(name)); if(String(name)=="_JSObjectID"){ return _attributes["_JSObjectID"]; } return AS2JS.callJS([_attributes["_JSObjectID"], String(name)]); } override flash_proxy function setProperty(name:*, value:*):void { ExternalInterface.call("AS2JS.Set", _attributes["_JSObjectID"], String(name), value); } override flash_proxy function callProperty(name:*, ... args):* { args.unshift(_attributes["_JSObjectID"], String(name)); return AS2JS.callJS(args); } //Tekitou.... override flash_proxy function nextNameIndex(index:int):int { if (index == 0){ _item = new Array(); _item[0]="_JSObjectID"; } if(index < _item.length){ return index + 1; }else{ return 0; } } override flash_proxy function nextName(index:int):String { return _item[index - 1]; } override flash_proxy function nextValue(index:int):*{ return _attributes[String(_item[index - 1])]; } } }
JavaScript
オブジェクトをAS2JS.storeへためておき、ActionScriptへIDを返す
var AS2JS = { store: [], Set: function(){ var id = arguments[0]; var func = arguments[1]; AS2JS.store[id][func]=arguments[2]; }, Call: function (){ var id = arguments[0].shift(); var func = arguments[0].shift(); var obj = AS2JS.store[id]; for(var i=0; i<arguments[0].length; i++){ arguments[0][i] = arguments[0][i]["_JSObjectID"] ? AS2JS.store[arguments[0][i]["_JSObjectID"]] : arguments[0][i]; } var result = typeof(obj[func])=="function" ? obj[func].apply(obj, arguments[0]) : obj[func]; if(typeof(result)=="string" || typeof(result)=="number" || typeof(result)=="undefined"){ return [typeof(result), result]; }else{ var new_id = AS2JS.store.push(result); return ["JSObject", (new_id - 1)]; } }, Register: function (generateScript){ var id = AS2JS.store.push(eval(generateScript)); return (id - 1); } }
あとはActionScriptのガベージコレクトのイベントをキャッチして、ActionScript → JavaScript と不要なオブジェクト削除の処理を加えたいな。ActionScriptでガベージコレクトのイベントをキャッチてどうやるんだろ。。