Flex: How I worked around MOUSE_OUT’s inefficiencies

In Twitterified Client v1, one of the features I really wanted available right off the bat, was that when a user moves their mouse pointer over a twitterer’s avatar, an overlay image is displayed. This image is a menu of sort, allowing the user to send a direct message, a reply or access a more advanced menu. Of course, when the mouse pointer exists the avatar’s region, the overlay image needs to quietly go. Being the Flex newbie that I am, I thought that a straightforward implementation would work:

?View Code ACTIONSCRIPT
_imageOverlayPanel.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);

In onMouseOut(), I would detach _imageOverLayPanel, remove the listener, and move foward. Unfortunately, when moving my mouse around at a reasonably fast speed, I found out that the overlay panel did not go away, and after a while I had several avatars “polluted” by that overlay panel. I started “tracing” the MOUSE_OUT event and found out that, at least in AIR applications, there is no guarantee that such an event will be triggered. Ouch.

I experimented with, instead, using a timer that would kick in every 500ms and check whether the mouse pointer was still in the avatar’s region. It worked very well but felt a bit clunky and there was a risk of race condition with mouse events.

In the end, I settled for an approach using MOUSE_MOVE, which feels “cleaner” and works almost as well as the timer method:

?View Code ACTIONSCRIPT
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMovePossiblyOut);
?View Code ACTIONSCRIPT
private function onMouseMovePossiblyOut(event:MouseEvent):void
{
    if(!_imageOverlayPanel.parent) return;
    var pt:Point = new Point(event.stageX, event.stageY);
    pt = _imageOverlayPanel.globalToLocal(pt);
    if(pt.x < 0 || pt.y < 0 || pt.x > _imageOverlayPanel.width || pt.y > _imageOverlayPanel.height)
    {
        _imageOverlayPanel.parent.addEventListener(MouseEvent.MOUSE_OVER, onImageMouseOver); // innerWrapper resumes listening to mouse_over events
        _imageOverlayPanel.parent.removeChild(_imageOverlayPanel); // overlay panel is detached from innerWrapper
    }
}

Note that the trick, here, is that I add my mouse listener to the stage rather than the image overlay itself. This allows me to receive mouse events that happen outside the overlay’s region; they are the ones I am interested in.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Similar Posts:

There are currently no comments highlighted.

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Comments

No comments yet.

Leave a comment

(required)

(required)