AS3: MOUSE_OUT not firing when Mouse leaves stage

I am developing a website with nav items that cover the whole stage from top to bottom (see altered image below) and it is pretty easy for the user to exit the stage with their mouse, not triggering the MouseEvent.MOUSE_OUT events required to "turn off" said nav items.

Should I be using Event.MOUSE_LEAVE to detect when the mouse has left the stage, and turn off any enabled nav items? That is what I been trying to do, but have had trouble getting any output from my listener. Any ideas?

For a class associated with a movieclip in the Flash IDE, is this the correct syntax for registering an Event.MOUSE_LEAVE listener? It doesn't seem to do anything no matter what I do. Is it a case where I have to embed the movie in a browser for the event to fire?

this.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveListener);

Here is my MainNav.as class:

package com.redpropeller {

import com.greensock.*;
import com.greensock.plugins.*;
import flash.display.*;
import flash.text.*;
import flash.events.*;

public class MainNav extends MovieClip { // MainNav is a movieclip in the IDE

    public var colors:Array;

    public function MainNav():void {
        colors = new Array(0xee3124, 0xc72a1f, 0xa62c24, 0x912923, 0x7e221c);
        TweenPlugin.activate([TintPlugin]);

        // trying to target stage through this object
        this.stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveListener);

        for(var i:Number=0; i<this.numChildren; i++){
            var n = this.getChildAt(i);
            n.useHandCursor = true;
            n.buttonMode = true;

            n.addEventListener(MouseEvent.MOUSE_OVER, navBtnOn);
            n.addEventListener(MouseEvent.MOUSE_OUT, navBtnOff);
        }
    }
    public function mouseLeaveListener(e:Event):void {
        trace('mouseleave'); // nothing ever happens

    }
    private function navBtnOn(e:MouseEvent):void {
        TweenLite.to(e.currentTarget.bar_mc, 0.01, {tint:0x333333});
    }
    private function navBtnOff(e:MouseEvent):void {
        TweenLite.to(e.currentTarget.bar_mc, 0.01,
            {tint:uint(colors[this.getChildIndex(MovieClip(e.currentTarget))])});
            // changes color back to specific tint
    }
}

}

Answers


You're trying to create the event listener for MOUSE_LEAVE in the constructor. It's possible that the stage object does not exist yet if MainNav has not been added to the stage via an addChild() method. If MainNav is already on the stage at design time, it's still possible that stage would not be available immediately. For classes that inherit from the DisplayObject (MovieClip, Sprite, etc.), I do only one thing in the constructor: set up an Event.ADDED_TO_STAGE listener. That listener triggers an init() method when the object has been added to the stage's display stack via addChild() from a parent container, or if the object is already on the stage at design time. When my init() method is called, I know that the stage property will be available.

In your constructor, stage may not exist in the instance yet, but you should get a runtime error. However, you're using the 'this' keyword ahead of stage. When you use 'this' in a class that inherits from Object (your class does via MovieClip->DisplayObject->EventDispatcher->Object), the compiler won't throw an error if the property does not exist because it attempts to create that property as a member of 'this'. This happens because the Object class is dynamic, meaning that new properties can be created at any time without having to declare them as class variables in the header -- you just have to use the 'this' keyword when using that dynamic property. When you use this.stage, if stage does not exist the class creates the property stage for you. However, this is not the stage you want, so the listener is just getting attached to an empty object that doesn't do anything. Try removing 'this' when referencing stage and I'm sure you'll see the error at some point. In general, it's not good practice to use 'this' for properties, since the compiler will ignore type errors for that property.

You mention in one comment above that MOUSE_LEAVE does not work in the IDE, but I tested this from CS4 and it does work. You may be witnessing a performance difference from the IDE's Flash Player compared to the browser's Flash Player plugin. In some cases your stage event listener will work from the constructor if the SWF loads quickly and stage is available immediately, but it's not reliable. Move that listener to an init() method that is called after the ADDED_TO_STAGE event and don't use the 'this' keyword.


Answer: Event.MOUSE_LEAVE does not fire in the IDE. It works fine when the movie is embedded in an HTML page. Thanks for your help!


Need Your Help

Why does XML::LibXML find no nodes for this xpath query when using a namespace

xml perl xpath libxml2

I'm attempting to select a node using an XPath query and I don't understand why XML::LibXML doesn't find the node when it has an xmlns atribute. Here's a script to demonstrate the issue:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.