views:

1238

answers:

3

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?

alt text

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
    }
}

}
A: 

Well, that is exactly how you would do it. You say you are testing this in the Flash IDE? It is certainly working for me.

One thing to note. The Event.MOUSE_LEAVE event does not fire until the user releases the mouse button (if depressed).


Just as a test, add the MOUSE_LEAVE event listener to the DocumentClass and test to see if it fires.

sberry2A
Well that might be the problem -- I need it for MOUSE_OUT, not MOUSE_DOWN. There is no clicking involved at this point. Any suggestions?
Marcy Sutton
That is only an issue if the user has the mouse button pressed when leaving the movie. In the case of something like a draggable MovieClip where the user presses the mouse button to start the drag and releases it to stop the drag, the MOUSE_LEAVE event will not fire while the user is attempting to drag the MovieClip. Make sense?If you are not pressing the mouse button at all then the event should fire as expected. I wonder if the problem might be with something else canceling the event during the capture phase.
sberry2A
I actually did try adding it to the Document class, and nothing happened. Since then, I created a test FLA and new document class and I still have the same problem -- no output from Event.MOUSE_LEAVE. It doesn't seem to matter if I target the stage through a movieclip or the document class.
Marcy Sutton
+1  A: 

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!

Marcy Sutton
What version of Flash are you using. I tested in both CS3 and CS4 and it works fine for me in the IDE.
sberry2A
Flash CS3... but even in a bare swf and a simple Document class, I got no output. But once I uploaded my file to the web, my MouseEvent.MOUSE_OUT events triggered fine, eliminating the need for Event.MOUSE_LEAVE.
Marcy Sutton
I can verify this doesn't work for me in the IDE either. I am using CS4 10.0.2 on OS X 10.6.3
James Fassett
A: 

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.

wmid