4

I'm a long-time ActionScript 2 user, now getting started with ActionScript 3. The one thing I'm missing is an easy way to duplicate the functionality of AS2's MovieClip.onReleaseOutside. It is almost always necessary to implement this event, otherwise you get funny bugs like flash thinks your mouse is down when really it's up.

According to the AS2 to AS3 Migration Guide, I'm supposed to use flash.display.InteractiveObject.setCapture() for this, however it does not exist as far as I can tell. I guess this document is out of date or incorrect. I've found a few posts on the web about how to duplicate this functionality, but they either have their own problems:

  • This one triggers onReleaseOutside even if there was no corresponding onPress event.
  • This one seems very inefficient, you'll add and remove an event listener every time the mouse is clicked anywhere inside your app.

There has to be an easier way, don't tell me Adobe forgot about this when rewriting Actionscript?

Example AS2 code:

// Assume myMC is a simple square or something on the stage

myMC.onPress = function() {
  this._rotation = 45;
}

myMC.onRelease = myMC.onReleaseOutside = function() {
  this._rotation = 0;
}

Without the onReleaseOutside handler, if you pressed down on the squre, dragged your mouse outside of it, and released the mouse, then the square would not un-rotate, and appear to be stuck.

davr
  • 18,877
  • 17
  • 76
  • 99
  • I moved from AS2 to Flex 3 and so haven't encountered this problem. So whilst I can't offer an answer, have an upvote for drawing my attention to the problem. Cheers. – David Arno Oct 31 '08 at 22:46
  • This will be ok if you release on the blank area of your stage. What to do if you release over an unknown sprite on your stage? or what if there are multiple buttons needing to check releaseOutside? –  Jan 12 '12 at 21:47

3 Answers3

10

Simple and foolproof:

button.addEventListener( MouseEvent.MOUSE_DOWN, mouseDownHandler );
button.addEventListener( MouseEvent.MOUSE_UP, buttonMouseUpHandler ); // *

function mouseDownHandler( event : MouseEvent ) : void {
    trace( "onPress" );
    // this will catch the event anywhere
    event.target.stage.addEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
}

function buttonMouseUpHandler( event : MouseEvent ) : void {
    trace( "onRelease" );
    // don't bubble up, which would trigger the mouse up on the stage
    event.stopImmediatePropagation( );
}

function mouseUpHandler( event : MouseEvent ) : void {
    trace( "onReleaseOutside" );
    event.target.removeEventListener( MouseEvent.MOUSE_UP, mouseUpHandler );
}

If you don't care about the difference between onRelease and onReleaseOutside (for example with draggable items) you an skip the mouse up listener on the button itself (commented here with an asterisk).

Antti
  • 3,119
  • 3
  • 24
  • 22
  • Remember to remove the stage listener on the buttonMouseUpHandler also ;) – Cay Oct 14 '09 at 10:34
  • Thanks Antii, that's very comprehensive. But does anyone else also think that it's kinda stupid that there's not just a MouseEvent.MOUSE_UP_OUTSIDE to encapsulate this _extremely common_ scenario... – aaaidan Mar 09 '10 at 04:19
  • aaaidan: The reason Adobe didn't put this in when going to as3 was performance. In order for this event to be fired, a display object would have to know about mouse events happening outside of it, adding some overhead. This was a known decision made by them as in most cases you won't need this anyway and the workaround is pretty easy. – Antti Mar 10 '10 at 10:38
  • 1
    Is there a way I can use this on the stage itself? i.e I want to do something, if the users puts the mouse outside the browser and then does a mouse_up.(incase you feel this is not possible, check out google finance charts, if you drag the scrollbar, and in the process take the mouse outside th window and then release it, it simply puts the scrollbar at on of the ends) – Neeraj Aug 01 '11 at 07:51
3

Have you looked at this event:

flash.events.Event.MOUSE_LEAVE



From the documentation:

Dispatched by the Stage object when the mouse pointer moves out of the stage area. The Event.MOUSE_LEAVE constant defines the value of the type property of a mouseLeave event object.

It will solve your problem if you are only interested whether the user's mouse if off the stage instead of just outside that particular MovieClip.

Ronnie Liew
  • 18,220
  • 14
  • 46
  • 50
3

root.addEventListener(MouseEvent.UP, onMouseReleaseOutside);

You define onMouseReleaseOutside of course. Basically any MouseEvent.UP (a mouse release) that happens outside of your button (or mc) will hit the stage instead of your button. This is the way i usually catch it.

Rafe
  • 8,467
  • 8
  • 47
  • 67