views:

185

answers:

1

This problem has me tearing my hair out.

The Symptoms: pop ups intermittently blocked/let through from external interface and navigateToURL combinations.

The Problem: Flash (or the browser..not sure) wont let pop ups be triggered outside of a time range and/or an event duration.

The Environment: I have an app that needs to send data via zendAMF, do some processing and be sent back to the flash player. On the response, if certain conditions are met true - then trigger a pop open window. The same code that gets blocked on response, works directly from a mouse event trigger.

So i set up a basic situation: 6 buttons, calling 3 methods. 3 buttons would call the method directly (all open the window perfectly) the other three would get the value of a numeric stepper, and use setTimeout(openWinMethod, NumericStepper.value) to simulate a delayed call from the zendAMF response.

UPDATE : if i select the 'navigateToURL, no delay' button first, close that window, then try any of the other delay calls - they work. its like the browser accepts that you have clicked to open a window at some point and therefore are allowed to call from a delay then on. (firefox only)

All three using the delay would be blocked (firefox and chrome) whereas all three directly would open. Safari - as well documented, would only work on the 2 methods using navigateToURL

Of interest: the js function in the html wrapper would be called be external interface to open a window. Without a delay this worked. With a delay, the js function would be called (as verified by some alert statements) but a new window was never spawned.

There are two options i am faced with: 1 - change the process to require a user click to continue once i receive my response from the zenAMF, or 2 - find out why this is happening and fix it (preferable)

the demo can be found here: http://www.digital.leskiwis.com/as3/popup/

here is my as3 class:

    package 
    {
        import fl.controls.Button;
        import fl.controls.NumericStepper;
        import flash.display.Sprite;
        import flash.events.*;
        import flash.text.TextField;
        import flash.utils.*;
        import flash.net.*;
        import flash.external.ExternalInterface;



        public class Main extends Sprite
        {

            private var but1:Button;
            private var but2:Button;
            private var but3:Button;
            private var but4:Button;
            private var but5:Button;
            private var but6:Button;
            private var reporting:TextField;
            private var dlay:NumericStepper;
            private var url:String =  'http://www.google.com';
            private var target:String = "_blank";

            public function Main() 
            {       
                if (stage) init();
                else addEventListener(Event.ADDED_TO_STAGE, init);
            }


            private function init(e:Event = null):void 
            {
                removeEventListener(Event.ADDED_TO_STAGE, init);
                // entry point
                dlay = new NumericStepper()
                dlay.minimum = 0
                dlay.maximum = 5
                dlay.stepSize = 0.1
                addChild(dlay)

                but1 = new Button()
                but1.label = "External interface window.open, use delay"
                but1.addEventListener(MouseEvent.CLICK, onOpenDelay, false, 0, true);
                addChild(but1)
                but1.width = 300
                but1.y = 50;

                but2 = new Button()
                but2.label = "External interface window.open, no delay"
                but2.addEventListener(MouseEvent.CLICK, onOpen, false, 0, true);
                addChild(but2)
                but2.width = 300
                but2.y = 80;

                but5 = new Button()
                but5.label = "External interface JS, use delay"
                but5.addEventListener(MouseEvent.CLICK, onJSOpenDelay, false, 0, true);
                addChild(but5)
                but5.width = 300
                but5.y = 110;

                but6 = new Button()
                but6.label = "External interface JS, no delay"
                but6.addEventListener(MouseEvent.CLICK, onJSOpen, false, 0, true);
                addChild(but6)
                but6.width = 300
                but6.y = 140;

                but3 = new Button()
                but3.label = "Navigate to url, use delay"
                but3.addEventListener(MouseEvent.CLICK, onNavUrlDelay, false, 0, true);
                addChild(but3)
                but3.width = 300
                but3.y = 170;

                but4 = new Button()
                but4.label = "Navigate to url, no delay"
                but4.addEventListener(MouseEvent.CLICK, onNavUrl, false, 0, true);
                addChild(but4)
                but4.width = 300
                but4.y = 200;   

                reporting = new TextField;
                reporting.y = 230
                reporting.width = 300;
                reporting.height = 170
                addChild(reporting);

                }


                private function onOpen(e:MouseEvent = null):void {

                    ExternalInterface.call('window.open',url, 'myWin','height=700,width=900,toolbar=no,scrollbars=yes');    

                    tracer('opening window with window.open')

                }

                private function onOpenDelay(e:MouseEvent):void {

                    tracer(('opening window in ' + dlay.value + ' seconds...'))

                    setTimeout(onOpen, dlay.value * 1000)


                }

                private function onJSOpen(e:MouseEvent = null):void {

                    tracer('opening window with external js function ...')

                    var success : Boolean  = ExternalInterface.call( "openURL", url, target );

                    if (!success) tracer('pop up blocked..');

                }

                private function onJSOpenDelay(e:MouseEvent):void {

                    tracer(('opening js external in ' + dlay.value + ' seconds...'))

                    setTimeout(onJSOpen, dlay.value * 1000) 

                    //setTimeout(function():void { ExternalInterface.call( "openURL", url, target ); }, dlay.value * 1000)              

                }

                private function onNavUrl(e:MouseEvent = null):void {

                    tracer('opening with navigateToURL')

                    try {

                        navigateToURL( new URLRequest(url), '_blank');

                    } catch (e:Error) {

                        tracer("Error occurred! " + e);

                    }



                }

                private function onNavUrlDelay(e:MouseEvent):void {

                    tracer(('opening navigateToURL in ' + dlay.value + ' seconds...'))

                    setTimeout(onNavUrl, dlay.value * 1000)
                    //setTimeout(function():void { navigateToURL( new URLRequest(url), '_blank'); }, dlay.value * 1000)


                }

                private function tracer(msg:String):void {

                    trace(msg)
                    reporting.appendText(msg + '\n');

                }




        }

    }

and here is the html:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
        <head>
            <title>popup test</title>
            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

            <script script language='JavaScript' type='text/javascript'>

                function openURL( url, target )
                {
                    try
                    {
                        var popup = window.open( url, target );
                        if ( popup == null ) 
                            return false;

                        if ( window.opera ) 
                            if (!popup.opera)
                                return false;
                    }

                    catch(err)
                    {
                        alert('errr...');
                        return false;
                    }
                    return true;
                }

            </script>   

            <script type="text/javascript" src="js/swfobject.js"></script>
            <script type="text/javascript">
                var flashvars = {};
                var params = {wmode:"opaque",allowScriptAccess:"always"};
                //var params = {allowScriptAccess:"sameDomain"};
                var attributes = {};
                attributes.id = "popupTest";
                attributes.name = "popupTest";
                swfobject.embedSWF("swf/popup2.swf", "altContent", "400", "400", "9.0.0", "swf/expressInstall.swf", flashvars, params, attributes);
            </script>



        </head>
        <body>

            <div id="altContent">


            </div>

        </body>
    </html>
A: 

read this:User Interaction Requirements

you will note that under "Pop-up windows" both externalInterface and navigatetoURL are listed as responding to user interaction only. basically what you are doing will be blocked if you are running a script that is taking too long.

if you are looking to do something like this then id either use ExternalInterface call to a javascript that will call and respond to the external page information, then respond with a boolean back to the flash or open the popup anyway and have it call and respond to the external page (display an error message etc if not).

depends exactly what you are doing with the zend stuff really.

shortstick
Seems a little over the top to open a new window, only to have to close it if the condition is met false. Also, it doesnt explain why using externalInterface and navigatetoURL actions with an interaction event will make all subsequent calls available from the delayed setting.But it does look like i will have to work in another user confirmation somewhere in the process. Thanks for the link
Beans