先日から、JavaScriptからswf中のactionscriptを呼び出す処理を作っていて、何故かFirefoxのみ、関数がコールできないという現象にハマる。
結果的に、AC_FL_RunContent()から出力されたobject,embedタグに付けられるid,nameが正しくマッチしてなかったというところにたどり着き、AC_FL_RunContent()内の処理を修正することで対応。
しかし、さらにトラップが仕掛けられてあった。
そのObject,embedで埋め込まれているswfのブロックの非表示(つまり、CSSでdisplay:none)になってると、ActionScript内の関数をコールできないのだ。
DOM的には存在してるブロックなので、単に表示されてないだけなのは別に問題ないとおもったら、そうはイカの外套膜。
例えば、まずはswfが入ってるブロックが表示されてる状態でページが表示されたとする。
このタイミングでは、swf内の関数にアクセス可能。
swf内の関数(ExternalInterface.calback()に登録された関数ね)にアクセスできたのを確認して、swfが含まれるブロックを、display:noneしてやると、あら不思議。その状態では、swf内の関数にアクセスできないのだ。
これは明らかにブラウザの挙動がおかしいと思う。
だって、display:noneは単に見た目の問題で、DOM的には存在してるから。
まぁ、でもブラウザがそうなってるんだったら、我々下僕はそれに従うしかない。
ActionScriptとJavaScriptで相互に関数をコールできるのは、両方のオブジェクトが存在するhtml中において大変便利。
しかし、罠が多いので気をつける必要がある。
以下の2点に気をつけるべし。
【問題1】マクロメディアのデフォルトのAC_RunActiveContent.jsを使ったAC_FL_RunContentにてObject/Embedを出力すると、ID,Nameの都合で、FirefoxがExternalInterface.callback()で登録された関数にアクセスできない。
【対策】AC_RunActiveContent.jsを修正し、Objectタグには、IDを、Embedタグには、Nameを割り振るようにする。
※Objectタグに、ID,Nameの両方が付いてるとダメ
または、SWFObjectなどを用いて、Object,Embedタグを出力する。(コチラは試してないので、誰かよろしこ)
【問題2】
ExternalInterfaceにてアクセスしたいSWFが入ってるブロック要素が、display:noneにより、表示されてない場合、ActionScript側にアクセスできない(not a functionとなる)
【対策】
display:noneしない。それしかない。
しかし、最初は非表示で、どこかをクリックしたタイミングでSWFが入ってるブロックを可視可(display:block)し、同時にSWF内の関数にアクセスする必要がある場合、JavaScriptのsetTimeoutなどを用いて、タイミングをズラしてアクセスする必要がある。僕が試した感じでは、ブロック要素が表示されて200msecくらい後じゃないと、アクセスできないみたい。
(この辺はswfの中身や、クライアントサイドのPCの負荷にもよると思う)
同じような問題で悩んでる人がいるとは思えないが、まぁ、1人でも2人でも参考になれば。