ben_ 0 Light Poster

By now Flash probably has an extension that does this, but since MM/Adobe are incapable of making anything small actually *be* small, here is a very efficient guide to creating handy drop down menus using ActionScript.

This has been taken with permission from my site.

Drop down menus are good. They give you the ability to cram a whole bunch of links into a smaller space, allowing you the maximum room for content. In Flash, they're a little complicated, but you'll be able to make one after you read all of this.

As always with Flash, there's two ways you can do things: you can Actionscript the lot, or you can do it 'on the stage'. I'll take you through doing it with Actionscript. There are benefits to both approaches - but - changes are a lot easier to apply to everything when it's just a pile of code compared to going through 50 clips, plus I'm good at Actionscript, and it's more efficient.

View a demo

Preparing ourselves
The first thing to do is work out what exactly a drop down menu consists of. I'll save you the trouble, and tell you! Each 'menu' consists of 3 things. There's a container clip, the menu button and it's submenu buttons.

Screenshot
[img]http://www.thecodebehind.com/imagebank/ben/dropdown1.gif[/img]

Setting up our Drop Down Menu
You can do this with a single button movieclip, but if you use two then you can have a different affect/appearance/transition for the submenu buttons. I use two in the example, the main menu items are physically on the stage, and the submenu items get attached by code.

The buttons are actually movieclips. I'm fond of using movieclips for buttons because it provides much easier access to the contents of the button. All a 'Button' actually provides is direct up/over/down/hit states, which are easy to implement anyway.

So, we create our two buttons:
[img]http://www.thecodebehind.com/imagebank/ben/dropdown2.gif[/img]

Because we're doing this with Actionscript, we need to 'share' the movies in the library. This way you can attachMovie the buttons to create our menus. To share the movie, in the library right click on it, select Linkage, type in a unique name for it. The name you give it is what you reference when you do an attachMovie.

You can apply a mouseover / mouseout effect easily, by putting your button across two frames.

The textfield in the button is Dynamic. This way we can set the text to whatever we want, and only need one button instead of 'one button for each item'.

The Actionscript

// this array describes the menu.  each 'drop down' 
// is an element of the array

var Menus = new Array();
Menus[0] = ["Main Menu #1", "Sub Menu #1a", "Sub Menu #1b", "SubMenu #1c">;
Menus[1] = ["Main Menu #2", "Sub Menu #2a", "Sub Menu #2b", "SubMenu #2c", "SubMenu #2d", "SubMenu #2e">;

// this array describes what's going to happen
// when you click on a menu.  this example is just
// going to do a 'ContentClip.gotoAndPlay' on whatever's 
// referenced here
var Actions = new Array();
Actions[0] = ["main", "sub1a", "sub1b", "sub1c">;
Actions[1] = [30, 40, 50, 60, 61, 62];

// this final array holds the 'state' of our menus
// initially each element is false, but when a
// menu is 'opened' its corresponding element
// here is set to true.  this is used to 'close'
// the menus
var MenuStates = new Array();
for(var i=0; i<Menus.length; i++) MenuStates[ i ] = false;


// create our menus
// ----------------
// first we have to go through each element
// in the Menus array

// after this loop has finished, our menus
// will physically exist on the movie.
for(var i=0; i<Menus.length; i++)
{
    // create our menu holder clip
    _root.createEmptyMovieClip("Menu" + i, 1500+i);
    
    // create a shortcut reference
    var m = _root["Menu"+i];
    
    // position our menu
    m._x = i * 120;
    m._y = 0;
    
    // store a reference to the 'Menu' element of our button
    m.index = i;    
    
    // create the main button
    m.attachMovie("MainMenu", "Main", 1);
    m.Main._y = 0;
    m.Main._x = 0;    
    m.Main.Label.text = Menus[0];
    m.Main.onRollOver = mainover;
    m.Main.onRollOut = up;
    m.Main.onRelease = click;
    
    // store a refernce to the frame we go to when clicked
    m.Main.targetframe = Actions[0];    
        
    // now create our submenu buttons
    for(var j=1; j<Menus.length; j++)
    {
        // create the button
        m.attachMovie("SubMenu", "Btn" + j, 5+j);
        
        // shortcut reference
        var b = m["Btn"+j];
        
        // set up the properties
        b._y = j * 20;
        b._x = 0;    
        b.Label.text = Menus[j];
        b.onRollOver = over;
        b.onRollOut = up;
        
        // store a refernce to the frame we go to when clicked
        b.targetframe = Actions[j];
        
        // assign our click function
        b.onRelease = click;
        
        // hide our button for now
        b._visible = false;
    }
}

// displays a submenu when you hover over a menu
function mainover()
{
    var index = this._parent.index;
    
    // we now need to walk through our Menus array and make the buttons visible
    for(var i=1; i<Menus[index].length; i++)
    {
        this._parent["Btn"+i]._visible = true;
    }
    
    // update MenuStates
    MenuStates[index] = true;
}

// close a submenu
function closemenu(menu)
{
    var index = menu.index;
    
    for(var i=1; i<Menus[index].length; i++)
    {
        menu["Btn"+i]._visible = false;
    }    
    
    MenuStates[index] = false;
}


// simple over, up and click functions for the buttons
function click()
{
    var t = this.targetframe;
    trace("SomeContentClip.gotoAndStop("+t+")");
    
    // now close our menu
    closemenu(this._parent);

}

function over()
{
    this.gotoAndStop(2);
}

function up()
{
    this.gotoAndStop(1);
}

// our menu is done now, except for closing the menus
// we have a problem there - how do we close a menu?
// if we put an event on the 'wrapping' MenuX clip,
// it'll override the buttons.  if we put an event
// on a specific button, it'll only affect that button.

// the answer is - a mouse listener & a hitTest
// function coupled with the values of our MenuState
// array.

var mouseout = new Object();
mouseout.onMouseMove = function()
{
    // go through each 
    for(var i=0; i<MenuStates.length; i++)
    {
        if(MenuStates == true)
        {
            var activemenu = _root["Menu"+i];
            var xmouse = _root._xmouse;
            var ymouse = _root._ymouse;
            
            // see if we're off the menu
            if(!activemenu.hitTest(_root._xmouse, _root._ymouse, true))
            {
                // we're outside the x/y width/height bounds of the menu
                CloseMenu(activemenu);
                MenusActive[ i ][1] = false;
            }
        }
    }
}

Mouse.addListener(mouseout);