JMark
JMark

Reputation: 171

Flash steals browser focus

I have a flash app in my page, and when a user interacts with the flash app, the browser/html/javascript stops receiving keyboard input.

For example, in Firefox control-t no longer opens a new tab.

However, if I click on part of the page that isn't flash, the browser starts receiving these events again.

Is there anyway to programatically (either through flash or javascript) to return focus to the browser?

After the user clicks a button in flash, I have the flash executing a javascript callback, so I've tried giving focus to a form field (and to the body) through javascript, but that approach doesn't seem to be working.

A perhaps more concrete example is Youtube. They also have this problem. When I click the play/pause button, or adjust the volume, I would expect my browser keyboard controls to still work, but they don't, I have to click somewhere on the page outside the movie area. This is the exact problem I'm trying to solve.

Upvotes: 17

Views: 7937

Answers (6)

distill
distill

Reputation: 61

There's a solution below in case somebody needs it. For me, that works quite nicely. I can click around my Flash but still use all the browser keyboard functionality (the focus is shifted to the html part when clicked inside the Flash).

http://forums.adobe.com/message/3431403#3431403

Upvotes: 0

Chris Anthony
Chris Anthony

Reputation: 21

In Firefox, document.body.focus(); doesn't work. Using the same idea as Cláudio Silva's solution to this Chrome issue, the following JavaScript will work in Firefox:

document.body.tabIndex = 0;
document.body.focus();

Upvotes: 2

Emerica
Emerica

Reputation:

    <?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init();">
    <mx:Script>
        <![CDATA[
            private function init():void {
                i.setFocus();
                this.addEventListener(KeyboardEvent.KEY_UP,keyPressed);
            }

            private function keyPressed(event:KeyboardEvent):void {
                if(event.keyCode.toString()=="84" && event.ctrlKey==true)
                    ExternalInterface.call('newtab');
            }

        ]]>
    </mx:Script>
    <mx:TextInput x="23" y="268" width="256" id="i" text="Text Box"/>
</mx:Application>

<script type="text/javascript">
function newtab(e){
    document.body.focus();
    window.open('about:blank');
}
</script>    

Now, what happens with other keyboards? is 84 standard for T? I like the focus idea, but in full browser apps there is not as much room to lose the focus. The user could change the key combo as well, I don't think these is much of a complete fix for this one without flash polling the command config from the browser and then listening for the combo as we are basically doing here. I dunno.

This also just attempts to open a new window after giving focus, there is no sense to me in making the user press it twice unless they block the window like a popup. But focus is called first so, if that happens the second attempt should work. You could alert the user in a browser app if needed.

Upvotes: 0

discorax
discorax

Reputation: 1487

You can use the ExternalInterface class within Flash to call JavaScript. For example you could set up a function on an interval (Event.ENTER_FRAME for example) to call the JavaScript function that @Diodeus mentioned:

document.body.focus();

Or, an even better solution would be to add an event listener to the flash root (stage) to listen for when the mouse leaves Flash. You can set up this event to move focus to the document.body.

AS3

package {
   import flash.display.*;
   import flash.events.*;
   import flash.external.ExternalInterface;

    public class TestMouseLeave extends Sprite
    {
        public function TestMouseLeave()
        {
            // Add event listener for when the mouse LEAVES FLASH
            addEventListener(MouseEvent.MOUSE_OUT, onMouseLeave);
        }

        private function onMouseLeave(ev:Event):void
        {
            var jslink = new ExternalInterface();
            jslink.call("changeFocus");
        }
    }

}

Javascript on your page:

<script type="text/javascript" language="javascript">
    function changeFocus(){
        document.body.focus();
    }
</script>

Let me know if you want an AS2 example, and I'll post it up.

Wanted to make a note about this solution: Once you push focus back to the browser, you will require that the user click on the Flash plug-in again to activate user input inside the flash plug-in. This could be a jarring user experience, and is something to consider when using this solution.

Upvotes: 6

Diodeus - James MacFarlane
Diodeus - James MacFarlane

Reputation: 114347

You can return the focus to the browser by doing a geturl can calling javascript on the HTML page:

document.body.focus()

How you do this in your Flash movie will depend on how the user interaction with the movie works. You could keep doing it on a timer, or when a control loses focus, or when the mouse moves. It depends.

Upvotes: 0

user32141
user32141

Reputation: 248

I think Adobe needs to drop the focus when the mouse goes out of its client area, or provide an option to do so.

However I think most Flash developers (and especially those who make games) rely on the fact that keyboard input is caught by the flash application regardless of where the mouse is.

Upvotes: 3

Related Questions