In this article, you will learn how to build this simple dropdown menu in Flash using Actionscript 3.0:
Download Starter File (For the finished file of the above menu, see the end of the second page of this article).
This article takes off where the Movie Clip Buttons article left off. So it would be helpful to read that article first. Also, if you haven't already downloaded the finished file from that article, I've provided the above download link for you to do so, as it will serve as our starter file for this one. So, having downloaded that, go ahead and open it in Flash, and let's begin!
You should now have the starter file "mcb.fla" open in Flash.
First, delete the buttons (instances of MCB) from the stage. Select them with the selection tool and press the delete key. Double click the "buttons" layer, and rename it "menu." Click on frame 1 of the actions layer and press F9 for the actions panel. Select all the code (CTRL-A) and press the delete key. Finally, go ahead and lock the actions layer. Locking the layer doesn't prevent you from adding code to the actions panel, but it does prevent you from inadvertently adding graphics to your actions layer.
Now click on the menu layer. Now the file is emptied of code and content and we're ready to start afresh. The MCB symbol we will use as a bulding block is still in the library, though. This symbol, as you no doubt recall, is just a movie clip button with some built in rollover behavior, and a dynamic textbox named "myText" that serves a label.
Next, go to Flash's Insert menu, and choose "New Symbol." Name the new symbol "Panel," make sure it's a MovieClip type, and click OK. You will now be in Panel's edit mode. Here we are going to create the panel that will move up and down inside the menu. The panel will be composed of however many movie clip buttons that you want. I am going to use four, but if you want to, you can build a menu with more (or fewer) choices. Drag four MCB's from the library to the stage. Align the first one to the left and top, placing it at 0, 0 (the registration point of this clip). Next, stack the other three immediately beneath the first one. Your screen should look like this:

The only other thing to do inside this Panel movie clip is to give the movie clip buttons instance names. Name them b1, b2, b3, and b4. Now the Panel movie clip is complete.
Next, go to Flash's Insert menu again, and once again choose "New Symbol" (it's not necessary to go back to scene 1 first, although you can). Name this new symbol "Menu," make sure it's a MovieClip type, and click OK. Now you are in Menu's edit mode. Let's build this menu from the back to the front, locking layers as we go. Rename Layer 1 to "panel." Drag an instance of the Panel MovieClip to the stage. In the properties panel, align it to the left by setting its X property to 0. But give the Y property a value of -96. This Y position will set up the panel to emerge from the bottom of the finished menu. Also in the properties panel, give this instance the name "panel." Your screen should now look like this:

Lock the panel layer, then press the "Insert layer" button to create a new layer. Name this new layer "mask." Choose the rectangle tool. Choose any color, but don't use any stroke. Draw a rectangle of any size. Next, click the rectangle you just drew to select it. In the properties panel, give its properties these values: W: 156, H: 134, X: -3, Y: 34. Lock this layer. Right click on this layer and choose "Mask" from the context menu. This will make this layer a mask layer. It will also automatically lock the layer, and you will see the masking in action. That is, the panel will seem to disappear. Have no fear, it is still there. Your screen will now look like this:

Click the "Insert layer" button again. Name the new layer "heading." Drag another MCB instance to the stage and place it at 0, 0. Give it an instance name of "heading." This clip is the one that will be seen when the menu is closed, and the panel will go up and down behind it. Lock this layer.
Add a new layer and name it actions. Go ahead and lock it. All the layers are now in place. Your screen should now look like this:

Click on frame 1. Press F9 to get the actions panel. Now we'll proceed to define the actions that will be built in to this menu. When you code things like this, you will start to get a feel for which actions ought to be built in, and which should be imposed from the outside. Basically, you want to build in whatever behavior you want for all menus. So the opening and closing of the menu when rollover / rollout happens is in. But any specific actions when the panel buttons are clicked are out. These will be defined from outside code. That way the menu is reusuable.
To make the menu's panel move up and down, we will use the Tween class. The Tween class is in the fl package, so it must be imported. In case you didn't know, in a fla file you can use classes from the flash package without importing, but any classes from the fl package must be imported. Anyway, start off with these lines:
import fl.transitions.Tween; import fl.transitions.easing.*;
Next, we are going to need a couple of variables for the Tweens. So let's go ahead and declare a Tween variable for each of the Tween motions we need. The "openTween" and "closeTween" variables will be for opening and closing the menu:
var openTween:Tween; var closeTween:Tween;
Next, let's add event listeners for the ROLL_OVER and ROLL_OUT mouse events:
addEventListener(MouseEvent.ROLL_OVER, over); addEventListener(MouseEvent.ROLL_OUT, out);
Notice that the addEventListener method isn't preceded with any object name or anything. That is because we are adding the event listener to the object that we're inside of. So the keyword "this" is implied. We're inside this object writing the code so we're adding the event listener to this object (the menu). Now we need to write the over and out handler functions. Let's take on the over handler function first.
We know that in the over function, we want the menu's panel to tween to the open position. The fully open position is going to be when the panel's top edge is even with the heading clip's bottom edge, right? So, let's set about translating that to code. But first, if you have never used the Tween class before, you need to know what each of its seven parameters means:
new Tween(object, property, easeFunction, start, stop, duration, useSeconds);
Let's just begin working this parameter list as it applies to our panel movie clip:
The object we are tweening is obviously the panel. Don't use any quotes around this name, as this parameter is specifying an object, so we need to provide the object's instance name here. The property is the "y" property of panel. We want the animation to take place in the y direction (up and down) and so we will be tweening the y property. The easing function will be None.easeNone, so we are basically specifying to not use easing.
The start parameter here is interesting. We not only don't code a hard number here, but we use panel.y for a parameter. This is basically saying "whatever the value of it is now." This way, the Tween will take the panel from it's current y location, wherever that may be. So even if the panel was in the process of closing due to a previous ROLL_OUT event, it will tween beginning from it's current y position.
The stop parameter is where we are tweening to. It's handy to be able to use the heading object's properties here, because we want the tween to finish precisely at the bottom edge of the heading clip. So we use heading's y property plus heading's height property. The - 3 at the end there is just to make up for the fact that our MCB clips all have a three pixel stroke.
The duration is 0.5, or half a second. Finally, the useSeconds parameter is set to true, because the previous parameter, 0.5, was intended to be expressed in seconds, not frames.
Let's take all of the above, and write it into the over function:
function over(event:MouseEvent):void { openTween = new Tween(panel, "y", None.easeNone, panel.y, heading.y + heading.height - 3, 0.5, true); }
Note: you may prefer that all of this appear on one line. I have formatted it this way because it fits this screen much better. Either way will work inside of Flash. On the other hand, seeing the seven parameters in a list like this can also be helpful.
The out function is similar. Only the stop parameter is different. Once again, the start parameter is set to whatever the current value is:
function out(event:MouseEvent):void { closeTween = new Tween(panel, "y", None.easeNone, panel.y, heading.y + heading.height - panel.height, 0.5, true); }
The stop parameter this time once again uses the heading clip for a handy anchor reference. Taking the value of the heading's y property, plus it's height, gives you the bottom edge of the heading. Then, subtracting the height of the panel from this should give you back the place where the panel originally started. And that is where we are tweening the panel to.
And that should conclude the work on the menu. Go back to scene 1. Click on the Menu layer. Drag out an instance of the Menu movie clip and place it on the stage. Test the movie (CTRL-ENTER). Try rolling over the menu and rolling out. It should open and close for you. If you were to drag out more instances from the library, they will all exhibit this opening and closing behavior, because it's built in.
On the next page, we will proceed to program this menu instance from the outside code.
Now, let's proceed to customize the dropdown menu by giving all the movie clip buttons in it some labels, and giving them some actions to perform when they are clicked.
You should be back at the main timeline (Scene 1). Click on the menu instance, and give it an instance name in the properties panel. For our present purposes, just name it "menu." Now click on frame 1 of the actions layer and press F9 to get the actions panel.
Let's begin by giving the heading inside the menu a label. Remember that each MCB instance has a dynamic textfield inside it with an instance name of "myText." So enter the following line of code into the actions panel:
menu.heading.myText.text = "Websites";
Test the movie. You should see the text "Websites" appear on the heading movie clip inside the menu. Next, let's program the text label of the first button of the nested "panel" MovieClip:
menu.panel.b1.myText.text = "Amazon";
Test the movie again. Roll over the menu so that the panel drops down. You will see that this time, no text appears on the first button, and there are no error messages! What could be the problem? Well, it so happens that any time you want to animate text, and any time you want text to appear from behind a mask, you have to embed the text. Here's how to do that:
Double click the MCB symbol in the library. Unlock the text layer. Click on the dynamic textbox "myText" on the stage. In the properties panel, click the Embed button. In the Character Embedding dialog box, choose Uppercase, Lowercase, Numerals, and Punctuation. You can do this by holding down the CTRL key as you click on each choice. When you have selected those four, click OK. Now all those characters will be embedded.
While still in the properties panel, click the "B" button to make the font bold. Lock the text layer again. Now go back to Scene 1. Test the movie. Roll your mouse over the menu. Now the text will show up on the Amazon button, because the font is now embedded. Back in the actions panel, frame 1 of the main timeline, let's proceed to set the labels for the other buttons, too. All the actions so far should look like this:
menu.heading.myText.text = "Websites"; menu.panel.b1.myText.text = "Amazon"; menu.panel.b2.myText.text = "Google"; menu.panel.b3.myText.text = "Yahoo"; menu.panel.b4.myText.text = "Actionscript.org";
Next we will make the nested buttons do something when they receive a click. We could add event listeners to each button. But we can also add one event listener to the whole menu, which, because of the event flow, will also trigger the mouse events coming from the children:
menu1.addEventListener(MouseEvent.CLICK, clickHandler);
It only remains to write the clickHandler function:
function clickHandler(event:MouseEvent):void { if(event.target == menu.panel.b1) { navigateToURL(new URLRequest("http://www.amazon.com")); } if(event.target == menu.panel.b2) { navigateToURL(new URLRequest("http://www.google.com")); } if(event.target == menu.panel.b3) { navigateToURL(new URLRequest("http://www.yahoo.com")); } if(event.target == menu.panel.b4) { navigateToURL(new URLRequest("http://www.actionscript.org")); } }
Ordinarily, using event.target to identify which button was clicked on might cause a problem. The problem is that the nested textfield inside each button could potentially trigger mouse events and be the event target instead of the button itself. But in this case, we've previously already built a movie clip button with a built-in instruction to set mouseChildren to false. So every instance of our custom movie clip button is protected against anything nested inside from receiving mouse events.
Test the movie. The menu should be fully functional now, and each button will open the corresponding web page in your default browser. Here's the download link for the finished file:
This dropdown menu has been coded on the timeline, and has some limitations you should know about. The menu is reusable as it is. You can drag more copies out of the library, give each one a different instance name, and program them with different button labels and different actions when they are clicked. As long as you want menus with four choices each, you can reuse this one.
But imagine that you want a menu with only three choices. You will find that, try as you might, you can't take an instance of this present menu and modify it to have only three choices. The reason is that the menu, and the panel built into it, are templates. They are the master copy. They are a library symbol, which is very analogous to a class. They are the blueprint from which instances are made. Editing their insides affects every instance of them. So it really has to do with what was built in, and what was left to outside code to customize. The idea of a four choice panel was built in to the design, and was not left to the outside code. So our Menu symbol might have been called "Menu With a Panel of Four Choices."
So, let's examine how we can create a new menu with only three choices. Open the finished file (from the end of the previous article page) in Flash. Right click the Menu symbol in the library and choose "duplicate." Change the name from Menu copy to Menu2. Cool! Now there is a duplicate symbol in the library called Menu2. But it is also going to be necessary to duplicate the Panel symbol. So right click it, choose "duplicate," and name the duplicate Panel2.
Now let's edit the inside of the Menu2 symbol. Double click it in the library to go into its edit mode. Unlock the panel layer. Select the panel instance on the stage. Notice that in the properties panel, it says (of course) that it's an instance of Panel. We really want to substitute our new symbol, though, and make this an instance of Panel2 instead. So, right click the instance on the stage. Choose "Swap symbol" from the context menu. Then, just choose Panel2 from the list. Now the panel instance is an instance of Panel2 instead of Panel! By the way, there's no need to change its instance name from panel, because now the nested instance named panel is an instance of Panel2. Get it?
Next, double click the instance of Panel2 on the stage to go into its edit mode. Click the last (bottom) button in the stack to select it. Press the delete key. Now there are only three buttons in the stack. They will still have their instance names (b1, b2, and b3) from before. You can click on each one and verify this. When you duplicate symbols, little details like that get duplicated as well.
Go back to Menu2. It's now going to be necessary to move the panel down one notch because of the button that was removed. Click on the panel. In the properties panel, type -64 in the Y field instead of -96.
Go back to Scene1. Click on the menu layer. Drag out an instance of Menu2. You should have a fully functional three choice menu. Now let's program the new menu with some labels and click actions. First, though, give it an instance name of menu2 in the properties panel. Then, click on the first frame of the actions layer and press F9. Paste in the following additional code:
menu2.heading.myText.text = "Other Sites"; menu2.panel.b1.myText.text = "Twitter"; menu2.panel.b2.myText.text = "You Tube"; menu2.panel.b3.myText.text = "Google News"; menu2.addEventListener(MouseEvent.CLICK, clickHandler2); function clickHandler2(event:MouseEvent):void { if(event.target == menu2.panel.b1) { navigateToURL(new URLRequest("http://www.twitter.com")); } if(event.target == menu2.panel.b2) { navigateToURL(new URLRequest("http://www.youtube.com")); } if(event.target == menu2.panel.b3) { navigateToURL(new URLRequest("http://news.google.com")); } }
And there you have it. Two menus! You can see that it wouldn't be too difficult to just place several of these menus side by side to form a menu bar and have a nice navigation system.
There are also other customizations you can make. For example, using some of the easing methods, you might make a menu that opens and closes (for example) using a bounce effect. You could also change the duration parameter of the closeTween, and, for example, make a menu that closes faster than it opened. I also realize that I didn't spend a whole lot of time designing this, so if you use it, you'll probably want to design some more elaborate and better looking buttons. 
Even more refinements: It might also bother you that the heading MovieClip has a rollover effect, because it's just another instance of MCB (movie clip button), and that rollover effect is built in. If so, just duplicate the MCB symbol, take out the rollover effect, and use your new symbol instead. Don't forget about the handy right-click "swap Symbol" menu choice. You might want a menu that must be clicked before it will open. If that's the case, just edit the menu symbol, and replace the line that adds a ROLL_OVER event listener, and use CLICK instead. Finally, it may bother you that the dropdown is animated (although I kind of like it myself), and you just want it to drop down in a "now you see it, now you don't" fashion. If so, take out the Tween stuff, position the panel clip just below the heading clip, and then just use the visible property to show and hide the panel.
The bottom line is that there are all kinds of ways that you can customize this and make it yours. I was just messing around with it myself and realized it will still work if you rotate it with the free-transform tool--even sideways and upside down! Then, just for fun, I made it mirror image instead:
menu.scaleX *= -1;
You might also wonder why I did this whole project on the timeline, instead of using custom classes. For one thing, I think it's kind of a myth that you can no longer code on the timeline in AS3. There are a lot of things you can do by coding on the timeline! But I also plan later to add another page to this article and demonstrate a dropdown menu class, because I have written one. Meanwhile, if you appreciated this, would you please provide me some feedback (comments)? Thanks!
Hey all!
I just finished writing a new tutorial on making dropdown menus using AS3 classes. Head on over to this page on actionscript.org and check it out: http://www.actionscript.org/resources/articles/979/1/AS3-Dropdown-Menu-w....
You will really like it. If you liked the timeline based menu I described here, I think you will like this one that uses classes way better!
Jody