4 Replies Latest reply on Jul 21, 2006 11:11 AM by a.neko®

    Event phases & events handling in nested MovieClips.

    a.neko®
      I am migrating a component to ActionScript 3.0. The component involves two (or more) nested MovieClips, which I need to be able to invoke different functions when clicked. In ActionScript 2.0 I used to simply handle this with indvidual MovieClip.onPress functions for each MovieClip. In ActionScript 3.0, I used event listeners as follows:

      // script
      public function createMovieClips():void {
      var clipA:MovieClip;
      this.clipA = new MovieClip ();
      this.clipA.graphics.beginFill(0xCDDCAF);
      this.clipA.graphics.drawRoundRect(0,0,100,100,50,50);
      this.clipA.graphics.endFill();
      this.clipA.name = "A";
      this.clipA.x=0;
      this.clipA.y=0;
      this.clipA.addEventListener(MouseEvent.CLICK, this.eventFunctionA);
      this.addChildAt(clipA,0);

      this.clipA.clipB = new MovieClip ();
      this.clipA.clipB.graphics.beginFill(0x8ACF83);
      this.clipA.clipB.graphics.drawRoundRect(0,0,100,100,50,50);
      this.clipA.clipB.graphics.endFill();
      this.clipA.clipB.name = "B";
      this.clipA.clipB.x=50;
      this.clipA.clipB.y=50;
      this.clipA.clipB.addEventListener(MouseEvent.CLICK, this.eventFunctionB);
      this.clipA.addChildAt(this.clipA.clipB,0);
      }

      public function eventFunctionA(event:Event):void {
      trace("eventFunctionA");
      trace(event);
      trace(event.target);
      trace(event.target.name);
      return;
      }

      public function eventFunctionB(event:Event):void {
      trace("eventFunctionB");
      trace(event);
      trace(event.target);
      trace(event.target.name);
      return;
      }



      When clipA is clicked, everything is fine:

      // trace result
      eventFunctionA
      [MouseEvent type="click" bubbles=true cancelable=false eventPhase=2 localX=51 localY=26 stageX=333 stageY=50 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
      [object MovieClip]
      A



      However, when clip is clicked, both functions are invoked, with clipB as event.target for both:

      // trace result
      eventFunctionB
      [MouseEvent type="click" bubbles=true cancelable=false eventPhase=2 localX=28 localY=68 stageX=360 stageY=142 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
      [object MovieClip]
      B
      eventFunctionA
      [MouseEvent type="click" bubbles=true cancelable=false eventPhase=3 localX=28 localY=68 stageX=360 stageY=142 relatedObject=null ctrlKey=false altKey=false shiftKey=false delta=0]
      [object MovieClip]
      B



      As I see, eventFunctionA() is invoked during the event's bubbling phase ( eventPhase=3). For now, I've solved this as follows:

      // script
      public function eventFunctionA(event:Event):void {
      if (event.eventPhase == 2) {
      trace("eventFunctionA")
      trace(event);
      trace(event.target);
      trace(event.target.name);
      }
      return;
      }



      This way, when clicking clipB, both functions are still invoked, but in eventFunctionA() no actions are taken.

      However, honestly, I still just don't get it. Does it mean that during the event's bubbling phase, all event target object's parents' event listeners for the same event will trigger their respectively attributed functions, or is just something wrong with my script?

      a.neko

        • 1. Re: Event phases & events handling in nested MovieClips.
          inlineblue Level 1
          Yep, events will bubble up to all parents until the top (Application) is reached. In the event, "target" is the original dispatcher of the event, so that's clipB in both cases (if you want to know where it has bubbled to, check the "currentTarget" property). There're various ways to handle this situation. I think for you, it's better to check the target and not the phase in eventFunctionA. ie. if target == clipA, then do something.
          • 2. Re: Event phases & events handling in nested MovieClips.
            inlineblue Level 1
            Yep, events will bubble up to all parents until the top (Application) is reached. In the event, "target" is the original dispatcher of the event, so that's clipB in both cases (if you want to know where it has bubbled to, check the "currentTarget" property). There're various ways to handle this situation. I think for you, it's better to check the target and not the phase in eventFunctionA. ie. if target == clipA, then do something.
            • 3. Re: Event phases & events handling in nested MovieClips.
              a.neko® Level 1
              inlineblue:

              Thanks for confirming. Well... then it's just a different way of thinking to adopt, with one more thing to remember. As my component has some complexity of interaction with the same event type, I think I'll go for a separate all-event-handling class method, which wll consider event types as well as targets (following your advice), etc...

              I just wonder what's about encapsulation, if an event from a deeply nested object triggers functions for all it's parent objects (in case they have listeners listening for the same event). I suppose it would be easier, if event flow would occur at a parameter-specified level... well... nevermind : )))

              Thanks.

              a.neko
              • 4. Re: Event phases & events handling in nested MovieClips.
                a.neko® Level 1
                Solution found:

                public function eventFunctionB(event:Event):void {
                event.stopPropagation();
                trace("eventFunctionB");
                trace(event);
                trace(event.target);
                trace(event.target.name);
                return;
                }


                a.neko