9 Replies Latest reply on Mar 14, 2007 11:47 AM by Peter Lorent

    EventDispatcher in a Class

    Rothrock Level 5
      I'm making my own AS2 class, let's say Table.

      When constructing an instance of the Table class I am using some creating and drawing in some movieclips.

      I want to have that when any of the clips are clicked the Table instance dispatches an event saying which clip was clicked on.

      I've searched the forums and it seems my problem is that when clicking on the MovieClip I'm out of the Table instance scope so it doesn't know what to do with the dispatch event.

      In some other similar (but not exactly the same) examples in the forums LuigiL posted a solution to create a temporary variable to hold a reference to the class instance and use that.

      I've posted a shortened version of my class. Assume that I've got all the EventDispatcher code and other variable required. And assume I've got the correct code in my FLA file. It is working, but it seems ugly.

      I guess my question is that using this ScopFixer solution seems like an inelegant hack and that I am wondering if there is a better way to do this?
        • 1. Re: EventDispatcher in a Class
          Level 7
          Rothrock,

          > When constructing an instance of the Table class I am
          > using some creating and drawing in some movieclips.

          Gotcha.

          > I want to have that when any of the clips are clicked
          > the Table instance dispatches an event saying which
          > clip was clicked on.

          Wow, pretty cool idea. I think your issue is definitely one of scope,
          and the Delegate class should fix it for you. Here's a thought:

          import mx.utils.Delegate;
          class Table {
          public var scopeFixer:Object;
          public function Table(target:MovieClip) {
          scopeFixer = this;
          var mc:MovieClip = target.createEmptyMovieClip("testMC", 1);
          with (mc) {
          beginFill(0xFF00FF, 100);
          moveTo(0, 0);
          lineTo(100, 0);
          lineTo(100, 100);
          lineTo(0, 100);
          lineTo(0, 0);
          endFill();
          }
          mc.onRelease = Delegate.create(this, function():Void {
          trace(scopeFixer);
          scopeFixer.test();
          });
          }
          public function test():Void {
          trace("Heard it!");
          }
          }

          Note how I used the in-coming target parameter to specify the target of
          the new clip. But that's an aside. I tested the above code and passed in
          "this" from the main timeline while instantiating this class. The resultant
          fuschia square was clickable, and it correctly fired the test() method.


          David Stiller
          Adobe Community Expert
          Dev blog, http://www.quip.net/blog/
          "Luck is the residue of good design."


          • 2. Re: EventDispatcher in a Class
            Rothrock Level 5
            I think I'm following you, maybe…

            But in my swf, how will I be able to make code that will listen for that event?
            • 3. Re: EventDispatcher in a Class
              Level 7
              Rothrock,

              > I think I'm following you, maybe?

              Eh, I wasn't especially clear, because my test() method didn't dispatch
              an event. So I went back to experiment a bit more ... and found that you've
              come up with a real head-scratcher! Here's my latest thought. Notice that
              I'm taking advantage of MovieClip instances as dynamic objects (objects that
              can have properties added to them at runtime). I ditched Delegate and am
              setting your scopeFixer property right inside each clip.

              import mx.events.EventDispatcher;
              class Table {
              private var dispatchEvent:Function;
              public var addEventListener:Function;
              public var removeEventListener:Function;

              public function Table(target:MovieClip) {
              EventDispatcher.initialize(this);
              for (var i:Number = 0; i<2; i++) {
              var mc:MovieClip = target.createEmptyMovieClip("mc" + i, i);
              mc.scopeFixer = this;
              with (mc) {
              beginFill(0xFF00FF, 100);
              moveTo(0, 0);
              lineTo(100, 0);
              lineTo(100, 100);
              lineTo(0, 100);
              lineTo(0, 0);
              endFill();
              _x += i * 100;
              }
              mc.onRelease = function():Void {
              this.scopeFixer.shout(this);
              };
              }
              }
              public function shout(clip:MovieClip):Void {
              dispatchEvent({
              type:"click",
              target:this,
              someOtherProp:"someValue",
              mc:clip
              });
              }
              }

              To listen for the "click" event from the main timeline, use something
              like the following:

              import Table;
              var t:Table = new Table(this);

              var listener:Object = new Object();
              listener.click = function(evt:Object):Void {
              trace(evt.mc);
              }
              t.addEventListener("click", listener);


              Let me know if that makes sense. :)


              David Stiller
              Adobe Community Expert
              Dev blog, http://www.quip.net/blog/
              "Luck is the residue of good design."


              • 4. Re: EventDispatcher in a Class
                Rothrock Level 5
                Yeah, that is basically the same solution I came up with as well. It just seems so kludgey to have to put that scopeFixer in there. But hey, it works. Thanks for the help.
                • 5. Re: EventDispatcher in a Class
                  Peter Lorent Level 2
                  Agreed, it seems kludgy but it is unavoidable in AS2 due to the fact that inside any callback handler the class members go out of scope. In AS3 this is solved.
                  For more information see the help-files: Best Practices and Coding Conventions for ActionScript 2.0 > ActionScript coding conventions > Handling scope > About scope in classes

                  Two ways to solve this depending on the situation. One is to use a local reference, the other is usage of the Delegate Class. Using the Delegate Class however needs another hack if you want to pass parameters.

                  The solution David posted has one small disadvantage: the local reference cannot be datatyped. Usage of the 'hack' is a little different, see attached code. Yes, the MovieClip Class is dynamic but 'on the dark side' we try to avoid that as much as possible.

                  • 6. Re: EventDispatcher in a Class
                    Rothrock Level 5
                    Thanks LuigiL. It was your posts on this subject , with regard to XML, that lead me to this solution.
                    • 7. Re: EventDispatcher in a Class
                      Level 7
                      >> The solution David posted has one small disadvantage: the
                      >> local reference cannot be datatyped.

                      Aw, shucks, strong typing isn't *really* possible with AS2 anyway; not
                      at runtime. But I hear ya. :) AS3 gets more and more satisfying the more
                      I use it, especially for this sort of thing.

                      >> Using the Delegate Class however needs another hack if
                      >> you want to pass parameters.

                      Have you seen Joey Lott's Proxy class? Similar to Delegate (based on
                      it, in fact), but allows parameters to be passed.

                      http://www.person13.com/articles/proxy/Proxy.htm


                      David Stiller
                      Adobe Community Expert
                      Dev blog, http://www.quip.net/blog/
                      "Luck is the residue of good design."


                      • 8. Re: EventDispatcher in a Class
                        Peter Lorent Level 2
                        You're welcome.
                        • 9. Re: EventDispatcher in a Class
                          Peter Lorent Level 2
                          Hi David,
                          I hope you and your family are doing fine.
                          Yes, I know Joey's class and in some cases use it. Scope is somewhat of an issue in AS2 (I must have posted a similar answer dozens of times...) and I'm very happy with the changes in AS3. In fact, in general I'm very happy with AS3!
                          But, most clients still want to target FP8... O well, patience is a virtue.