In this, my first tutorial for Flashtuts+, I’ll quickly explain how to create an object oriented drop down menu. We’ll use ActionScript 3.0 and pull all the necessary data from an xml file.
The resulting menu can be used in any flash file without needing recoding.
Step 1 – Setting the Classpath
First, we’ll setup a classpath. If you dont yet have one, it’s a useful place for putting ActionScript files that you use in every project. This way you dont need to copy the ActionScript files to a folder of the fla document everytime that you create a new website or application.
Create a folder for ActionScripts files in c:. I’ll create the folder c:/myActionScripts, but you can create a directory anywhere you want with any name you wish.
For flash CS3, go to Edit > Preferences. In the category menu of the preferences panel, select "ActionScript". On right side of the panel, click the button "ActionsScript 3.0 settings…".
This will open another panel (Actionscript 3.0 settings panel). Click the plus button ( + ) and type "c:/myActionScripts", or whatever your directory location is. Then just click OK in all the open panels, now we have a classpath.
For flash CS4, go to Edit > Preferences. In the category menu of the preferences panel, select "ActionScript". On right side of the panel, click the button "ActionsScript 3.0 settings…".
This will open a panel called "Actionscript 3.0 Advanced Settings". In the "source path" area, click the plus button ( + ) and type c:/myActionScripts, or whatever your directory location is. Then just click OK in all the open panels, now we have a classpath.
Step 2 – Downloading Classes and Creating Folders
Go to http://blog.greensock.com/tweenliteas3/ and download the TweenLite ActionScript 3.0 class, courtesy of Jack Doyle. This class is much better than the Tween class built in flash CS3 and flash CS4.
When the download is finished, just uncompress the contents of "gs" inside the .zip file to c:/myActionScripts/gs to make the TweenLite class available for use any time you want, without needing to copy the gs folder to an equivalent folder of your project.
Also, create the folder c:/myActionScripts/dropdownmenu. We’ll put the ActionScript files from this tutorial here. We’ll then be able to use our DropDownMenu Object whenever we want, without needing to copy the dropdownmenu folder to each project. This is the advantage of using a classpath.
Step 3 – Creating the XML Documents
I’ll be using 5 xml files, one xml for the main drop down menu and others to populate data in the second drop down menu. Save all the xml files in c:/dropdownexample/xml.
Save the first xml document as "menu.xml" in the folder "xml". Fill it with data such as:
<?xml version="1.0" encoding="utf-8"?> <menu> <item caption="Company contacts" value="xml/contactlist1.xml" /> <item caption="Home contacts" value="xml/contactlist2.xml" /> <item caption="Friends" value="xml/contactlist3.xml" /> <item caption="School contacts" value="xml/contactlist4.xml" /> </menu>
Save a second xml document as "contactlist1.xml" in the xml folder, data as follows:
<?xml version="1.0" encoding="utf-8"?> <menu> <item caption="Director area" value="director@company.com" /> <item caption="Finance area" value="finance@company.com" /> <item caption="Designing area" value="designing@company.com" /> <item caption="Care area" value="care@company.com" /> <item caption="Print area" value="print@company.com" /> <item caption="Internet area" value="internet@company.com" /> <item caption="Knowlege area" value="knowlege@company.com" /> </menu>
Save a third xml document as "contactlist2.xml" in the xml folder, data as follows:
<?xml version="1.0" encoding="utf-8"?> <menu> <item caption="Mom" value="mom@hotmail.com" /> <item caption="Daddy" value="daddy@gmail.com" /> <item caption="Brother" value="brother@live.com" /> <item caption="Syster" value="syster@email.com" /> </menu>
Save another xml document as "contactlist3.xml" in the xml folder, data as follows:
<?xml version="1.0" encoding="utf-8"?> <menu> <item caption="Tim" value="tim@email.com" /> <item caption="Sam" value="sam@hotmail.com" /> <item caption="David" value="david@live.com" /> <item caption="Julio" value="julio@gmail.com" /> <item caption="Lucas" value="lucas@uol.com.br" /> </menu>
Finally, create the last xml document as "contactlist4.xml", again in the xml folder with the following data:
<?xml version="1.0" encoding="utf-8"?> <menu> <item caption="Math teacher" value="math@myschool.com" /> <item caption="English teacher" value="english@myschool.com" /> <item caption="Geography teacher" value="geography@myschool.com" /> <item caption="History teacher" value="hisroty@myschool.com" /> <item caption="Fisic teacher" value="fisic@myschool.com" /> </menu>
Step 4 – Coding the MenuItem Object
Now we’ll start coding the MenuItem Object. This is required for our drop down menu and will build the items in the list.
Start creating the package, we’ll save the file in c:/myActionScripts/dropdownmenu so the package is called "dropdownmenu", then we’ll import the classes that we want to use in this object.
package dropdownmenu{
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.events.*;
import gs.TweenLite;
Now create the class MenuItem. As we’re extending the Sprite class, we’ll have all the methods and properties of that class, but we’ll still add more.
Note that we’ll save this ActionScript file as "MenuItem.as" in the dropdownmenu folder. The package therefore has the same name as the folder and the class has the same name as the .as file.
public class MenuItem extends Sprite{
Declare and set the variables here, so you can use them with any function in the class. We’ll set as them private so only this class has access to them. If you declare the variables inside a function, only that function will have access to the variable. In our case, we want the entire class to have access to the variables.
private var _value:String; private var txt:TextField=new TextField(); private var txtFormat:TextFormat=new TextFormat();
We’ll declare the following function as public, so you can access it from anywhere. This function has the same name as the class It’s the constructor function and will be called when we instantiate this object. It will be the first function to be executed and will be executed every time you create a new object of MenuItem. The constructor function is always public.
We’ll pass the caption, value, width and height values through the constructor:
public function MenuItem(caption:String,value:String,_width:int=200,_height:int=20):void{
Now we’ll set this class to "buttonMode", so it will behave like a button and the hand cursor will show every time you pass the mouse over it. We set the alpha to .8 (this will be the mouse out state) we’ve declared the _value variable before, outside the function, so here we make the value visible to any other function of the class and the _width we reduce by 10, so the menu item will be a little bit smaller.
this.buttonMode=true; this.alpha=.8; _value=value; _width-=10
Draw a black rectangle for the background (this can be any color, just change the 0×000000 to whatever you want).
this.graphics.beginFill(0x000000); this.graphics.drawRect(0,0,_width,_height);
Now we’ll set the text format object. It’s created outside the function and will be accessible to any function in this class. This will be our item caption (a dynamic textfield).
txtFormat.color=0xFFFFFF; txtFormat.size=10; txtFormat.font="Verdana";
Now we’ll set the default textfield format to the text format object. We’ll disable the mouse interactivity of the textfield, so the text wont be clickable (this works with any displayed object). We’ll set the text of txt dynamic text field as the variable "caption" passed through the constructor parameter. Then it’s a question of setting the position x and y of the textfield and its width and height. Then we add the text to the MenuItem Object´s display list.
txt.defaultTextFormat=txtFormat; txt.mouseEnabled=false; txt.text=caption; txt.x=5; txt.y=2; txt.width=_width-10; txt.height=_height-4; addChild(txt);
Now let’s add the events. When we add this object to the stage, the addedToStage function will be called. When we pass the mouse over the object, the mouseOver function will be called. When we take the mouse out of this object the mouseOut function will be called. We also close the constructor function with a "}" at the end.
addEventListener(Event.ADDED_TO_STAGE,addedToStage); addEventListener(MouseEvent.MOUSE_OVER,mouseOver); addEventListener(MouseEvent.MOUSE_OUT,mouseOut); }
Insert a new function here. When the mouse is over the object it will smoothly set the alpha to 1, so this object appears different to the others (mouse over state).
private function mouseOver(e:MouseEvent):void{
new TweenLite(this,1,{alpha:1});
}
When we take the mouse out of the object, the alpha will smoothly be set back to .8 (the mouse out state).
private function mouseOut(e:MouseEvent):void{
new TweenLite(this,1,{alpha:.8});
}
When this object is added to the stage, we set the object’s position by getting its index in the displaylist and multiplying this by its height. We have a sequence of indexes (0, 1, 2, 3) and will position one object upon the other, not over one another.
private function addedToStage(e:Event):void{
this.y=this.parent.getChildIndex(this)*this.height;
}
The function "get" is a property, it works like a variable but it is read only. You cant set those values outside this class, but you can read them. They return the value of variables or textfields which are inaccessible outside the class.
public function get caption():String{ return txt.text; }
public function get value():String{ return _value; }
Now close the class and the package we opened at the start of the file. Save it as "MenuItem.as" at c:/myActionScripts/dropdownmenu, the file should be located at c:/myActionScripts/dropdownmenu/MenuItem.as
} }
Step 5 – Create the Custom Event
Now we’ll create a custom event for this class. When we change the menu item we’ll get the value through this event.
Start the package, import the Event and create the class extending the Event class. Now we have a new Event class which we’ll call "DropDownMenuEvent".
package dropdownmenu{
import flash.events.Event;
public class DropDownMenuEvent extends Event{
Static variables, functions or constants can be accessed without needing to instantiate the object. You don’t need to use the new statement, you can simply access it by using: DropDownMenuEvent.CHANGE
The const are constants. Once you have set a value to the const, its value can’t be changed. You can use lowercase to name constants, but by default almost everbody uses uppercase for constants and we won’t do any different.
public static const CHANGE:String="change";
Instantiate these String objects right here to ensure access from anywhere in this class.
private var _caption:String; private var _value:String;
Now create the constructor function. The super(type) is to set this class as a superclass.
public function DropDownMenuEvent(type:String,caption:String,value:String):void{
super(type);
_caption=caption;
_value=value;
}
Now make the getter functions of the class, to get the values as read only. I´ve explained before how the getter function works.
public function get caption():String{ return _caption; }
public function get value():String{ return _value; }
Close the package and the class using "}" and save as c:/myActionScripts/dropdownmenu/DropDownMenuEvent.as
} }
Step 6 – Create the DropDownMenu Object
I saved this object for last because it´s more complex. Also, it won’t work without the 2 classes created above.
This part is already well explained; we’ll define the package, import all the classes that we’ll use, create the class extending the Sprite, set the variables outside the functions to use with any other function of this class, then start the constructor function. Nothing new here.
I also shouldn’t need to say again that the class, the constructor and the file name are the same.
The constructor function has all the parameters pre-defined, so we can choose whether or not to pass parameters. We could pass just the first parameter, or the first and the second, or the first, the second and the third. We could also pass the first parameter as null, so it will be the same value as the pre-defined value in the constructor.
package dropdownmenu{
import flash.display.Sprite;
import flash.display.Shape;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.xml.*;
import flash.events.*;
import flash.display.Graphics;
import flash.display.GradientType;
import flash.geom.Matrix;
import flash.display.SimpleButton;
import gs.TweenLite;
public class DropDownMenu extends Sprite{
private var container:Sprite=new Sprite();
private var req:URLRequest=new URLRequest();
private var loader:URLLoader=new URLLoader();
private var txt:TextField=new TextField();
private var txtFormat:TextFormat=new TextFormat();
private var button:SimpleButton=new SimpleButton();
private var _value:String;
public function DropDownMenu(url:String=null,_width:int=200,_height:int=30):void{
The container is a sprite, created above outside any function for the entire class have access. We’ll put all the menu items inside the container; set the y property to the _height param. The container will be invisible to begin with(alpha=0), so it can’t be clicked. Even if it were visible, the alpha is still 0, so it won’t show yet.
container.y=_height; container.alpha=0; container.visible=false; addChild(container);
Create a background and add to the object. The drawObject is a function that returns a Shape, we’ll see this a little later.
var bg:Shape=drawObject(_width,_height); addChild(bg);
Again, we set the textFormat object properties and set the defaultTextFormat property of the txt object as the textFormat object. We disable interactivity with the mouse, set a default text while the xml is not loaded yet and add the txt textField to this object display list. All of these actions have been seen before, so they don’t need too much explanation.
txtFormat.bold=true; txtFormat.size=15; txtFormat.font="Verdana"; txt.defaultTextFormat=txtFormat; txt.x=5; txt.y=3; txt.width=_width-10; txt.height=_height-6; txt.mouseEnabled=false; txt.text="XML not loaded"; addChild(txt);
The button, created outside the function, can be acessed from anywhere in this class. We set a new Shape for the hitTestState, then add an event. When clicked it will call for function "open". We then add the button to this object´s display list.
button.hitTestState=drawObject(_width,_height); button.addEventListener(MouseEvent.CLICK,open); addChild(button);
Now add the event listeners. One for the loader when the loader has fully completed loading the xml document. This will call the function loaderComplete, or if the loader doesn’t find the xml document it will call the function loaderIOError
This class when added to the stage will call the function addedToStage. When removed from stage it will call the function removedFromStage.
loader.addEventListener(Event.COMPLETE,loaderComplete); loader.addEventListener(IOErrorEvent.IO_ERROR,loaderIOError); addEventListener(Event.ADDED_TO_STAGE,addedToStage); addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
Here we check if any value other than null was passed to url param of the constructor. If so, we’ll set the url ( private var url:URLRequest=new URLRequest() )and call the function load. Close the constructor function with a " } "
if(url) load(url); }
As the load function is public, it allows you to load xml anywhere outside or inside this class. First this function will remove all the menu items inside the container. If any exist, then it will start loading the xml document.
public function load(url:String):void{
txt.text="Loading";
_value=null;
var total:int=container.numChildren;
for(var i:int=0;i<total;i++){ container.removeChildAt(0); }
req.url=url;
loader.load(req);
}
This function will be called when the button is pressed. It will check if the alpha of the container is equal to zero. If so, it will set the visibility of the container to true, alpha to 0 and will smoothly set the alpha of the container to 1. If the alpha of the container is already more than 0, it will call for the close function.
private function open(e:MouseEvent):void{
if(container.alpha==0){
container.visible=true;
container.alpha=0;
new TweenLite(container,.5,{alpha:1});
}
else{ close(); }
}
The close function will be called when you click anywhere, because we’ll add an event to the stage for when the mouse is down. This function will check if a container´s alpha is more than 0. If that’s the case it will smoothly set the container´s alpha to 0. When finished it will call the function hideContainer() that sets the container´s visibility to false (invisible and unclickable).
We’ll add an event to the stage, the MouseEvent.MOUSE_DOWN, so the function stageMouseDown.
private function close():void{
if(container.alpha>0) new TweenLite(container,.5,{alpha:0,onComplete:hideContainer});
}
private function hideContainer():void{ container.visible=false; }
private function stageMouseDown(e:MouseEvent):void{ this.close(); }
private function stageMouseLeave(e:Event):void{ this.close(); }
loaderIOError will be called if the load function of the loader doesn’t find the xml document and will set the caption to "XML not found".
The addedToStage will be called when this object is added to the stage display list. It will add an event for when you click anywhere on the stage to call the stageMouseDow function.
The removedFromStage will be called when this object is removed from the stage. It removes the event from stage so that clicks on stage will no longer call for the stageMouseDown function.
When the mouse leaves the stage, we’ll also close the drop down menu.
private function loaderIOError(e:IOErrorEvent):void{ txt.text="XML not found"; }
private function addedToStage(e:Event):void{
stage.addEventListener(MouseEvent.MOUSE_DOWN,stageMouseDown);
stage.addEventListener(Event.MOUSE_LEAVE,stageMouseLeave);
}
private function removedFromStage(e:Event):void{
stage.removeEventListener(MouseEvent.MOUSE_DOWN,stageMouseDown);
stage.removeEventListener(Event.MOUSE_LEAVE,stageMouseLeave);
}
The function loaderComplete is called when the xml is fully loaded, it will work like this:
- Set the default text of txt object to "Select" and the value to null, so we don’t have a value and the default caption is just "Select"
- Create a new XML instance
- Check the total number of nodes that have an <item> tag in the xml document and insert into the "total" variable.
- Loop the values of the xml document, getting their caption and value properties. The properties in xml are gotten by @property and the node value just .node without @.
- Create a new MenuItem object with a menuItem instance, passing the caption and the value to the MenuItem constructor.
- Add an event to the menuItem, when clicked it will call the function menuItemClick.
- Add the menuItem just created to the container display list.
- Set the position x of the container to the center of the DropDownMenu Object using some calculation.
private function loaderComplete(e:Event):void{
txt.text="Select";
_value=null;
var xml:XML=XML(e.target.data);
var total:int=xml.item.length();
var _w:int=this.width;
var _h:int=this.height;
for(var i=0;i<total;i++){
var caption:String=xml.item[i].@caption;
var swf:String=xml.item[i].@value;
var menuItem:MenuItem=new MenuItem(caption,swf,_w,_h);
menuItem.addEventListener(MouseEvent.CLICK,menuItemClick);
container.addChild(menuItem);
}
container.x=(this.width-container.width)*.5;
}
The function menuItemClick will be called when you click any menu item object, the currentTarget parameter will get the object that was clicked.
We compare the actual value of DropDownMenu Object to the value of the clicked menu item and compare the current text of the txt textfield to the caption of the menu item. If there is any difference in the value, the function will dispatch a new DropDownMenuEvent passing the new caption and the new value.
private function menuItemClick(e:MouseEvent):void{
if(e.currentTarget.value!=_value && e.currentTarget.caption!=txt.text){
dispatchEvent(new DropDownMenuEvent(DropDownMenuEvent.CHANGE,e.currentTarget.caption,e.currentTarget.value));
_value=e.currentTarget.value;
txt.text=e.currentTarget.caption;
}
}
This is the function we have used to create the background and the hit state of the button. In the constructor function, this function returns a new Shape Object.
private function drawObject(_width:int,_height:int):Shape{
var newShape=new Shape();
var colours=[0xA6A6A6,0x515151];
var alphas=[1,1];
var ratios=[0,255];
var radians:Number=90*(Math.PI/180);
var matrix:Matrix=new Matrix();
matrix.createGradientBox(_width,_height,radians);
newShape.graphics.beginGradientFill(GradientType.LINEAR,colours,alphas,ratios,matrix);
newShape.graphics.drawRoundRect(0,0,_width,_height,5,5);
return newShape;
}
We create 2 read-only properties, one to get the caption and other to get the value of this object. These 2 properties will be visible outside the class, but can’t be changed outside the class, only read.
Use 2x " }" to close the package and the class.
public function get caption():String{ return txt.text; }
public function get value():String{ return _value; }
}
}
Now save this file as c:/myActionScripts/dropdownmenu/DropDownMenu.as. We have 3 files in the c:/myActionScripts/dropdownmenu:
- DropDownMenu.as
- MenuItem.as
- DropDownMenuEvent.as
Now we have a dropdownmenu package with 3 classes.
Step 7 – The .fla and the Document Class
In Flash, go to File > New.
Select Flash File (ActionScript 3.0) and click OK.
Then go to Window > Properties. The properties panel will open
In the properties panel enter "Main" in the Class textbox (without the " surround) and save your .fla file in c:/dropdownexample/dropdown.fla (remember that we already have the c:/dropdownexample folder with the xml folder inside.
Step 8 – Coding the Main Document Class
Create a new ActionScript file document (File > New > ActionScript file).
We’ll save the document in the same folder as the .fla document, with the name Main.as. This class belongs to the TopLevel package, so its package is just package…
We import the necessary classes. Notice that we import all the dropdownmenu package, so the three files created above (DropDownMenu, DropDownMenuEvent and MenuItem) will be imported to the Main class.
package{ import flash.display.Sprite; import dropdownmenu.*; import flash.events.*; public class Main extends Sprite{
Attention here, we’re creating 2 drop down menus; the first drop down menu will select a new xml document and make the second drop down menu load the value selected.
The first parameter, if not null, will automatically load the xml document when creating this object. The second parameter is the width of the drop down menu. We didn’t pass the third parameter; the height of the drop down menu, but we set the default value to 30, which I think it is a good height.
The first drop down menu will automatically load the xml called menu.xml in the folder xml, the second will load an xml file only when we use the load function.
private var d1:DropDownMenu=new DropDownMenu("xml/menu.xml",150); private var d2:DropDownMenu=new DropDownMenu(null,150);
We create the constructor. As this class is the document class, the function will be called when we compile the .swf and every time we open the .swf file too. We add the two drop down menus we´ve created, set the x position of both, then set the same y value to them. Add event listeners to both drop down menus, when we change the value we’ll call for the listeners.
public function Main():void{ addChild(d1); addChild(d2); d1.x=50; d2.x=210; d1.y=d2.y=40; d1.addEventListener(DropDownMenuEvent.CHANGE,d1Change); d2.addEventListener(DropDownMenuEvent.CHANGE,d2Change); }
This is the listener of drop down menu 1. When the d1 value changes, it will load its value in d2 drop down menu.
private function d1Change(e:DropDownMenuEvent):void{ d2.load(e.value); }
This is just to test the second drop down menu, but you can get the drop down menu´s values by getting instance.value and get the drop down menu´s captions by getting instance.caption.
private function d2Change(e:DropDownMenuEvent):void{ trace(e.caption+" = "+e.value);
//or trace(d2.caption+" = "+e.value); }
Close the package and the class with 2x " } "
} }
Now we have the Main class to test our work, just save in c:/dropdowexample/Main.as and compile the dropdown.fla document. Test it in flash so the trace will work.
The captions and the values can, of course, be anything you like.
Conclusion
The classes are a little bit big, but they’re correctly coded, don’t have bugs and you can use them whenever you want by just importing the dropdownmenu package and creating DropDownMenu objects. Classes and the Document class are the biggest difference between ActionScript 2.0 and 3.0. Anybody that learns how to work with ActionScript files and learns how to use the classpath will find it far better than using the timeline to code.
Thats all for now!




Fluxglide Complete Flash Web ... only $50.00 
Nice code dude and great tutorial. Maybe you can use colors when select one option. Regards!
var total:int=container.numChildren;
for(var i:int=0;i 0){
container.removeChildAt(0);
}
and you should use holder mc created in the flash ide, becouse it would save 30 – 50 lines of code and you could achive much better effects
while(container.numChildren) container.removeChildAt(0);
//faster and little bit less code
and where could i save 30-50 lines of code, please specify so i can get your suggestion for next tuts.
Thanks
ye while(container.numChildren > 0) container.removeChildAt(0);
thats what i wrote, but somehow i didnt appear on the page.
you just creat a moveclip with a background and a textfield export it and then you creat instances of that in your xml for loop this will safe you this wired:
newShape.graphics.beginGradientFill(GradientType.LINEAR,colours,alphas,ratios,matrix);
newShape.graphics.drawRoundRect(0,0,_width,_height,5,5);
and so on
Actually the code looks like it’s written by someone who just followed another tutorial and wrote this one up. The formatting of the code is very bad and hard to read. Good code is not about get it as short as possible, good code is about being easy to understand and easy to enhance. That’s what OOP is actually for.
Thanks for commenting…
First: this tutorial was 100% made by me, i didnt follow any tutorial to write this one, so if you have any difficulty feel free to ask and i will have the pleasure to answer.
Second: Good codes isn’t the better for understanding, but are codes that runs faster and doesn’t have bugs. The purpose of OOP isnt just to create easy to understand codes, but have another purposes too like creating advanced reusable codes (this example)…
Amen… and I didn’t have any problem following the tutorial, great job!
If you want to understand what i say with “reusable codes” try this:
1. Create a new .fla AS3.0 file, and save anywhere…
2. Copy the gs and dropdownmenu folder from the source files to the same folder of the .fla file, or if you have a classpath, copy both to the classpath…
3. Copy the menu.xml from the xml folder of the source files to the same folder of the .fla file
4. Open the actions pannel (window -> actions) and paste the following:
import dropdownmenu.*;
var dropdown:DropDownMenu=new DropDownMenu(“menu.xml”,200);
dropdown.addEventListener(DropDownMenuEvent.CHANGE,dropdownchange);
addChild(dropdown);
function dropdownchange(e:DropDownMenuEvent):void{
trace(e.value);
}
/*
This shows how to reuse a code, and one of the MAIN porpouse of OOP, and how it becomes ease to use… any question as i told i will have pleasure to answer, and suggestions are welcome…
*/
Ops, sorry i´ve duplicated the code, but you can understand, if any moderator can remove the duplicated content please do this. Thanks
The actually meaning of reusable code in terms of OOP is to make easier to extend at all. The goal of OOP isn’t to make it easier to use for people who ain’t that much into that language or programming at all, that’s why good code takes way more space sometimes than bad code would do, yet good code is better because it will keep the software stable and understandable. Get in touch with Design Patterns (MVC, Factory, Decorator etc.) to see what good OOP would look like.
But what bothers me most is the formatting of your code, it’s simply unreadable. It’s not about saving every possible line or character!
for(var i:int = 0; i < number; ++i)
{
callFunction(i)
}
is way better than
for(var i=0;i<number;++i) {callFunction(i)}
Also did you not type some of the variables (:String, :Boolean etc.), that’s a no-go for proper coding.
I suggest you to get in touch with coding convenctions of ActionScript. They’re called “conventions” for some reason!
Weber, it seems that you are trying to find any fail in his code and bother him, come on man, this is one of the best tuts written here.
Understand that reusable codes isnt the same of extendable codes, you can make a final class (not extendable) but that you can use in any application (reusable)… there are differences.
And… the code is very clear, i´ve followed and had no problems, as he told, if you are getting difficulties ask him instead of trying to find fails.
Hugs and good luck with the code.
And André, great work you´ve done, i am waiting the tut you´ve promissed in a comment about the pixelbender and flash, remember?
Weber, if you are getting difficulty, please tell me where, and i can help you, the convention point maybe you´re right, i really missed to type some variables, but the point of using single line doesnt change the learning…
Another thing, you are confusing extendable with reusable, final classes are not extendable but can be reusable, but not final classes can be reusable and are extendable…
But is this, if you get some difficulty please ask and i can help.
Good tutorial!!! thanxs!!!!
nice tut Andre, very illustrative – keep it up. This should give ppl lots of insights to build from
Almost every tutorial in flashtuts that I have seen seems to have someone commenting on how bad the code is. This is confusing to new guys like me.
Should I use this tutorial? Should I not? Is it going to teach me bad habits?
Can someone explain to me why all these flashtuts having people saying the code is wrong or poor?
No, it wont teach you bad habits, but there are some variables not typed, the most correct is to type all variables… (ex var variable:String or var variable:Number, etc.)
If you have any difficulty please ask here
Dear Andre,
Thanks for writing this tutorial.
I have been working on my own menu system and my work has given me a huge appreciation for the complexity of developing simple menus. It is not easy to make it easy (if you know what I mean).
Step 4 – Coding the MenuItem Object needs another right brace at the end of the code.
Yes, it´s really missing, and the end of all, thanks for your observation!
Awesome tutorial
Thanks so much for writing & posting this tutorial
Thanks so much for your kind effort for making
This Awesome tutorial.
Your tutorials are more valuable for us
please keep them coming
God bless you :-)
Next tuto is about pixelbender + flash, i´ve already made it and sent to publish!! just wait
I don’t know if this is too much to ask, but I would love to see a tutorial on sprites. I don’t really understand them yet, and they aren’t explained in intro OOP courses.
http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/display/Sprite.html
The Sprite class behave like the MovieClip class, the difference it doesnt have timeline animation, you cant control the timeline since Sprite doesnt have gotoAndPlay, gotoAndStop, currentFrame… those things that control the timeline in the MovieClip…
All the courses should explain about this, since the MovieClip class (the most used) extends the Sprite class.
See the link http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/display/MovieClip.html about the MovieClip class, where it shows the inheritance are the classes that the MovieClip class extends, one extends other, and the subclasses are the classes that extends the MovieClip class.
Note: another differente between the MovieClip and Sprite class is the keyword dynamic, this keyword enable the class to creat variables, properties or functions at runtime.
I hope it explains your doubts.
We need more like this one!
Is this for Flash CS3 or CS4? I get “Unexpected File Format” when I try to open source.fla.
Thanks -
Sorry, for flash CS4, i dont have the files for CS3, and i recommend to start using the CS4 because of the Flash Player 10.0
Good Tutorial and I like the way you explain each section of the ActionScripts.
But sadly I am new at Flash and trying very hard to understand ActionScripts 3 but at the begining of your tutorial you say this is for CS3 & CS4 but clearly it is not for CS3 and I am kinda frustrated and anoyed that I have wasted the last couple of nights trying to understand the ActionsScripts only to find this does not work with CS3 as I get “Unexpected File Format” when I open it.
Please make things very clear at the begining of your tutorial what is required, so us new people don’t waste our time trying to get something to work, only to find it does not because you didn’t tell us that is only for CS4.
Good luck on your second attempt.
Really sorry for this, but the source is for CS4, but the tutorial works also for CS3
Great menu options. Just what I have been looking for. Thanks.
One small question, as I have very little with regards to ActionScript.
Was wondering how easy would it be to implement a scroll bar at the side of the drop down if you have lots of options?
Kind regards,
Chris
Thanks fot yout comment…
Scrollbar usually are not easy to create, but i will try to explain how it could be done here…
Ok, we already have our container, where we put all the MenuItem objects… so we need a scrooll and a mask, we could just mask the container (we already have this), and create a scroolbar, when you put the MenuItem objects inside the container, you check if the container is bigger tham the limit (the mask), if yes, set the scroll bar visibility to true (scrooll.visible=true; for example)… when you drag the scroollbar you can check it´s value, i recomend a scroolbar wich goes from 0 to 1 only, so when you drag and change the value of the scroolbar you set the position of the container, but the mask will not change it´s position, so you get the difference between the container´s height and the mask height and set the container y position according to the difference and the value of the scroollbar… for example:
if the container.height is 300 and the mask.height is 100, the diference will be 200, so the y position of the container will be -200*scroollbar.value… (scrollbar.value will be a number between 0 and 1)…
Another way is to set the maximum value of the scroollbar, when change the contents of the Container, check the diference, if more tham 0 so set the max value of the scroolbar as the difference between the container.height-mask.height… if this value is less or equal to zero, the scroollbar should be hidden or disabled
Any doubts just ask here :D
I need different name for each button which is shown select right now how I can do that, if I try to put the statement
txt.text=xml.item[i].@caption;
inside the loop then it repeats only one caption on all main buttons.
Please help
The txt.text is the main caption, wich will display the SELECTED caption, wich name you would like to change?
var menuItem:MenuItem=new MenuItem(caption,swf,_w,_h);
this is the constructor of the MenuItem Object, the argument caption is a variable the Type of String, you can use whatever you want there, but the porpouse is to use xml to set the values…
If you want to change the value of some button at runtime, you will need to add the folowing at MenuItem Object:
public function set caption(v:String):String{ txt.text=v; }
public function set value(v:String):String{ _value=v; }
so you can set by using:
var menuItem:MenuItem=new MenuItem(“caption”,”value”,width,height);
menuItem.caption=”new caption”;
menuItem.value=”new value”;
If this is not your difficult please just give me more details for a better help, or you can add in msn: group225300@groupsim.com
it´s a online chat at msn wich you can ask there and people who are online can help you, i am almost full time there
Hi Andre!
I’m referencing your tuturial for a project that I am doing, so far everything has been going great (so to say) when I stumbled upon a dead end.. and this is probably the stupidest question asked,
I am a noob at this so bear with me..
in your XML file, you have a value = “email address” from my understanding you’re able to change the email addy to a URL link, but how do I access the URL so that when I click on the links, it actually calls upon external links? I know it has something to do with the e.value variable but I can’t seem to get it to work..
Please help.
Thank you.
Hi, thanks for your words.
You can create a XML file like this:
</menu
Them, in the Main.as file you have the line:
private function d2Change(e:DropDownMenuEvent):void{ trace(e.caption+" = "+e.value);
}
the e.caption will be the selected item caption, and the e.value will be the selected item value, so instead of using trace you can use for example navigateToURL…
so:
private function d2Change(e:DropDownMenuEvent):void{
navigateToURL(new URLRequest(e.value)); //it will open the selected url from the box
}
Sorry, the coment just got away my xml…
but the same structure, just the caption for the first you change for “google” and it´s value change to http://www.google.com and for the second line of the xml file you change the caption to “yahoo” and it´s value to http://www.yahoo.com, and test it with the navigateToURL
I hope you put it working
Hello,
Good tutorial but i have a couple of questions… (bare with me i’m new at this)
1. Can’t it use 1 xml file instead of multiple? Because if you want to update the data it is easier that way.
2. Instead of an external url can it take you to a different frame of the flash file?
Hello vagz, thanks for your comment…
1. The point of this tutorial is really to create a custom object using xml external file, it´s much easyer you update an xml file instead of opening flash and change the values from there, that´s why exists the insteraction of flash and xml, for easyer updates, and this is the porpouse of this tutorial…
2. As you can see at step 5, we created a custom event for the menu, when it´s changed, and in step 8, i showed how to use this event to get the values from the drop down menu, instead of using trace, you can use whenever you want… for example in line:
private function d2Change(e:DropDownMenuEvent):void{
trace(e.caption+” = “+e.value);
}
instead of trace you can use gotoAndPlay(e.value);
but you would need to change the value in xml for a number value… OR also could it be a string value but the timeline would need to have a labeled keyframe… for example, in contactlist3.xml there is:
you could use:
or:
I hope this clear your doubts, if not, just ask again
I am customizing the drop-down menu due to space considerations. This is for a chart of commodity values and I want users to be able to select one of three metals as well as one of three periods to chart. The chart would start with an initial value (‘gold’ and ‘week’, which charts gold quotes over the past week), and the matching caption would appear in place of “Select”. The other unselected values should appear in the drop-down menu; when someone selects a caption in the drop-down menu, I want that caption to swap places with the first position (where “Select” currently appears).
Since the value is the same as the caption, I’m not worried about transferring the value (since “Select”‘s parent is not a MenuItem object).
1) Initialization:
a) when the drop-down list is initialized, I got rid of ‘txt.text = “Select”‘ and instead I put in the first caption from the XML file. All subsequent caption/value pairs create a MenuItem object.
2) OK here is the problem: I am trying to figure out how to access the MenuItem object – already created – whose caption matches ‘e.currentTarget.caption’ in the menuItemClick function.
a) added set functions to MenuItem for both caption and value
b) in DropDownMenu.as, changed ‘menuItemClick’ as follows:
private function menuItemClick(e:MouseEvent):void{
if(e.currentTarget.value!=_value && e.currentTarget.caption!=txt.text){
dispatchEvent(new DropDownMenuEvent(DropDownMenuEvent.CHANGE,e.currentTarget.caption,e.currentTarget.value));
_old_value = _value;
_old_caption = txt.text;
_value=e.currentTarget.value;
txt.text=e.currentTarget.caption;
for(var i:int=0;i<container.numChildren;i++) {
if (container[i].caption == txt.text) {
container[i].value == _old_value;
container[i].caption == _old_caption;
break;
}
}
}
this does not change any of the existing MenuItem objects' captions. I even added an 'else' so that if there is no match, it should change each tested caption anyway to something like, 'tested'.
What am I missing here? Thanks in advance.
I found one (pair of) mistakes, the new value/caption needs to be passed as an argument. This still does not get it to work, however…
container[i].value(old_value);
container[i].caption(_old_caption);
Hi, if you can post anywhere i can see what happen and give you the solution, sorry for the late answear…
There are some things that i could see that maybe be wrong…
For first, if the container is an Sprite object, it´s not dynamic, so you cant access the children by using container[i].value, you can use container.getChildAt(i) to access the child…
Also it seems that you´re trying to set the value with two equals (==) it is for comparation only, when you set a property you use single equal (=)…
your code:
container[i].value == _old_value;
container[i].caption == _old_caption;
Correct:
container[i].value = _old_value;
container[i].caption = _old_caption;
Since it´s property you set this way, not like argument… it´s like a variable, but it´s a property so it activates a function…
So… try:
private function menuItemClick(e:MouseEvent):void{
if(e.currentTarget.value!=_value && e.currentTarget.caption!=txt.text){
dispatchEvent(new DropDownMenuEvent(DropDownMenuEvent.CHANGE,e.currentTarget.caption,e.currentTarget.value));
_old_value = _value;
_old_caption = txt.text;
_value=e.currentTarget.value;
txt.text=e.currentTarget.caption;
for(var i:int=0;i<container.numChildren;i++) {
if (Sprite(container.getChildAt(i)).caption == txt.text) {
Sprite(container.getChildAt(i)).value = _old_value;
Sprite(container.getChildAt(i)).caption = _old_caption;
break;
}
}
}
Maybe it work, i dont know how is the rest of your code, but if you need more help with this you can add group225300@groupsim.com in your msn or yahoo messenger, i am everyday there and i can help you more with this…
I’m embarrassed that I posted my dumb mistakes with ==. I’m still working on this, your version did not compile; I figured out a way to get it to compile but it still does not work. When I figure it out I will post a solution. Thanks for responding.
Please, post your compilation errors here, them maybe i can help
:D
Great tut, but if you could add comments to the files that would be great for customization for those of us who are new to this. Thanks!
In the MenuItem.as and I figured out how to make the background alpha to 0, but is there anyway to make it so that the roll over state is at .8 of the background color and still keep the background alpha at 0?? i attached the code that I’m working with if anyone can help me this would be a huge help. thanks!
public function MenuItem(caption:String,value:String,_width:int=145,_height:int=18):void{
this.buttonMode=true;
this.alpha=1;
_value=value;
this.graphics.beginFill(0×000000, 0);
this.graphics.drawRect(0,0,_width,_height);
txtFormat.color=0×000000;
txtFormat.size=9;
txtFormat.font=”Verdana”;
txt.defaultTextFormat=txtFormat;
txt.mouseEnabled=false;
txt.text=caption;
txt.x=5;
txt.y=2;
txt.width=_width-10;
txt.height=_height-4;
addChild(txt);
addEventListener(Event.ADDED_TO_STAGE,addedToStage);
addEventListener(MouseEvent.MOUSE_OVER,mouseOver);
addEventListener(MouseEvent.MOUSE_OUT,mouseOut);
}
private function mouseOver(e:MouseEvent):void{ new TweenLite(this,1,{alpha:.8}); }
private function mouseOut(e:MouseEvent):void{ new TweenLite(this,1,{alpha:1}); }
private function addedToStage(e:Event):void{ this.y=this.parent.getChildIndex(this)*this.height; }
public function get caption():String{ return txt.text; }
public function get value():String{ return _value; }
}
}
Good tutorial but with the least amount of explains and lack of comments in as file, actually I don’t know what you are talking about at all. It just like show the code to me and it’s done, For noobs who don’t even understands concept like getters/ staic function just like me, it is rather too hard yo know what you are doing.
Hi,
how can i make this menu loan an external swf?