Home > ActionScript 3.0 Tutorial, Flash Development > Building a Basic Menu in ActionScript 3.0 Tutorial – Part 2 – XML

Building a Basic Menu in ActionScript 3.0 Tutorial – Part 2 – XML

A few posts ago, I showed you how to build a basic menu using an Array of button names. Now, I will demonstrate how to build the same menu, but this time use the new XML class which is based on E4X. There are many benefits of using XML in your applications. The main reason being that it allows you to update your application instantly without having to open up Flash to republish it. XML also allows your application to be easily updated from a server side page that generates XML output. This opens up the possibility of using a CMS to modify your application, thus enabling your clients to make updates on their own. Almost every project I develop uses XML.

And now for the code:

package ca.flashdev.example {		

  import flash.display.Sprite;
  import flash.display.Shape;
  import flash.events.MouseEvent;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;
  import flash.text.TextFormat;
  import flash.net.URLLoader
  import flash.net.URLRequest
  import flash.xml.XML
  import flash.events.Event;
  import flash.error.Error;

  public class BasicMenuXML extends Sprite {		

    // Create an XML list to hold the buttons.
    private var __menuList:XMLList;	 

    // External file loader.
    private var __loader:URLLoader;

    /**
     * The constructor. This method is fired
     * automatically when the class is instantiated.
     */
    public function BasicMenuXML():void {
      loadXML();
    }

    /**
     * Load the XML.
     */
    private function loadXML():void {			

      // Create a URL loader.
      __loader = new URLLoader();

      // Attach a listener to the loader.
      __loader.addEventListener(Event.COMPLETE, onXMLLoaded);

      // Load the xml file.
      __loader.load(new URLRequest("menu.xml"));
    }

    /**
     * Called when the XML has been loaded.
     * @param   event   The event that called this method.
     */
    private function onXMLLoaded(event:Event):void {

      // Put some error catching in case the XML is malformed.
      try {

        // Load the data into the XML object.
        var menuXML:XML = new XML(__loader.data);

        // Create a list of the buttons.
        __menuList = menuXML.button; 

        // Now that the XML is loaded create the menu.
        drawMenu();	

      } catch(error:Error) {

        // Display an error message.
        var errorMessage:TextField = new TextField();
        errorMessage.autoSize = TextFieldAutoSize.LEFT;
        errorMessage.textColor = 0xFF0000;
        errorMessage.text = error.message;
        addChild(errorMessage);
        return;
      }
    }

    /**
     * Draw the menu.
     */
    private function drawMenu():void {

      // This variable will hold the x position for the next button.
      var xPos:Number = 0;

      // Create a holder that will contain the menu.
      var menuHolder:Sprite = new Sprite();

      // Add the holder to the stage.
      addChild(menuHolder);			

      // Create text formatting for the text fields in the menu.
      var format:TextFormat = new TextFormat();
      format.font = "Verdana";
      format.color = 0x000000;
      format.size = 12;
      format.bold = true;

      // Loop through the list and create each button in the list.
      var count:int = 0;
      for each (p in __menuList) {

        // Create the button.
        var button:Sprite = new Sprite();
        button.name = "button"+count;

        // Disable the mouse events of objects inside the button.
        button.mouseChildren = false;

        // Make the sprite behave as a button.
        button.buttonMode = true;

        // Create the label for the down button state.
        var label:TextField = new TextField();
        label.autoSize = TextFieldAutoSize.LEFT;
        label.selectable = false;
        label.defaultTextFormat = format;
        label.text = __menuList[count].text();

        // Create a up state for the button.
        var up:Sprite = new Sprite();
        up.graphics.lineStyle(1, 0x000000);
        up.graphics.beginFill(0x00FF00);
        up.graphics.drawRect(0, 0, 100, 30);
        up.name = "up";

        // Create a over state for the button.
        var over:Sprite = new Sprite();
        over.graphics.lineStyle(1, 0x000000);
        over.graphics.beginFill(0xFFCC00);
        over.graphics.drawRect(0, 0, 100, 30);
        over.name = "over";

        // Adder the states and label to the button.
        button.addChild(up);
        button.addChild(over);
        button.addChild(label);				

        // Position the text in the center of the button.
        label.x = (button.width/2) - (label.width/2);
        label.y = (button.height/2) - (label.height/2);

        // Add mouse events to the button.
        button.addEventListener(MouseEvent.MOUSE_OVER,
                                  displayActiveState);
        button.addEventListener(MouseEvent.MOUSE_OUT,
                                  displayInactiveState);
        button.addEventListener(MouseEvent.CLICK, displayMessage);

        // Add the button to the holder.
        menuHolder.addChild(button);

        // Position the button.
        button.x = xPos;

        // Increase the x position for the next button.
        xPos += button.width + 2;

        // Hide the over state of the button.
        over.alpha = 0;

        // Increase the count.
        count++;
      }

      // Postion The Menu.
      menuHolder.x = 20;
      menuHolder.y = 20;

    }

    /**
     * Show the active state of the button.
     */
    private function displayActiveState(event:MouseEvent):void {

      // Hide the over state of the button.
      event.currentTarget.getChildByName("over").alpha = 100;
    }

    /**
     * Hide the active state of the button.
     */
    private function displayInactiveState(event:MouseEvent):void {

      // Show the over state of the button.
      event.currentTarget.getChildByName("over").alpha = 0;
    }

    /**
     * Display a message in the Output window.
     */
    private function displayMessage(event:MouseEvent):void {

      // Output the name of the clicked button.
      trace(event.currentTarget.name)
    }
  }
}

Save this file as BasicMenuXML.as in a folder structure of ca.flashdev.example.
Create a new movie and add ca.flashdev.example.BasicMenuXML to the ActionScript 3.0 Settings Document class field. Save this file as basicMenuXML.fla in the same directory as your ca folder. Publish (Ctrl+Enter) your movie and you should see the menu.

Download the source files

  1. swanthon
    June 7th, 2007 at 07:19 | #1

    Hehe, if anyone’s trying to run this code, you’ll want to edit the import statements to:
    import flash.xml.XMLDocument;
    import flash.errors.*;
    to reflect changes to packages in ActionScript 3.0

  2. rem7
    July 2nd, 2007 at 12:39 | #2

    doing
    import flash.xml.XML; won’t work

    and

    import flash.xml.XMLDocument; will use the old XML from Actionscript2.0 wouldnt it?

    source:
    http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000132.html

  3. July 3rd, 2007 at 15:48 | #3

    This tutorial was written for Flash 9, not Flash CS3, thus the incorrect import statements. import flash.xml.XMLDocument; is the correct statement and will use E4X. Thanks for the correction.

  4. gonzo
    July 8th, 2007 at 09:32 | #4

    I really new at this. Exactly what does this mean, “the ActionScript 3.0 Settings Document class field.”??

    I searched the entire menu and couldn’t find how to bring the source into Flash CS3 the correct way so that this would work. I loaded the .fla in the zip file and saw that it indeed works..but i want to do it myself.

    thanks,

  5. July 8th, 2007 at 20:20 | #5

    In Flash CS3 the Document Class field is at the bottom of the screen in the properties inspector right below the publish settings.

  6. Dion
    July 14th, 2007 at 07:32 | #6

    Hello, i am also really new to this.
    How can i make the buttons refer to a frame or link to another page in the website….?
    Do i have to adjust the xml file for that or something?

  7. August 21st, 2007 at 15:12 | #7

    I compiled it as shown and it threw me an error..

    1120: Access of undefined property p.

    At this line

    for each (p in __menuList) {

    then went reading and found that p must be defined.. and defined as an XML var.. thus the result will be..

    …….
    var p:XML;
    for each (p in __menuList) {
    …….

    Thanks for the tutorials.

  8. August 22nd, 2007 at 16:09 | #8

    im trying to make a ‘morphing button’

    i have an invisible button, and shape animated frames thay acount for the states of the button

    these codes work just fine individually, but whn they are combined like this it doesnt work properly anymore

    what am i doing wrong here

    button1.addEventListener
    (MouseEvent.MOUSE_OVER,
    function(MouseEvent)
    {(gotoAndPlay(“over”,”Scene 3″))});

    button1.addEventListener
    (MouseEvent.MOUSE_OUT,
    function(MouseEvent)
    {(gotoAndPlay(“out”,”Scene 3″))});

    button1.addEventListener
    (MouseEvent.MOUSE_UP,
    function(MouseEvent)
    {(gotoAndStop(2))});

  9. August 23rd, 2007 at 09:46 | #9

    Hi Peter,

    Can you email me your fla so I can take a look at it?
    fraser@flashdev.ca

    Thanks

  10. Tony
    September 24th, 2007 at 20:46 | #10

    Hi,

    Thanks for the tutorial. I built my AS3 code taking an xml file, parsing that into multiple arrays, then used those arrays to create buttons and populate the text fields of those buttons. Now that I see this tutorial, maybe I should just go straight from xml – buttons. Any reason not to?

  11. Tony
    September 24th, 2007 at 21:16 | #11

    here is my xml to array to movie clip code, but I’m having a hard time making my movie clips respond like buttons:

    var xml:XML = new XML();
    var loader:URLLoader = new URLLoader();
    loader.load(new URLRequest(“fsproconfig2.xml”));
    loader.addEventListener(
    Event.COMPLETE,
    function(evt:Event):void {
    xml = XML(evt.target.data);
    var newCircleX:Number;
    var newCircleY:Number;

    var num:Number = xml.fsproevent.length();
    var fsproeventname:Array = new Array();
    var fsproeventdate:Array = new Array();
    var fsproeventpackage:Array = new Array();
    var fsproeventID:Array = new Array();
    var fsproeventlocation:Array = new Array();
    var fsproeventtheme:Array = new Array();

    newCircleX = 200;
    newCircleY = 400;

    for (var i:Number = 0; i

  12. September 24th, 2007 at 22:41 | #12

    Hi Tony,

    It looks like there must be a max amount of lines or characters for a comment as your last chunk of code got cut off. With E4X I find I am using arrays much less and XML much more. I would say that there is no need to parse XML anymore.

    Maybe you can email me your code and I will add it to your comment above if WordPress lets me.

    Fraser ;)

  13. Norley Tucker
    October 19th, 2007 at 04:21 | #13

    Many thanks for this and the previous tutorial, nice and clear and finally helped me to get my dynamic buttons working, cheers :)

  14. Mark
    October 20th, 2007 at 19:33 | #14

    I have a question. I have been doing Flash 2.0 for years, and the switch has been pretty hard. A simple action for an object to move to the right won’t even work. I’ve switch all the _x’s to x’s, and all _root’s to root’s. Heres my code:
    First Frame:
    x += 15;

    Second Frame:
    gotoAndPlay(1);

    What’s wrong?

  15. Mark
    October 20th, 2007 at 19:35 | #15

    *I mean the switch to 3.0, in CS3*

  16. Mark
    October 20th, 2007 at 19:48 | #16

    Also, I can’t figure out a simple command for the 2.0 code:

    on(release){
    _root.gotoAndStop(2);
    }

    How do I do so in 3.0?

  17. October 20th, 2007 at 20:06 | #17

    Hi Mark,

    I just tested it out and it works fine. Make sure you give your movieClip an instance name (ie. test_mc) and then just use test_mc.x += 15.

    Watch out for root. I personally recommend you never use root because it will restrict the flexibility of your movie. Say you build an animation and use root to control its playback. If you ever want to use that animation inside another Flash project, chances are it will not work like you expect it to. I recommend you stick to using parent, or passing a reference movieClip into your code. Also, I am pretty sure root’s reference has changed in AS3. I believe it no longer refers to the Stage as it did in AS2.

    You can no longer use movieClip handlers in ActionScript 3. So, all of the on(release) crap is gone, thank God. You will have to start coding your projects using instance names for your movieClips like I mentioned above. Check out some of the tutorials on this site and others to learn about using Events.

    Hope this helps.

    Fraser ;)

  18. November 30th, 2007 at 01:26 | #18

    Thanx for this great tutorial.
    I have just finished the book essential actionscript 3.0
    by colin moock and your tutorials are helping me a lot.
    I am also trying to convert the basic bookselectionsytem
    (example from the book flash application design solutions by ka wai cheung and craig bryant, chapter 3)
    from as2 to as3, but i am stuck with the code on the .fla
    Is there anybody who has tried this or who knows where to
    find a simular example?

  19. qpixo
    January 16th, 2008 at 11:03 | #19

    I follow this tutorial but want to add another feature. Had a hard time to figure this in AS3.
    How to make a mouse selected, initialize to “button0″ when the user click to each other button. this color will be appear in others?

  20. psio
    February 6th, 2008 at 10:25 | #20

    Fraser,

    First off thanks for this great tutorial, but I’m running into several problems/errors. Here is the list of errors in the compiler…

    1180: Call to a possibly undefined method addChild.
    1180: Call to a possibly undefined method addChild.
    1172: Definition flash.error:Error could not be found.
    5000: The class ‘code.actionscript.MenuXML’ must subclass ‘flash.display.MovieClip’ since it is linked to a library symbol of that type.

    The first two addChild errors refer to the XML loading class. The import.error.Error isn’t right for some reason in the third error. And the last one is just weird to be honost, it refers to the classification next to package path.goes.here{

    Thanks for any help!

  21. psio
    February 6th, 2008 at 10:53 | #21

    OK, so I’ve fixed all of the errors except the remaining two, which have me completely stumped!

    1180: Call to a possibly undefined method addChild.
    This is for the part after this code…

    var menuHolder:Sprite = new Sprite();
    addChild(menuHolder);

    5000: The class ‘code.MenuXML’ must subclass ‘flash.display.MovieClip’ since it is linked to a library symbol of that type.

    This is a result of line 1, I’m just trying to show the path… help?

  22. worked
    February 8th, 2009 at 10:11 | #22

    Thanks for the tut! I have one question, how would I animate this menu? If I wanted each button to animate on the screen to specific location at runtime, how would I do that? Do I need to store the XML into an array first?

  23. March 9th, 2009 at 07:59 | #23

    Thank you for the tutorial, it was very helpful for me.
    After changing the imports u have listed in the code to these imports:
    import flash.xml.XMLDocument;
    import flash.errors.*;
    I had also the cpile error in this part
    [ for each (p in __menuList) { ]
    p seems to be undefined
    I have fixed the errors and I succeeded to get the code running.Now apllication can be instantly updated without having to open up Flash to republish it.

  24. manny
    May 20th, 2009 at 13:02 | #24

    First of all great post,

    I am trying to find where we associate the button with a specific path eg Button 1 links to home.swf and button 3 is gallery.swf.

    Shouldn’t this be in menu.xml?

    Probably stupid question bur asking anyway

  25. Tawhid
    June 9th, 2009 at 19:49 | #25

    Anybody knows how to change the text color on MouseOver on this code?

  1. No trackbacks yet.