flash blocking javascript events
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:
- javascriptKeyEvent: bodyDn ** currentFocusedElement: body
- javascriptKeyEvent: docDn ** currentFocusedElement: body
- actionScriptEvent : activate ** currentFocusedElement: [object]
- actionScriptEvent : mouseDown ** currentFocusedElement: [object]
- 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);
}
}
}
}
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.
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.
精彩评论