A couple weeks ago, I struggled to make sense of Flex event oropagation. Looking back at it last night, it all came together for me in about 4 minutes. Amazing.
I was struggling with a scenario like so. Imagine that you've got a blue canvas and a green button on the canvas:
I wanted to be able have a single mouse listener on the Canvas that wasn't thrown off when I hovered over the button. At first, I found this frustratingly difficult: (a) I tried attaching one listener to the Canvas and one to the Button and have them stay coordinated and (b) the value of localX and localY were vastly different when the mouse switched from the Canvas to the Button.
In this case, I was definitely working against Flex - as it makes solving the above problem quite easy. Here's what I did:
- I didn't need to attach a mouse listener to the button. In fact, that's bad. By not attaching one to the Button and only having it on the Canvas, the Canvas would automatically be delivered the Button's events. This is called bubbling, and it just works. If you want, you can add a listener to the Canvas that hears events before the button itself - this is known as capture, and while doable, wasn't what I needed.
A key item I needed to make sure of was that the event handler was on the Canvas, specifically, the Button's parent. If I had an event handler on an object that was say a sibling of the Button, it would never hear the Button's events.
- My localX, localY shift was caused by the fact that I was using the event's target attribute. When the Canvas is delivered the Buttons'e event (because the Button doesn't handle it, so it bubbles up) - the value of target is the Button. However, if you look at the value of currentTarget will be automatically adjusted to tell you which object is currently handling the event. So, it will start off set to the Button, and then update to the Canvas.
In order to get the x, y coordinates of the mouse in the right context I needed to switch from:
function(e:MouseEvent):void { doIt(e.target, e.localX, e.localY); }
to:
function(e:MouseEvent):void { // currentTarget will be my Canvas // with mouseX and mouseY initialized properly doIt(e.currentTarget, e.currentTarget.mouseX, e.currentTarget.mouseY); }
Flex events definitely take some getting used to - but they are powerful, and quite usable. Now when I get that feeling that I'm doing work that the Flex API should handle (say, converting x,y coordinates to the right values for a given context), I know to go shopping around on the API itself for a solution. This sucker is pretty dang complete.
Update Thanks to Dave Nelson for sending me a note to tell me my title was misspelled. Usually, I'd blame this type of error on Firefox not spell checking the title field by default. However, I typed prorogation - which is in fact, a real word. Defined as: discontinuing the meetings (of a legislative body) without dissolving it. I do believe this could be a handy word to use. Thanks Dave!
No comments:
Post a Comment