ActionScript 3 Vertical & Horizontal Accordion Menu
This example extends and supersedes an earlier version of this file I wrote about a year ago. I always wanted to make a horizontal version and extend the class, making it more flexible and useful to people.
As was the previous menu, this menu is a Class based ActionScript 3 Accordion Menu, with either a rollOver/RollOff activation scheme for a onRelease activation scheme. I also added in a better extended event class which allows you to control, or respond to all menu activity via events.
Class Features
- Vertical or Horizontal Menu Orientation
- Visible or invisible Menu Bar
- Supports parsing functions passed to each menu item
- Control
- Menu Spacing
- MenuBar colour / RollOver/Off colour
- Menu text format
- Menu tween speed
- Menu easing type
- MenuBar width, height, visibility
- Menu Click behaviour
- Disable / Enable Menu
- Open Particular Panels
- etc, etc.
- Menu attributes are applicable on a per menu item basis
The only thing I have left to add is support for passing in custom menuBar assets. Thats if people would like that to be added?
View Example
http://noponies.com/dev/as3_accordion/
Source Files
http://www.blog.noponies.com/wp-content/uploads/npaccordion.zip
Dependencies
TweenLite - http://www.tweenlite.com
Class ActionScript
* Copyright 2008 noponies.
*/
package noponies.ui{
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.display.Shape;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;
import flash.text.AntiAliasType;
import fl.motion.easing.*;
//non internal imports
import gs.TweenLite;
import noponies.ui.events.NpAccordionEvent;
import noponies.ui.NpAccordionPaneV;
import noponies.ui.NpAccordionPaneH;
/**
* <strong>NpAccordion</strong>
* <p>This menu system was written as a means to display content in a condensed manner. Menus can be either vertical or horizontal. Supports mulitple columns.</p>
* <p>Simple XML based accordion menu. Menu acts as a content space minimiser, with content hidden behind menu bar items. Content
* slides into view when the menu item is clicked on. However, you can pass it any display objects, derived how you like. </p>
* <p>Menu supports parsing function calls passed as a string value , along with parameter support for these functions. This is useful for perhaps
* calling a function on the parent timeline of the menu. Menu also supports a standard URL call passed to it.</p>
* <p>Menu supports any DisplayObject. Loaded swfs can contain their own interactivity. </p>
* <p>Menu supports using either the whole menu or just the menu bar as the mechansim for sliding the menu up and down. Generally it is better to only use
* the bar if you want to include interactivity in the menu items.</p>
* <p>Positioning menu:To create a column, or otherwise change menu item positions, set either the menuPosX or menuPosY values, like so, menuInstanceVarName.menuPosX = newValue</p>
* <p>Menu supports custom events, so that individual menu instances can be targetted. Doing so relies on the <code>NpAccordionEvent</code> Class, which allows for the passing
* of parameters to each menu item. This param is checked against the ID var of each menu, if they match, then the menu acts on the event.</p>
* <p>Class requires TweenLite <a href="http://blog.greensock.com/tweenliteas3" target="_blank">http://blog.greensock.com/tweenliteas3</a><p>
* <b>Author:</b> noponies - <a href="http://www.blog.noponies.com/" target="_blank">www.blog.noponies.com</a><br />
* <b>Class version:</b> 1<br />
* <b>Actionscript version:</b> 3.0 Player Version 9.0.28<br />
* <b>Copyright:</b>
* Creative Commons AttCreative Commons Attribution 3.0 New Zealand License<br />
* <a href="http://creativecommons.org/licenses/by/3.0/nz/" target="_blank">http://creativecommons.org/licenses/by/3.0/nz/</a><br />
* You can use this class how you like, except as a base for Flash Components or for Flash Template sites.<br />
* <br />
* <b>Date:</b> 17 July 2008<br />
*/
public class NpAccordion extends Sprite {
private var menuOrientation:String = "horizontal"
private var clickMode:Boolean = true
private var counter:int
private var menuItems:Array
private var menuPosY:int = 0;
private var menuPosX:int = 0;
private var menuPadding:int = 5;//space between menu items
private var barHeight:int = 10//default
private var barWidth:int = 10
private var menuTxtFormat:TextFormat
private var menuEnabled:Boolean =true//defaut, is the menu as a whole disable from mouse interactivity
private var speed:Number = .5;//menu transition speed - in seconds
private var useWholeMenu:Boolean = false;//default
private var menuColour:uint = 0x000000;//menu bars colour
private var menuAlpha:Number = 1//default
private var useHighLighting:Boolean = true;//change colours of bar on rollOver?
private var menuHighlightColour:int = 0xCCCCCC;//menu rollover colour
private var easeType:Function = fl.motion.easing.Linear.easeNone //default ease type
//action handling
private var contentHasAction:Boolean = true//default
private var contentActionScope:Object //scope that actions run within when applying actions internally
private var handleActionsExternally:Boolean = true//default
/**
* Get / Set whether or not to change the colour of the menu bar with a rollOver. A value of <code>true</code> enables this feature.
* @param Boolean
* @default true
* @return Boolean
*/
public function get setMenuX():int {
return menuPosX;
}
/**
* @private
*/
public function set setMenuX(newMenuPosX:int):void {
menuPosX = newMenuPosX;
}
/**
* Get / Set whether or not to change the colour of the menu bar with a rollOver. A value of <code>true</code> enables this feature.
* @param Boolean
* @default true
* @return Boolean
*/
public function get setMenuY():int {
return menuPosY;
}
/**
* @private
*/
public function set setMenuY(newMenuPosY:int):void {
menuPosY = newMenuPosY;
}
/**
* Get / Set the padding between each menu item.
* @param int
* @default 5
* @return int
*/
public function get menuSpacing():int {
return menuPadding;
}
/**
* @private
*/
public function set menuSpacing(newMenuPadding:int):void {
menuPadding = newMenuPadding;
}
/**
* Get / Set if the menus respond to interactivity. Use this property when loading a menu set and you want to disable a user clicking on menu items until all
* content has loaded, or some other event occurs. If you set this property, dispatch a <code>NpAccordionEvent.ENABLE_MENU</code> event to enable menu interactivity globally.
* @param Boolean
* @default true
* @return Boolean
* @see noponies.accordion.events.NpAccordionEvent#DISABLE_MENU
* @see noponies.accordion.events.NpAccordionEvent#ENABLE_MENU
*/
public function get menusEnabled():Boolean {
return menuEnabled;
}
/**
* @private
*/
public function set menusEnabled( newMenuEnabled:Boolean):void {
menuEnabled = newMenuEnabled;
}
/**
* Get / Set whether or not to change the colour of the menu bar with a rollOver. A value of <code>true</code> enables this feature.
* @param Boolean
* @default true
* @return Boolean
*/
public function get highLightMenuBar():Boolean {
return useHighLighting;
}
/**
* @private
*/
public function set highLightMenuBar(newHigh:Boolean):void {
useHighLighting = newHigh;
}
/**
* Get / Set the colour to use when you have enabled the <code>highLightMenu<code> property.
* @param uint
* @default 0xCCCCCC (light grey)
* @return uint
*/
public function get highLightColour():uint {
return menuHighlightColour;
}
/**
* @private
*/
public function set highLightColour(newCol:uint):void {
menuHighlightColour = newCol;
}
/**
* Get / Set the tween speed of the menus opening and closing.
* @param Number representing the speed in seconds for menu opening and closing tweens.
* @default .5
* @return Number
*/
public function get tweenSpeed():Number {
return speed;
}
/**
* @private
*/
public function set tweenSpeed(newSpeed:Number):void {
speed = newSpeed;
}
/**
* Get / Set the height of the menu bar in pixels.
* <p>The impact of this setting depends on how you are displaying your menus. If you have chosen to display a <em>horizontal</em> (menu slides across x axis)
* menu, then this setting controls how far across the side of your content the menuBar displays.
* If you want it to match the height of your content, set it to <code>0</code>. If you are displaying your menu as a <em>vertical</em> menu, then this setting controls the visible height
* of the menuBar. Setting the menuBarAlpha to <code>0</code> will make your menuBar invisible.
* @param int
* @default 10
* @return int
* @see #menuBarAlpha
* @see #menuBarWidth
*/
public function get menuBarHeight():int {
return barHeight;
}
/**
* @private
*/
public function set menuBarHeight(newBarHeight:int):void {
barHeight = newBarHeight;
}
/**
* Get / Set the width of the menu bar in pixels.
* <p>The impact of this setting depends on how you are displaying your menus. If you have chosen to display a <em>horizontal</em> (menu slides across x axis)
* menu, then this setting controls the visible width of the menuBar. If you are displaying your menu as a <em>vertical</em> menu, then this setting
* controls how far across the top of your content the menuBar displays. If you want it to match the width of your content, set it to <code>0</code>.
* Setting the menuBarAlpha to <code>0</code> will make your menuBar invisible.
* @param int
* @default 10
* @return int
* @see #menuBarHeight
* @see #menuBarAlpha
*/
public function get menuBarWidth():int {
return barWidth;
}
/**
* @private
*/
public function set menuBarWidth(newBarWidth:int):void {
barWidth = newBarWidth;
}
/**
* Get / Set the colour of the menu bar.
* @param uint
* @default 0x000000 (black)
* @return uint
*/
public function get menuBarColour():uint {
return menuColour;
}
/**
* @private
*/
public function set menuBarColour(newMenuColour:uint):void {
menuColour = newMenuColour;
}
/**
* Get / Set the alpha levels of the menu bar.
* <p>A technique you can employ here is to set the menu bars alpha to 0, so that your content will be visible. You may also wish to adjust the <code>menuBarHeight</code> property, as this will
* control how much of your content is visible.</p>
* @param Number
* @default 1
* @return Number
* @see #menuBarWidth
* @see #menuBarHeight
*/
public function get menuBarAlpha():Number {
return menuAlpha;
}
/**
* @private
*/
public function set menuBarAlpha(newMenuAlpha:Number):void {
menuAlpha = newMenuAlpha;
}
/**
* Get / Set how a the menu item and menu content respond to clicks. A value of <code>false</code> enables mouseEvent.CLICK interactivity on the menu bar alone. This is the setting you would use if your content
* itself had interactivity. A value of <code>true</code> enables mouseEvent.CLICK interactivity on the entire menu item.
* @param Boolean
* @default false
* @return Boolean
*/
public function get globalMenuClick():Boolean {
return useWholeMenu;
}
/**
* @private
*/
public function set globalMenuClick(newUseWholeMenu:Boolean):void {
useWholeMenu = newUseWholeMenu;
}
/**
* Get / Set how a the menu will handle any actions passed to it. A value of <code>true</code> will dispatch all actions via the <code>NpAccordionEvent.PRESS</code> event. You can access this events
* <code>menuAction</code> property to parse what action the menu item contained. This property is sent in String form. A value of <code>false</code> will make the menu run the actions internally.
* @param Boolean
* @default true
* @return Boolean
* @see #actionScope
*/
public function get delegateActions():Boolean {
return handleActionsExternally;
}
/**
* @private
*/
public function set delegateActions(newDispatchMenuActions:Boolean):void {
handleActionsExternally = newDispatchMenuActions;
}
/**
* Change the way actions are fired off a menu item. Setting this value to <code>true</code> will make the contentItem itself, rather than the menu bar fire any actions you may have set.
* A value of <code>false</code> will make menu actions fire from a CLICK on the menu bar. This means that a user has to first click on the bar to open the menu item, then click on any content it may have.
* @param Boolean
* @default true
* @return Boolean
* @see #actionScope
* @see #delegateActions
*/
public function get contentActions():Boolean {
return contentHasAction;
}
/**
* @private
*/
public function set contentActions(newContentAction:Boolean):void {
contentHasAction = newContentAction;
}
/**
* Set the scope that internally applied actions run within. By default this is set to the parent object of each menu item. Set this property of you want actions to run internally in another scope.
* @param Object
* @default menuItem.parent
* @return Object
* @see #delegateActions
*/
public function get actionScope():Object {
return contentActionScope;
}
/**
* @private
*/
public function set actionScope(newActionScope:Object):void {
contentActionScope = newActionScope;
}
/**
* Set the textformat that the menu items will use for their text display. If you do not pass in a TextFormat Object the class defaults to using 10 pt, white _sans for any menu text. By default the menu
* textField is set to use embedded fonts. This setting affects the defaultTextFormat property of the menus textField. So, once this is set, future text assignments will inherit that text format.
* @param Textformat
* @default null
* @return
*/
public function set menuTextFormat(newFormat:TextFormat):void {
menuTxtFormat = newFormat;
}
/**
* Set the ease type that the menus use when moving. This parameter is in the form of a <code>fl.motion.easing.Elastic.easeInOut</code>. The default is a <code>fl.motion.easing.Linear.easeNone</code>, or no easing.
* @param Function
* @default fl.motion.easing.Linear.easeNone
* @return
*/
public function set menuEaseType(newEaseType:Function):void {
easeType = newEaseType;
}
/**
* Get the current menu items as an array of Class Objects representing each menu item created by this Class.
* @return Array
*/
public function get currentMenuArray():Array {
return menuItems
}
//--------------------------------------
// CONSTRUCTOR
//--------------------------------------
/**
* Please review the various Getter / Setter Methods for controlling the look, feel and behaviour of the Accordion Menu.
* <p>To control the properties of individual menu items, set the menu items properties before you call the <code>addPanel()</code> method!</p>
* <p>Make sure you pay attention to the <code>menuBarHeight</code> and the <code>menuBarWidth</code> properties when switching between vertical or horizontally displaying menus.</p>
* <p>Should you need access to the current active menu items ID, or its menuBar Sprite or menuBar textField please review the various events and event parameters that allow for this access</p>
* @param mouseMode String. <strong>Optional (Default: click)</strong> Controls the click or rollOver action of the menu. A value of <code>click</code> makes the menu open in response to Mouse Clicks. A value of <code>rollover</code> makes the menu open and close in reponse to
* a user rolling over and off individual menu items.
* @param menuOrientation String. <strong>Optional (Default: vertical)</strong> String representing the click action of the menu item. This can be either a http URL or a function with parameters. In this format <code>Function Name, param, param</code>
* @see #globalMenuClick
* @see #menusEnabled
* @see #menuColour
* @see #menuBarAlpha
* @see #menuBarHeight
* @see #menuBarWidth
* @see #menuSpacing
* @see #tweenSpeed
* @see #actionScope
* @see #delegateActions
* @see #contentActions
* @see #menuTextFormat
* @see #menuEaseType
*/
public function NpAccordion(mouseMode:String ="click", menuOrientation:String ="vertical") {
//validate menu mode
switch (mouseMode) {
case "click" :
clickMode = true
break;
case "rollover" :
clickMode = false
break
default:
throw new Error("Problem :The mouseMode parameter passed is incorrect. It must be either 'click' or 'rollover'!"+ " You passed '"+mouseMode+"'");
}
//validate menuOrientation
switch (menuOrientation) {
case "horizontal" :
this.menuOrientation = menuOrientation
break;
case "vertical" :
this.menuOrientation = menuOrientation
break
default:
throw new Error("Problem :The menuOrientation parameter passed is incorrect. It must be either 'horizontal' or 'vertical'!"+ " You passed '"+menuOrientation+"'");
}
menuItems = []
addEventListener(Event.REMOVED_FROM_STAGE, handleStageRemoval)
}
//--------------------------------------
// ADDPANEL METHOD - ADD A MENU PANEL TO THE ACCORDION MENU
//--------------------------------------
/**
* The addPanel Method adds an accordion panel (via an instance of the NpAccordionPane Class) to an instance of the NpAccordion Class.
* <p>To control the properties of individual menu items, set the menu items properties before you call the <code>addPanel()</code> method!</p>
* @param loadedContent DisplayObject. The content you want to place within an NpAccordion Menu item.
* @param titleText String. <strong>Optional</strong> String representing the text of the menu bar.
* @param action String. <strong>Optional</strong> String representing the click action of the menu item. This can be either a http URL or a function with parameters. In this format <code>Function Name, param, param</code>
* @see #globalMenuClick
* @see #menusEnabled
* @see #menuColour
* @see #menuBarAlpha
* @see #menuBarHeight
* @see #menuBarWidth
* @see #menuSpacing
* @see #tweenSpeed
* @see #actionScope
* @see #delegateActions
* @see #contentActions
* @see #menuTextFormat
* @see #menuEaseType
*/
public function addPanel(loadedContent:DisplayObject, titleText:String="", action:String=""):void {
var ClassSwitch:Class
if(menuOrientation=="vertical"){
ClassSwitch = NpAccordionPaneV
}else{
ClassSwitch = NpAccordionPaneH
}
var menuItem:Object = new ClassSwitch(loadedContent, counter, titleText, action);
//set menu properties before it draws itself to stage
menuItem._clickMode = clickMode
menuItem.x = menuPosX
menuItem.y = menuPosY
menuItem._barHeight = barHeight
menuItem._barWidth = barWidth
menuItem._menuTxtFormat = menuTxtFormat
menuItem._menuEnabled = menuEnabled
menuItem._speed = speed
menuItem._useWholeMenu = useWholeMenu
menuItem._menuColour = menuColour
menuItem._menuAlpha = menuAlpha
menuItem._useHighLighting = useHighLighting
menuItem._menuHighlightColour = menuHighlightColour
menuItem._easeType = easeType
//action handling
menuItem._contentHasAction = contentHasAction
menuItem._contentActionScope = contentActionScope
menuItem._handleActionsExternally = handleActionsExternally
if(menuOrientation=="vertical"){
menuPosY += (barHeight+menuPadding);//positioning of menu, vertically = barheight + menu padding
}else{
menuPosX += (barWidth+menuPadding);//positioning of menu, horizontally = barwidth + menu padding
}
addChild(DisplayObject(menuItem))
//push menu instances into array
menuItems.push(menuItem)
//increment counter
counter++
}
//--------------------------------------
// OPENPANEL METHOD - OPEN A PANEL IN THE ACCORDION MENU
//--------------------------------------
/**
* This public method will open a particular menu panel.
* @param int Representing the menu panel you would like to open. Menus are stored as a zero based array. Some error checking is conducted to test if the menu requested is within the range of available menu items.
* <p>The same effect can be achieved by dispatching a <code>NpAccordionEvent.EXPAND_MENU</code> event at the Accordion Class instance.</p>
* @see noponies.accordion.events.NpAccordionEvent#EXPAND_MENU
* @return
*/
public function openPanel(menuToOpen:int):void {
if(menuToOpen>menuItems.length || menuToOpen<0){
throw new Error("Passed menu index is out of bounds!");
}else{
menuItems[menuToOpen].openPane()
}
}
//--------------------------------------
// CLOSEPANEL METHOD - CLOSE ANY OPEN PANEL IN THE ACCORDION MENU
//--------------------------------------
/**
* This public method will close any open menu panels.
* <p>The same effect can be achieved by dispatching a <code>NpAccordionEvent.RESETALL</code> event at the Accordion Class instance.</p>
* @see noponies.accordion.events.NpAccordionEvent#RESETALL
* @return
*/
public function closePanel():void {
dispatchEvent(new NpAccordionEvent(NpAccordionEvent.RESETALL,true, false));
}
//--------------------------------------
// REMOVED FROM STAGE HANDLER
//--------------------------------------
private function handleStageRemoval(event:Event):void {
menuItems = []
counter=0
}
}
}