1

O.K. Here's the situation...

I have a custom mxml component that contains a couple of images and 4 buttons. The component file already contains a clickHandler for each of the buttons. I need to be able to either access the clickHandler or create another function and attach it to those buttons from within my Main.mxml file. Should I add to the original clickHandlers? if so, how do I apply the method to my Main.mxml file?

FYI: The component has 5 states and each clickHandler triggers transitions between the states.

Here are the two clickHandlers from the component file:

protected function submit_clickHandler():void
        {
            const state:String = currentState;
            if ( state == 'state1' ) {
                currentState='state2';
            }
            if ( state == 'state3' ) {
                currentState='state4';
                addElement(images[i]);     //The methods I want to run from 
                getStudentAnswer();        //within the Main.mxml.
                submit();                  //If I add them here, I get an
                newQuestion();             //undefined method error.
            }
            if ( state == 'state4' ) {
                currentState='state4';
            }
            if ( state == 'state5' ) {
                currentState='state4';
            }
            if ( state == 'state3' ) {
                Sequence1.play();
            }
        }

        protected function checkAnswer_clickHandler():void
        {
            const state:String = currentState;
            if ( state == 'state2' ) {
                currentState='state1';
            }
            if ( state == 'state4' ) {
                currentState='state5';
            }
        }

Thanks, JM

César
  • 9,939
  • 6
  • 53
  • 74
  • Just trying to wrap my head around your issue. Would bubbling the click event and adding a listener in Main.mxml solve the problem. Or, could you just dispatch a custom event to pass along the data you need? – Corey May 03 '11 at 17:30
  • Corey, thanks for the response.Forgive my ignorance. I am a self taught newbie and haven't learned about bubbling. I read the AS3 reference guide and still don't completely understand. Does bubbling allow me to refer to the click event directly from my Main.mxml? If so, how do I set it up? My guess would be to set bubbles = true, then put an event listener in Main.mxml? Sample code would be helpful. Thanks. – Jason Martin May 03 '11 at 23:11

1 Answers1

1

If you have access to the dispatch event for the buttons, just set "bubbles" to "true" and listen for the event in Main.mxml. If you think of the display list as a hierarchal tree with branches, an event that bubbles will travel up the branch until it reaches the first DisplayObject. Along the way, it checks each DisplayObject to find if it is waiting to capture the event.

Here is a basic illustration where Main is listening for a click event and has a child MovieClip instance with a child Sprite instance. The Sprite instance has a child Button instance that is dispatching a click event.

[object Main] (listening for MouseEvent.CLICK)
      |
      |__[object MovieClip]
                |
                |___[object Sprite]
                          |
                          |____[object Button] (dispatching MouseEvent.CLICK)

The dispatched click event in Button would be:

dispatchEvent(new MouseEvent(MouseEvent.CLICK, true));

In Main, you would just listend for the event:

addEventListener(MouseEvent.CLICK, clickHandler);

Because MouseEvent.CLICK is such a common event, I would suggest creating a custom event (or at least a unique event name) in this type of scenario to avoid the possibility of DisplayObject's capturing incorrect events. But, hopefully this gives a better idea of how to handle bubbling.

-

Without bubbling, the only other way to capture the event would be to use dot syntax. I don't recommend this method because it could get messy, but this helps to illustrate the concept of bubbling (assuming each child DisplayObject is public):

In Main: (again, not recommended)

movieClip.sprite.button.addEventListener(MouseEvent.CLICK, clickHandler);

Hope that helps!

[EDIT - Added custom Event] Here is what a custom Event class would look like:

package com.example.events
{
    import flash.events.Event;

    public class CustomEvent extends Event {

        public static const WITH_DATA:String = "withData";

        public var data:Object;

        public function NavEvent(type:String, data:Object=null, bubbles:Boolean=false, cancelable:Boolean=false) {
            super(type, bubbles, cancelable);
            this.data = data;
        }
    }
}

You would then dispatch an event like:

var myString:String = "buttonState";
dispatchEvent(new CustomEvent(CustomEvent.WITH_DATA, myString, true));

And listen for the event like:

addEventListener(CustomEvent.WITH_DATA, customEventHandler);

private function customEventHandler(e:CustomEvent):void {
    trace(e.data);
}
Corey
  • 5,818
  • 2
  • 24
  • 37
  • Do I place the dispatchEvent within the if statement? I only want it to dispatch if the component is in state3 or state4. Also how do I give the event a unique name? I tried `dispatchEvent(new MouseEvent("onSubmitClick", true));` Eclipse didn't show any syntax error, but it didn't work either. :) – Jason Martin May 05 '11 at 23:05
  • You could dispatch from the if statement. However, you will need another method of determining which "state" the component is in. This is where a custom event would help. I have added an example of a custom event and usage above. – Corey May 06 '11 at 15:02
  • Thanks again Corey. It took me a while to wrap my head around what you were showing me, but with a little help from my Java friend, we got it firing on all cylinders. Woohoo!!! – Jason Martin May 13 '11 at 09:46