I need to close the popup(adobe flex), non modal window if I click on the parent page of the popup. I have to do the out of focus check and then do some validation before close the popup. So what I was thinking that is there any inbuilt focus check event or do we need to create custom event for that ?
In your popup you need to listen for mouse up event on the popup itself, and the stage. On the popup if you catch a mouse up event, stop it from getting to the stage. Then, if you receive a mouse up event on the stage you will know that it was outside of the popup and can close the popup.
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" creationComplete="onCreationComplete()">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
private function onCreationComplete():void {
//listen for MouseUp events on the popup, and the stage
this.addEventListener(MouseEvent.MOUSE_UP, handleMouseUp);
stage.addEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
}
private function handleMouseUp(e:MouseEvent):void {
//catch any MouseUp events on the popup,
//and prevent them from getting to the stage
e.stopPropagation(); //don't let this event get to the stage
}
private function handleStageMouseUp(e:MouseEvent):void {
//if the stage fires a MouseUp event, the mouse event
//came from outside of the popup, so we can close it
closePopup();
}
private function validate():Boolean {
//add your validate code here
return true;
}
private function closePopup():void {
if ( validate() ) {
//clean up event listeners, and close popup
stage.removeEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
PopUpManager.removePopUp(this);
}
}
]]>
</mx:Script>
</mx:Canvas>
Related
I have a button that starts the game, it initializes the game when you click it
startButton.addEventListener(MouseEvent.CLICK, onStartButtonClick);
I also have a firing thing, it's supposed to shoot AFTER you start the game by clicking the start button and THEN shoot when you click.
stage.addEventListener(MouseEvent.CLICK, fire);
However, it fires right when I click the start button. How can I fix this?
This is my code.
public function Game()
{
startButton.addEventListener(MouseEvent.CLICK, onStartButtonClick);
}
function onStartButtonClick(event: MouseEvent): void
{
addEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(MouseEvent.CLICK, fire);
function fire(m: Event)
{
//shoot bullet
}
}
It's caused by event bubbling.
Just modify your onStartButtonClick function to:
function onStartButtonClick(event: MouseEvent): void
{
event.stopPropagation();
addEventListener(Event.ENTER_FRAME, loop);
stage.addEventListener(MouseEvent.CLICK, fire);
For more information about event bubbling CHECK HERE
I am using the flex SuperTabNavigator and want on closing the tab check if the control button was pressed. I tried:
public static var CONTROL_PRESSED:Boolean = false;
public function init():void {
var clickListener:Function = function _clickListener(event:MouseEvent):void{
trace(event.ctrlKey);
if(event.ctrlKey){
CONTROL_PRESSED = true;
}else{
CONTROL_PRESSED = false;
}
};
FlexGlobals.topLevelApplication.addEventListener(MouseEvent.CLICK, clickListener);
}
The problem with this is that the mouse click is called everywhere in the application except on the tab. I also tried the same code but addEventListener(MouseEvent.CLICK, clickListener); to add the listener to the SuperTabNavigator and it did not work at all. Is there another way to catch the mouse click?
This is because the SuperTabNavigator has a private mouse click handler function that hides the MouseEvent:
private function closeClickHandler(event:MouseEvent):void {
if(this.enabled) {
dispatchEvent(new Event(CLOSE_TAB_EVENT));
}
event.stopImmediatePropagation();
event.stopPropagation();
}
You'll need to modify the SuperTab class in the SuperTabNavigator source to dispatch some CustomEvent with the data you want instead of a plain new Event(CLOSE_TAB_EVENT).
Then change the onCloseTabClicked function in SuperTabBar to know about your CustomEvent. Then you can pass that to your application code (by adding it to the SuperTabEvent, perhaps).
I have a problem similar like this question but i'm not able to get understand this answer code, Can any one explain this code.
private function attachListeners():void
{
this.addEventListener(MouseEvent.MOUSE_DOWN, selfMouseDownHandler, false,0,true);
this.addEventListener(MoveEvent.MOVE, selfMoveHandler, false,0,true);
}
private function selfMoveHandler(event:MoveEvent):void
{
redrawConnectedLinks();
}
private function selfMouseDownHandler(event:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUpHandler, false,0,true);
stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false,0,true);
}
private function stageMouseUpHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUpHandler, false);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false);
}
private function stageMouseMoveHandler(event:MouseEvent):void
{
dispatchEvent(new MoveEvent(MoveEvent.MOVE));
}
Please suggest me how to use this in flex application.
This code is tracking mouse movement by Flash's MouseEvent.MOUSE_UP, MouseEvent.MOUSE_MOVE and MouseEvent.MOUSE_DOWN.
Along with those events, the code is using a custom Event: MoveEvent.MOVE.
Any time, a MoveEvent.MOVE is being dispatched, the app would redraw the connectors. So, a listener to MoveEvent.MOVE is being added once and for all at the beginning.
Also, to track a drag, this code waits for MOUSE_DOWN and then keep on dispatching MoveEvent.MOVE for each MouseEvent.MOUSE_MOVE until a MOUSE_UP event occurs.
Now, let me associate the above explanation to the lines of code:
private function attachListeners():void
{
/*Wait for mouse down event to initiate mouse move and mouse up tracking*/
this.addEventListener(MouseEvent.MOUSE_DOWN, selfMouseDownHandler, false,0,true);
/*Always track MoveEvent.MOVE and start redrawing connectors whenever it's dispatched*/
this.addEventListener(MoveEvent.MOVE, selfMoveHandler, false,0,true);
}
private function selfMoveHandler(event:MoveEvent):void
{
/*Redraw connectors when the custom event MoveEvent.MOVE is received*/
redrawConnectedLinks();
}
private function selfMouseDownHandler(event:MouseEvent):void
{
/*Wait for mouse up event on receiving a mouse down*/
stage.addEventListener(MouseEvent.MOUSE_UP, stageMouseUpHandler, false,0,true);
/*Track mouse movement once mouse is down*/
stage.addEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false,0,true);
}
private function stageMouseUpHandler(event:MouseEvent):void
{
/*Once mouse up happens stop tracking mouse up... */
stage.removeEventListener(MouseEvent.MOUSE_UP, stageMouseUpHandler, false);
/*Don't track mouse movement once mouse button gets released*/
stage.removeEventListener(MouseEvent.MOUSE_MOVE, stageMouseMoveHandler, false);
}
private function stageMouseMoveHandler(event:MouseEvent):void
{
/*dispatch MoveEvent.MOVE when mouse is moved.
If you read the above setup again, this should get dispatched on mouse moves
happening after a mouse down and before a mouse up
*/
dispatchEvent(new MoveEvent(MoveEvent.MOVE));
}
HTH.
Explanation of custom events as asked in the comment by OP
Custom events are useful to add custom message passing semantics. e.g. in this case, mouse drag is a detected by a series of mouse events, and once those events happen a custom event is dispatched to notify the connectors should be redrawn. Similarly, you might have a refresh button and clicking on it might dispatch the same event to force redraw.
Is there any way to detect if the user click outside a MovieClip?
For instance, I need to detect it to close a previously opened menu (like Menu bar style: File, Edition, Tools, Help, etc).
How can I detect this kind of event? Thanks!
Add a listener to stage and check if stage is the target of the event.
Example of code here:
http://wonderfl.net/c/eFao
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
public class FlashTest extends Sprite
{
private var _menu : Sprite;
public function FlashTest()
{
_menu = new Sprite();
_menu.x = 100;
_menu.y = 100;
_menu.alpha = 0.5;
with(_menu.graphics)
{
beginFill(0xFF0000, 1);
drawRect(0, 0, 300, 300);
endFill();
}
addChild(_menu);
_menu.addEventListener(MouseEvent.CLICK, onClickHandler);
stage.addEventListener(MouseEvent.CLICK, onClickHandler);
}
private function onClickHandler(event : MouseEvent) : void
{
switch(event.target)
{
case _menu:
_menu.alpha = 0.5;
break;
case stage:
_menu.alpha = 1;
break;
}
}
}
}
You can add a listener to the click event of the root element:
MovieClip(root).addEventListener(MouseEvent.CLICK, clickObject);
then in the function clickObject, you can check to see what you are clicking.
function clickObject(e:Event):void
{
var hoverArray:Array = MovieClip(root).getObjectsUnderPoint(new Point(stage.mouseX, stage.mouseY));
var hoverOverObject:* = hoverArray[hoverArray.length - 1];
}
hoverOverObject references the element that you are clicking on. Often this will be the shape within the movie clip, so you'll need to look at it's parent then compare it to your movie clip. If the click wasn't on the drop down movie clip, trigger the close.
var container:MovieClip = new MovieClip();
var mc:MovieClip = new MovieClip();
with(mc.graphics){
beginFill(0xff0000,1);
drawCircle(0,0,30);
endFill();
}
mc.name = "my_mc";
container.addChild(mc);
addChild(container);
stage.addEventListener(MouseEvent.CLICK, action);
function action (e:MouseEvent):void
{
if(e.target.name != "my_mc"){
if(container.numChildren != 0)
{
container.removeChild(container.getChildByName("my_mc"));
}
}
}
Use capture phase:
button.addEventListener(MouseEvent.CLICK, button_mouseClickHandler);
button.stage.addEventListener(MouseEvent.CLICK, stage_mouseClickHandler, true);
//...
private function button_mouseClickHandler(event:MouseEvent):void
{
trace("Button CLICK");
}
private function stage_mouseClickHandler(event:MouseEvent):void
{
if (event.target == button)
return;
trace("Button CLICK_OUTSIDE");
}
Note that using stopPropagation() is good for one object, but failed for several. This approach works good for me.
Use a stage and a sprite (menu) click listener with the sprite listener executing first and apply the stopPropagation() method to the click handler of the sprite. Like this:
menu.addEventListener(MouseEvent.CLICK, handleMenuClick);
stage.addEventListener(MouseEvent.CLICK, handleStageClick);
private function handleMenuClick(e:MouseEvent):void{
// stop the event from propagating up to the stage
// so handleStageClick is never executed.
e.stopPropagation();
// note that stopPropagation() still allows the event
// to propagate to all children so if there are children
// within the menu overlay that need to respond to click
// events that still works.
}
private function handleStageClick(e:MouseEvent):void{
// put hide or destroy code here
}
The idea is that a mouse click anywhere creates a single MouseEvent.CLICK event that bubbles from the stage, down through all children to the target, then back up through the parents of the target to the stage. Here we interrupt this cycle when the target is the menu overlay by not allowing the event to propagate back up to the parent stage, ensuring that the handleStageClick() method is never invoked. The nice thing about this approach is that it is completely general. The stage can have many children underneath the overlay and the overlay can have its own children that can respond to clicks and it all works.
I've made this game with event listener (coordinates) on mouse position when a click occurs (to move the character).
I've another event listener for drag and drop (to combine items) that works pretty well.
function stageDown (event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.CLICK, coordinates);
MovieClip(getChildByName(event.target.name).toString()).startDrag();
MovieClip(getChildByName(event.target.name).toString()).addEventListener(MouseEvent.MOUSE_UP,stageUp);
...stuff..
}
function stageUp(event:MouseEvent):void
{
stopDrag();
...stuff...
stage.addEventListener(MouseEvent.CLICK, coordinates);
}
In the function stageDown I remove the event listener for the movement(coordinates), than I add it again at the end of the function stageUp (when you release the mouse button and the drag is complete)
But is not working, when I release the drag the character start moving, can't understand why
I don't fully understand the why (something to do with how Click events are tracked I suppose) but it is the 'normal' behavior.
Here is how I've handled this in the past. Basically you can add a higher priority click listener to the object you are dragging and cancel the event there: (see code comments)
//Assuming you have something like this in your code/////////
stage.addEventListener(MouseEvent.CLICK, coordinates);
function coordinates(event:MouseEvent):void {
trace("STAGE CLICK"); //whatever you do here
} ///////////////////////////////////////////////////////////
//add your mouse down listener to your object
someObject.addEventListener(MouseEvent.MOUSE_DOWN, stageDown);
//ALSO add a click listener to your object, and add it with higher priority than your stage mouse click listener
someObject.addEventListener(MouseEvent.CLICK, itemClick, false, 999);
function itemClick(event:MouseEvent):void {
//stop the event from reaching the lower priority stage mouse click handler
event.stopImmediatePropagation();
trace("Item CLICK");
}
function stageDown (event:MouseEvent):void
{
Sprite(event.currentTarget).startDrag();
//listen for the mouse up on the stage as sometimes when dragging very fast there is slight delay and the object may not be under the mouse
stage.addEventListener(MouseEvent.MOUSE_UP,stageUp, true);
//if you don't care about mouse up on stage, then you can just forget the mouse up listener and handler altogether and just stop drag on the itemClick function.
}
function stageUp(event:MouseEvent):void
{
//remove the stage mouse up listener
stage.removeEventListener(MouseEvent.MOUSE_UP,stageUp, true);
trace("UP");
stopDrag();
}