flash blocking javascript events
Asked Answered
E

2

8

this is an edit of the original post now that I better understand the problem. now with source code!

In IE, if body (or another html div has focus), then you keypress & click on flash at the same time, then release... a keyup event is never fired. It is not fired in javascript or in flash. Where is this keyup event?

This is the order of event firing you get instead:

  1. javascriptKeyEvent: bodyDn ** currentFocusedElement: body
  2. javascriptKeyEvent: docDn ** currentFocusedElement: body
  3. actionScriptEvent : activate ** currentFocusedElement: [object]
  4. actionScriptEvent : mouseDown ** currentFocusedElement: [object]
  5. actionScriptEvent : mouseUp ** currentFocusedElement: [object]

Subsequent keydown and keyup events are captured by flash, but that initial keyUp is never fired.. anywhere. And I need that keyup!

What does not work:

  • checking if the key is up without a listener. Check if a key is down?
  • wmode opaque or direct. Although, with opaque, it is far more difficult to reproduce.
  • pushing the focus back to javascript asap to catch the up event. (tried this with a blur listener in javascript and setting focus when as3 is activated.)
  • neither jquery or prototype capture the missing keyup
  • both static and dynamic swfobject publishing

Here is the html/javascript:

<html>

<head>
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript" src="swfobject.js"></script> 

    <script>


    function ic( evt )
    {   Event.observe( $("f1"), 'keyup', onKeyHandler.bindAsEventListener( this, "f1Up" ) );
        Event.observe( $("f2"), 'keyup', onKeyHandler.bindAsEventListener( this, "f2Up" ) );
        Event.observe( document, 'keyup', onKeyHandler.bindAsEventListener( this, "docUp" ) );
        Event.observe( $("body"), 'keyup', onKeyHandler.bindAsEventListener( this, "bodyUp" ) );
        Event.observe( window, 'keyup', onKeyHandler.bindAsEventListener( this, "windowUp" ) );

        Event.observe( $("f1"), 'keydown', onKeyHandler.bindAsEventListener( this, "f1Dn" ) );
        Event.observe( $("f2"), 'keydown', onKeyHandler.bindAsEventListener( this, "f2Dn" ) );
        Event.observe( document, 'keydown', onKeyHandler.bindAsEventListener( this, "docDn" ) );
        Event.observe( $("body"), 'keydown', onKeyHandler.bindAsEventListener( this, "bodyDn" ) );
        Event.observe( window, 'keydown', onKeyHandler.bindAsEventListener( this, "windowDn" ) );

        Event.observe( "clr", "mousedown", clearHandler.bindAsEventListener( this ) );

        swfobject.embedSWF( "tmp.swf",
                            "f2",
                            "100%",
                            "20px",
                            "9.0.0.0", null, {}, {}, {} );
    }

    function clearHandler( evt )
    {   clear( );
    }

    function clear( )
    {   $("log").innerHTML = "";    
    }

    function onKeyHandler( evt, dn )
    {   logIt( "javascriptKeyEvent:"+dn );
    }

    function AS2JS( wha )
    {   logIt( "actionScriptEvent::" + wha );
    }

    function logIt( k )
    {   
        var id = document.activeElement;
        if (id.identify)
        {   id = id.identify();
        }

        $("log").innerHTML = k + " ** focuedElement: " + id + "<br>" + $("log").innerHTML;
    }

    Event.observe( window, 'load', ic.bindAsEventListener(this) );

    </script>

</head>

<body id="body">
<div id="f1"><div id="f2" style="width:100%;height:20px; position:absolute; bottom:0px;"></div></div>

<div id="clr" style="color:blue;">clear</div>

<div id="log" style="overflow:auto;height:200px;width:500px;"></div>
</body>
</html>

Here is the as3 code:

package
{

import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.external.ExternalInterface;

public class tmpa extends Sprite
{

public function tmpa( ):void
{
    extInt("flashInit");
    stage.align = StageAlign.TOP_LEFT;
    stage.scaleMode = StageScaleMode.NO_SCALE;
    stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDnCb, false, 0, true );
    stage.addEventListener( KeyboardEvent.KEY_UP, keyUpCb, false, 0, true );

    stage.addEventListener( MouseEvent.MOUSE_DOWN, mDownCb, false, 0, true );
    stage.addEventListener( MouseEvent.MOUSE_UP, mUpCb, false, 0, true );
    addEventListener( Event.ACTIVATE, activateCb, false, 0, true );
    addEventListener( Event.DEACTIVATE, dectivateCb, false, 0, true );
}

private function activateCb( evt:Event ):void
{   extInt("activate");
}

private function dectivateCb( evt:Event ):void
{   extInt("deactivate");
}

private function mDownCb( evt:MouseEvent ):void
{   extInt("mouseDown");
}

private function mUpCb( evt:MouseEvent ):void
{   extInt("mouseUp");
}

private function keyDnCb( evt:KeyboardEvent ):void
{   extInt( "keyDn" );
}

private function keyUpCb( evt:KeyboardEvent ):void
{   extInt( "keyUp" );
}

private function extInt( wha:String ):void
{   try
    {   ExternalInterface.call( "AS2JS", wha );
    }
    catch (ex:Error)
    {   trace('ex: ' + ex);
    }
}

}
}
Endrin answered 16/3, 2010 at 19:38 Comment(1)
Not firing the keyup event in JavaScript sounds like expected behaviour to me. ActiveX controls consume events and do not propagate them back to the containing document. That doesn't explain why Flash doesn't fire the event properly though - an interesting question. Unfortunately I think the only people who might be able to answer the question are Adobe's staff :-)Doorstone
L
1

Here is what I expect is going on: You keypress while focus is in html. You click the flash object and focus goes to that. When the key is lifted, because the html no longer has focus, it doesn't know about the key up. You could easily test this by doing the same thing only instead of clicking on the flash object, click on another window and try the same thing, because that is effectively what is happening.

As for the key up event not happening in flash, that is likely because it doesn't generate key up events without getting a key down, which it never got because focus was still in html.

I can think of two possible solutions to this. The first is to make sure that the flash object starts with focus. The second is to overlay an empty div over the flash object so it never receives focus.

Latinize answered 29/3, 2010 at 21:23 Comment(4)
Regarding your second suggestion - an empty div on top of the swf - this works, but being forced to use compatible embed modes makes performance suffer. Regrettable.Endrin
Regarding your first suggestion, if your embedded flash is just one of many elements on a page, then Adobe's suggestion has limited utility.Endrin
Out of curiosity, how about using the blur event as a failsafe for the keydown? That is, if the document receives a keydown, then a blur event, trigger the keyup event manually.Sander
@Codemonkey - Yeah, that's a pretty good idea. Definitely worth a shot.Latinize
L
0

Place your SWF Embed before any other JavaScript.

swfobject.embedSWF( "tmp.swf",
                            "f2",
                            "100%",
                            "20px",
                            "9.0.0.0", null, {}, {}, {} );

I would try it outside of all functions or in a document ready jQuery function because Flash gets a z-index of infinity and should accept key strokes before anything else unless it is not yet present when the first keyup occurs.

My guess is that the first key up is occurring before anything is able to receive it. Try your keyup event trigger with jQuery in an on document ready function.

Leialeibman answered 17/3, 2010 at 20:34 Comment(1)
Thank you. I've read your response a few times, and I think you think the problem is only at loading time. Please correct me if I am wrong. Once loaded, the problem occurs repeatedly -- you can give focus to another html div, and then click/type on flash to play "lose the keyup".Endrin

© 2022 - 2024 — McMap. All rights reserved.