How to Trigger Event Handlers of Other Objects

ActionScript 2.0

In response to a question in one of the comments to “How to Reference Objects Dynamically,” here’s a code sample that illustrates one way to trigger event handlers of other objects.  Specifically, the commenter had a series of movie clip “buttons,” which had their own MovieClip.onRollOver and onRollOut event handlers.  She wanted to see the rollover and rollout effect without having to put the mouse near those movie clips.  (To put this in perspective, the movie clips in question were thumbnails in a slideshow.  She wanted to highlight the current thumbnail either by hovering over it or selecting it via a set of Prev and Next buttons.)  Let’s take a look. 

An answer (not so short, but sweet — and how it works)

Remember, this is one approach out of, I’m sure, quite a few.  It does make a good example on using the array access operator, in any case ([]).  ;)   Here we go.

Assume two Library assets, here:  one movie clip symbol and one button symbol.  The movie clip should have to frames total, both keyframes.  Make sure there’s a different shape in each keyframe.  You might draw a circle in frame 1, for example, then add a stroke to that circle in frame 2.  Drag several instances of this movie clip to the Stage and give them sequential instance names — mc0, mc1, mc2, and so on.  Drag the button symbol out twice.  Give one the instance name prev and the other next.  Now enter the following into a scripts layer:

var buttonList:Array = new Array(mc0, mc1, mc2);
for (var i:Number = 0; i < buttonList.length; i++) {
  var mcBtn:MovieClip = buttonList[i];
  mcBtn.stop();
  mcBtn.onRollOver = function():Void {
    this.gotoAndStop(2);
  };
  mcBtn.onRollOut = function():Void {
    this.gotoAndStop(1);
  };
}

First, an arbitrarily named variable, buttonList, is declared and set to an instance of the Array class.  In the above example, I “seeded” the buttonList array with the instance names of three movie clips.  If you have five, use all five.

Next, a for loop counts from zero to less than the number of elements in the array.  In the case of our three elements, i will start at 0 and stop at 2, thus counting through our three buttons (arrays start at zero rather than one).  The next line is a matter of convenience.  An arbitrarily named variable, mcBtn, is set to buttonList[i].  In this context, the array access operator “reaches in” to the array and pulls out the element at the number specified.  On the first go-around, i is zero, so mcBtn will be set to the first item, which happens to be mc0.  This movie clip, represented by mcBtn, is immediately told to stop, via the MovieClip.stop() method.  This keeps mc0 (and all the rest, as the loop continues) from traveling to frame 2, where that stroke appears.  After that, two mouse events are handled.  The mc0 movie clip, by way of the mcBtn reference, is assigned a function to its MovieClip.onRollOver and onRollOut events.  When the mouse rolls over this movie clip, it will go to frame 2 and stop; when the mouse rolls out, the movie clip will return to frame 1.  This will give a nice rollover effect of a stroke appearing and disappearing from the circle.

Looping like this allows us to assign this functionality to all the movie clips referenced in the buttonList array.  There’s another way to do this, which uses strings in the array rather than actual object references.  In that case, as described in “How to Reference Objects Dynamically,” the array access operator is used slightly differently.

But this is all setup!  Here’s the fun part.  Add a bit more ActionScript:

var current:Number = 0;
prev.onRelease = function():Void {
  current--;
  if (current < 0) {
    current = buttonList.length - 1;
  }
  turnAllOff();
  buttonList[current].onRollOver();
};

Here, we keep track of which movie clip “button” should be the current one.  Just a simple number variable, current, set to zero by default.  The prev button instance is assigned a function to its Button.onRelease event.  This function reduces current by one.  The first time this ever happens, current would now be -1.  An if statement checks the value of current.  If less than zero (which it currently is), that variable is set to buttonList.length – 1, which, in our case, makes it 2 — that’s three elements in the array, minus 1.  Next, a custom turnAllOff() function is called (we’ll get to that in a moment).  Finally, movie clip mc2 is referenced by way of the buttonList array, using current in the array access operator.  We’re effectively saying, “Hey, buttonList, what do you have in slot 2?”  buttonList says, “Uh, lemme see.  Ah, mc2.”  “Great!” we say, and use that reference to trigger mc2’s onRollOver event handler.  Remember, at the very beginning, we set mc2.onRollOver to a function, so now we can call that function by invoking onRollOver and adding those parentheses at the end — it’s the parentheses that actually execute the function.  The function, as you recall, “highlights” the movie clip by sending it to frame 2.

So what’s that turnAllOff() function?  All that does is use a for loop to cycle through the movie clips and invoke their MovieClip.onRollOut event handlers:

function turnAllOff():Void {
  for (var i:Number = 0; i < buttonList.length; i++) {
    buttonList[i].onRollOut();
  }
}

Same principle, really.  This just ensures that whatever movie clip might already be highlighted is unhighlighted.

Finally, we need code for the next button.

next.onRelease = function() {
  current++;
  if (current > buttonList.length - 1) {
    current = 0;
  }
  turnAllOff();
  buttonList[current].onRollOver();
};

Jen, I hope that helps!

15 Responses to “How to Trigger Event Handlers of Other Objects”

  1. Jen Says:

    Hey Dave,

    Sorry it’s taken this long to give a response to this and your previous posting. Ma-in-law was visiting, computer time was very limited.

    My goodness, you’ve really outdone yourself here. Reading through this quickly already makes more sense to me than most else on what I’ve read about AS. You’re a great writer and teacher!

    I haven’t had a chance to work this into my own project, but it’s looking like it will get the job done. I will definitely give you an update once I a get a chance to play around with it.

    Thanks a zillion for taking the time to customize an article specifically for my problem. :)
    Jen

  2. David Stiller Says:

    Jen,

    Glad to help. I field a lot of questions in response to this blog and try to write articles that answer the popular ones. Yours happened to overlap with concepts that I believe will be useful to a number of people, so I didn’t especially go out of my way. :)

    Best of luck with your project!

  3. franclin Says:

    Well written. Great explanation. Thanks

    Have you come across a methode in which flash counts the number of object in a folder? I’m guessing this is taboo and Flash security would nix this sort of thing. I’m doing something similar with a photo library and I need a way for flash to count the number of photo’s in the photo folder. Currently I’m updting an XML file every time I add a photo but it would be nice if flash just counted the number of photo’s ahead of time.

    Thought you might know?

  4. David Stiller Says:

    franclin,

    When Flash references objects as described in the above article, those objects may only be interior to the SWF. To accomplish what you’re after, you’ll have to use a server-side script (PHP, ASP, etc.) to gather the names of those files, then pass them along to Flash. You could query that script with something like loadVariables() or an instance of the LoadVars class.

  5. eddie Says:

    how do you get two buttons (button1_mc, button2_mc) to both activate from one mouseover?

    Here is the script for the one button action:

    button1_mc.onRollOver = function () {
    this.gotoAndStop(2);
    }

    I tried something like this but it won’t work.

    button1_mc.onRollOver = function () {
    this.gotoAndStop(2);
    }
    button1_mc2.onRollOver = button1_mc.onRollOver;

    Would be so glad if you could help!

    Thanks

  6. David Stiller Says:

    eddie,

    It looks like your button1_mc is actually a movie clip that is programmed to respond like a button. If that’s so, and if you want both clip “buttons” to go to frame 2 of their own timelines and stop, you could do this:

    button1_mc.onRollOver = function () {
      this.gotoAndStop(2);
      button1_mc2.gotoAndStop(2);
    }
    
    button1_mc2.onRollOver = function () {
      this.gotoAndStop(2);
      button1_mc.gotoAndStop(2);
    }
  7. David Says:

    Thanks, your explanation of dynamic referencing was a godsend. I just wish I had read it sooner!

  8. David Stiller Says:

    David,

    Glad to help! :)

  9. Bill Bond Says:

    Hi Dave, As a newcomer to ActionScript, I’m trying to create a drag and drop quiz, and so far have managed to drag “answers” into “question” targets using variable text to give right or wrong comments. I’ve also got a final score sorted out. What is evading me though, and not for want of experimenting, is the script to have a right or wrong answer trigger a movieClip or animation, and similarly an animation trigger to launch various animations depending on final scores… Sounds like you might be a man who knows… Any help here would be greatly appreciated.

    All the best

    Bill

  10. Riff Says:

    Hi Dave,

    Excellent tutoring!. My problem is I need to control 1 mc with two sets of buttons using arrays. Its an interactive map by which users can rollover 1.country map and/or 2.country name for an interaction.
    The country map increases in size with a rollover and reverts on rollout. The country name buttons also does this.

    I managed to get the rollover country map array to work but cant figure out how to attach the country name to the same interaction. I’m losing sleep over this!

    Appreciate if you could help. Thanks in advance.

  11. David Stiller Says:

    To Bill …

    I’m not clear from your comments if you managed to get Flash to “understand” when an answer has been dragged correctly vs. incorrectly. You said you got the dragging part figured out. I imagine you’re using MovieClip.hitTest(), and then comparing the values of things with an if statement. If so, then triggering movie clips is a matter of referencing the clip in question and invoking its MovieClip.play() method (or gotoAndPlay() or whatever makes sense). To test against scores you might use another if and reference a variety of clips in your else clauses (or a variety of frame labels in a single movie clip).

    There are virtually countless possibilities, of course, but based on your description I’m afraid I can’t envision the particulars of your scenario in my mind.

    To Riff …

    This might sound awful, but here, too, I’m afraid I can’t “see” the mechanics of what’s going on beneath your question. Bill’s scenario and yours may benefit from the topic of this blog entry (triggering events handlers of other objects), but then again, you might both benefit from handling custom dispatched events.

  12. Broc Says:

    Hello David,
    I’d like to thank you for facilitating this complex procedure!

    I’m using this tutorial to build a project, but I’m having trouble altering it to fit my needs. I want to be able to click on a button and have it go to frame 2, also. The problem is that everytime I rollOut, it goes back to frame 1.

    I have a feeling I need a function and conditional in my rollOut event handler. I’ve tried it, but I’m not having much luck.

    I figured you might have some answers.

    Thanks.

  13. David Stiller Says:

    Broc,

    Sure thing. Based on your description, you might try something like this:

    myButton.onRollOut = function():Void {
      if (this._currentframe == 1) {
        // do whatever ...
      }
    }

    That movie clip symbol with the instance name myButton. The if statement checks if the current frame of that button is 1 — if so, it performs whatever you tell it to; if not (because, for example, a previous onPress event has sent it to frame 2), it won’t do anything. Or you could add an else clause for additional instructions.

    Pretty straightforward, as you imagined. :)

    P.S. Because this particular blog entry is entitled “How to Trigger Event Handlers of Other Objects,” I feel I should add that I don’t see (so far) where you might need to trigger event handlers of other objects, but maybe you’ve already got that part solid.

  14. kasim Says:

    Dear sir,
    i want to make one application in flash, i want if i click one button in my department, it should triger one swf file to other department and thre will be one sound,

    hope u will help me,

    regards

    kasim

  15. David Stiller Says:

    kasim,

    In order to trigger actions or responses on someone else’s computer, Flash needs the sort of complex infrastructure provided by something like Flash Media Server. On its own, Flash Play cannot do what you’re hoping for.

Leave a Reply