Flexのアプリで入力したデータをPDFの帳票にして出したい!とか、「商品説明へ」のボタンを押したら別ウィンドウで自社サイトを表示したい!というようなシチュエーションて、結構あると思います。
ポップアップを出すには、AS2の場合は「getURL」関数、AS3の場合は「navigateToURL」を使用しますが、最近AS3でnavigateToURLを使ってみたところポップアップブロックが出てきてしまい、若干イラっとしたので、調査してみました。
ひとまずネットを検索して、いろいろと情報を入手しました。ここら辺を参考にしました。
http://d.hatena.ne.jp/os0x/20070812/1186941620
http://d.hatena.ne.jp/os0x/20080212/1202825631
http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=2&postId=5221
AS3からポップアップを上げる方法は
- navigateToURLに対して、URLと"_blank"を渡す
- navigateToURLに対して、"javascript:window.open"を渡す
- ExternalInterfaceに対して、"window.open"を渡す
の3つがあるようです。また、それらの挙動は「wmode」により変わるそうです。
さらに、「wmode」は日本語入力に影響を及ぼすということです。
http://support.adobe.co.jp/faq/faq/qadoc.sv?228635+002
また通常、ポップアップブロックは、ボタンクリックなどのユーザーアクション内だと回避される場合があります。
(JavaScriptとかはそうですね)
ということで、ひとまずテスト用サンプルを作成してみました。
http://hatena.souko105.net/20090215/NavigateToURLTest.html
(4つサンプルが入っているので、重いです)
テスト項目として、以下の7つを実行できます。
- 1.navigateToURL_normal・・・ボタンクリック時に通常のnavigateToURLを実行。
- 2.navigateToURL_javascript・・・ボタンクリック時にnavigateToURLにjavascriptを渡す
- 3.externalInterface・・・ボタンクリック時にExternalInterfaceを実行
- 4.setTimeOut_navigateToURL_normal・・・ボタンクリック時に1秒待ってから通常のnavigateToURLを実行。
- 5.setTimeOut_navigateToURL_javascript・・・ボタンクリック時に1秒待ってからnavigateToURLにjavascriptを渡す
- 6.setTimeOut_externalInterface・・・ボタンクリック時に1秒待ってからExternalInterfaceを実行
- 7.日本語入力
(3,4,5は、setTimeoutで実行を遅らせて、ユーザーアクション外でポップアップ処理をするためのテストです)
上記サンプルを使用してIE6,7,FireFox3で試してみましたが、結果はものの見事にバラバラです。
IE7がかなり制約が厳しくなっており、ユーザーアクション内でもほとんどのポップアップはブロックされてしまいます。
試した中では唯一、wmode=transparentもしくはopaqueにした状態でExternalInterfaceを使用するとブロックされずにポップアップを出すことが出来ました。ただし、このwmodeの場合は日本語入力がまともに使用できないため、アプリっぽいものを作ることは出来ません。
ということで、現状ではすべてのブラウザ共通でポップアップブロックを回避する方法はないようです。
ところでなぜポップアップブロックが困るかというと、ブラウザ上部に出るメッセージをクリックしてポップアップを許可すると、一度ブラウザがリロードしてしまうからです。
Flexアプリを使用して、ある程度の画面数データを入れた後に最後入力データを使って帳票、というようなシチュエーションの場合、リロードされるとデータがなくなるので大変困ってしまいます。
ブラウザに、ポップアップがブロックされるかどうかを知る為のAPIと、ユーザーにポップアップブロック解除を確認させるダイアログを出せるAPIがあるといいのですが、ちょっと探したところではそのようなものはありませんでした。
もしこれがあれば、トップ画面で確認ダイアログを出して解除してもらえるので。。。
ということで今考えているのは、navigateToURLにレイヤーを作るJavaScriptを渡して、Flexの上のレイヤーを作ってそこにポップアップを出す方法です。
しかしながら、IE7のブロックには困ったもんです。Flash右クリックメニューの「Flash Player 10 について」までブロックしやがります。
追伸:サンプルのソース貼っときます。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" width="400" height="250"> <mx:Script> <![CDATA[ import flash.utils.setTimeout; import flash.net.navigateToURL; private var popupUrl:String ="popup.html"; public function navigateToURL_normal():void{ var request:URLRequest = new URLRequest(popupUrl); navigateToURL(request,"_blank"); } public function navigateToURL_javascript():void{ var jscommand:String = "window.open('"+popupUrl+"','_blank','height=600,width=600');"; var request:URLRequest = new URLRequest("javascript:" + jscommand + " void(0);"); navigateToURL(request,"_self"); } public function externalInterface():void{ ExternalInterface.call("window.open", popupUrl , "_blank", "height=600,width=600"); } public function setTimeOut_navigateToURL_normal():void{ setTimeout(navigateToURL_normal,1000); } public function setTimeOut_navigateToURL_javascript():void{ setTimeout(navigateToURL_javascript,1000); } public function setTimeOut_externalInterface():void{ setTimeout(externalInterface,1000); } ]]> </mx:Script> <mx:Button click="navigateToURL_normal()" label="1.navigateToURL_normal"/> <mx:Button click="navigateToURL_javascript()" label="2.navigateToURL_javascript"/> <mx:Button click="externalInterface()" label="3.externalInterface"/> <mx:Button click="setTimeOut_navigateToURL_normal()" label="4.setTimeOut_navigateToURL_normal"/> <mx:Button click="setTimeOut_navigateToURL_javascript()" label="5.setTimeOut_navigateToURL_javascript"/> <mx:Button click="setTimeOut_externalInterface()" label="6.setTimeOut_externalInterface"/> <mx:HBox> <mx:Label text="7.日本語入力"/><mx:TextInput imeMode="{IMEConversionMode.JAPANESE_HIRAGANA}"/> </mx:HBox> </mx:Application>