CREATING AN XML-BASED APPLICATION

Download FlashXMLBasedApp.zip

In this lesson, you will learn how to create an XML-based application.

NOTE: If you understand in advance why you are doing a given step, you can skip the "why" explanation below it.

Create new Flash file and set initial dimensions, etc.

  1. Create a new Flash ActionScript 3 file and save it as FlashXMLApp.fla in your Lesson folder (or a folder of  your choosing)
  2. Set stage size to 700W x 500H in the Property Panel by clicking on the document properties button.
  3. (Optional) Create a new layer and give it a name of Background.  Then, add a background image that is the same size as the stage and lock that layer.

Layout Flash application interface (with components)

  1. Drag out the following components from the component panel (Window > Component) and lay them out as follow:

    TextArea for title (286Wx28H) & (x=411 and ay=0)
    TextArea for intro (600Wx60H) & (x=47 and y=65)
    TextArea for mineral name (286Wx28H) & (x=359 and y=151)
    TextArea for mainbody (289Wx289H) & (x=357 and y=178)
    TileList for menu (270Wx318H) & (x=47 and y=147)

Give Component Instance Names

It is important to give components instance names so they can be "talked to" programmatically. Pay attention to spelling and cases.

  1. Give each component an instance name: (Note: Naming conventions are a blend between the purpose and the type of component)

    title_ta for title field
    intro_ta for intro field
    mineralName_ta
    for mineral name
    mineral_ta for mainbody field
    thumbnails_tl for menu (note suffix "tl" for tile list and not "ta" for text area)

  2. With thumnails_tl component selected, select Window > Component Inspector from the main menu. In the Component Inspector dialog box, change the following parameters:
    1. direction: vertical
    2. columnWidth: 125
    3. rowHeight: 125

  3. Rename Layer 1 to components and create a new layer and name it ActionScript that should be the first layer.

Populate List with data from XML file

Create URLLoader (not UILoader) and XML object to hold data from an external XML file:

  1. Select ActionScript layer and write the following code in the ActionScript panel.
    Why? To create URLLoader object and add URLLoader load method to it and pass it a URLRequest object that will point to the actual index.xml file. This is in essence creating a new object (loader) and then creating another object (URLRequest) inside it as it parameter or argument.

    var loader:URLLoader = new URLLoader();
    loader.load(new URLRequest("index.xml"))

    CAUTION: Note two ending parenthesis.

  2. Write the following code below current code.
    Why? To create a addEventListener for the loader object and an event Handler function (onDataLoad) to create an XML object and trace result of the applicationData variable.

loader.addEventListener (Event.COMPLETE, onDataLoad);

function onDataLoad (eventObject:Event):void
    {
      var applicationData:XML = new XML(eventObject);
      trace(applicationData)
    }

NOTE: In this event handler, you created an XML object and passed it data from the URLLoader created earlier to provide data for the XML object and added a trace statement to see the result. In is helpful to think the the eventObject parameter will "sneak in" many of the properties of the object that made the call (loader). We will use the eventObject to ascertain certain properties of that object.

  1. Save and Test.

    Result Checkpoint: You should be able to see some METADATA about the event that was dispatched or fired ( [Event type="complete" bubbles=false cancelable=false eventPhase=2] ) displayed in the Output panel. Not exactly what we wanted. We have to "drill" down further to get what we need.

  2. Add ".type" to the end of the eventObject.

       var applicationData:XML = new XML(eventObject.type);

  3. Save and Test.

    Result Checkpoint: You should be able to see the type of event that was dispatched or fired ( complete )displayed in the Output panel. Again, not exactly what we wanted. This basically tell us that the object that made the called (loader) is "listening" for an event by the name of complete.

  4. Replace  ".type" with ".target" at the end of the eventObject.

    var applicationData:XML = new XML(eventObject.target);

  5. Save and Test.

    Result Checkpoint: You should be able to see the target object that made the function called displayed ( [object URLLoader]  ) in the Output panel.

  6. Add ".data" to the "eventObject.target" to "drill down" further to get the the ACTUAL data in the loader object. (Do not delete the word target).

    var applicationData:XML = new XML(eventObject.target.data);

Result Checkpoint: You should be able to see the complete XML file.  Examine it to see the XML tree structure and take note of the repeating nodes (list_item) highlighted in bold. This is only an extract of the XML file.

<application title="ROCK CLASSIFICATION">
<intro>Rocks are classified by mineral and chemical composition....</intro>

<list_item>
<link_item_name>BASALT</link_item_name>
<thumbnail_img>Thumbnails/Basalt.jpg</thumbnail_img>
<main_body>Basalt is the most common type of solidified lava.... </main_body>
</list_item>

<list_item>
<link_item_name>BRECCIA</link_item_name>
<thumbnail_img>Thumbnails/breccia.jpg</thumbnail_img>
<main_body>Breccia is typically a sedimentary rock .... </main_body>
</list_item>
    ......
</application>

Since the "list_item" nodes are repeating nodes, we will need to drill down deeper just like a file structure (directory/directory/file) to retrieve each node separately and add them to a XMLList.

  1. Comment out trace and add the following code in bold to the onDataLoad function.
    Why? To create an XMLList (similar to an Array) and to trace it.

function onDataLoad (eventObject:Event):void
    {
         var applicationData:XML = new XML(eventObject.target.data);
         //trace(applicationData)
         var MenuList:XMLList = applicationData.list_item
         trace(MenuList)

    }

  1. Save and Test.

Result Checkpoint: Only the list_item REPEATING nodes highlighted in bold should be returned and not the complete XML file as before. The attribute (<application title="ROCK CLASSIFICATION"> .... </application> and its "non-repeating tag, best called "metadata" is not included ( <intro>Rocks are classified by mineral and chemical composition....</intro> )

<list_item>
<link_item_name>BASALT</link_item_name>
<thumbnail_img>Thumbnails/Basalt.jpg</thumbnail_img>
<main_body>Basalt is the most common type of solidified lava.... </main_body>
</list_item>

<list_item>
<link_item_name>BRECCIA</link_item_name>
<thumbnail_img>Thumbnails/breccia.jpg</thumbnail_img>
<main_body>Breccia is typically a sedimentary rock .... </main_body>
</list_item>

  1. Comment out the trace and add the following code in bold to the onDataLoad function.
    Why? Since MenuList is similar to an array we can use a "for" loop to iterate through it to get the data we need. Note we also added a line ( var menu_total:Number = MenuList.length()) above the loop statement to ascertain the number of elements in the XMLList.   You could also trace this variable by uncommenting the trace line below it.

function onDataLoad (eventObject:Event):void
    {
         var applicationData:XML = new XML(eventObject.target.data);
         //trace(applicationData)
         var MenuList:XMLList = applicationData.list_item
         //trace(MenuList);

         var menu_total:Number = MenuList.length()
        //trace(menu_total);

        for (var i:uint=0; i<menu_total; i++)
          {
            var MenuNames:String = MenuList.link_item_name[i];
           trace(MenuNames)

           }

    }

 CAUTION: Note parenthesis on the MenuList.length().  An XMLList has length as a method – length() unlike a property – length in an Array.   Also, watch out for cases, spaces, and braces.

Result CheckPoint: You should see a list (i.e., BASALT, BRECCIA, etc.) from the index.xml file in the output panel.

  1. Comment out the two previous lines. (They were only used to show the some of the data that will be used to populate the thumbnails_tl in the next step.).   Add the follow code in bold to the onDataLoad function.
    Why? Use a "for" loop to iterate through the XML MenuList data to create generic objects with properties while at the same time populating the TileList component which will act as our menu list.

function onDataLoad (eventObject:Event):void
    {
         var applicationData:XML = new XML(eventObject.target.data);
         //trace(applicationData)
         var MenuList:XMLList = applicationData.list_item
         //trace(MenuList)

         var menu_total:Number = MenuList.length()

        for (var i:uint=0; i<menu_total; i++)
          {
            // var MenuNames:String = MenuList.link_item_name[i];
           //trace(MenuNames)

          //Setup Dynamic text for menu list
               thumbnails_tl.addItem ({label:MenuList.link_item_name[i],
                                                             data:MenuList.main_body[i],
                                                             source:MenuList.thumbnail_img[i]});
          
}
    }

 CAUTION: Note parenthesis.  An XMLList has length as a method -- length() unlike a property -- length in an Array. Also, watch out for cases, spaces, and braces.

IMPORTANT NOTES:

Result CheckPoint: You should see TileList component populated with content from the "link_item_name" tags (i.e., BASALT, BRECCIA) from the index.xml file as well as the images.

  1. Add the following code below the existing code (still inside of the onDataLoad function) to add the static content (title and intro) to the page when it first load

    function onDataLoad (eventObject:Event):void
        {
             var applicationData:XML = new XML(eventObject.target.data);
             //trace(applicationData)
             var MenuList:XMLList = applicationData.list_item
             //trace(MenuList)

             var menu_total:Number = MenuList.length()

            for (var i:uint=0; i<menu_total; i++)
              {
                // var MenuNames:String = MenuList.link_item_name[i];
               //trace(MenuNames)

              //Setup Dynamic text for menu list
          
         thumbnails_tl.addItem ({label:MenuList.link_item_name[i],
                                                                 data:MenuList.main_body[i],
                                                                 source:MenuList.thumbnail_img[i]});
    //Setup initial page and STATIC text (title/intro)
    mineral_ta.htmlText = MenuList.main_body[0];
    thumbnails_tl.selectedIndex = 0;
    mineral_ta.text = MenuList.link_item_name[0];
    //Setup static content from XML file (not MenuList)
    intro_ta.text = applicationData.intro
    title_ta.text = applicationData.@title
              
    }

NOTE: The last two lines of code is not using the MenuList variable because, as you may have remembered, the attribute  of the <application> tag and node of the <intro> tag were "stripped out" in the MenuList variable. So we needed to use the complete XML variable (applicationData) to get to those values.
Note: The "mineral_ta.htmlText = MenuList.main_body[0]" is the same as the one in the "for" loop except it is hardwired with zero instead of "i" to retrieve the first node (which should always be the first item in the list).
Note: It is helpful to think of the list box as a set of drawers.  Each of which can have similar or the same "stuff" in them based on the data in the repeating nodes in the XML file which represent each drawer.

Result CheckPoint: You should see all of the text fields populated.  However, if you click on a tile list item, nothing happens. That because we have not yet told the Tile list to "talk" to the Mineral Text Area when it is clicked. We we do that next.

Connect TileList to Text Area components (mineralName_ta and mineral_ta)

  1. Add following code to the bottom of current code outside of the onDataLoad function.
    Why? Since we created a data property as one of our properties of our generic object for each main_body tag in the XML file, we can listen for a change in the TileList component to display the data property in the currently selected menu item in the TextField component (mineral_ta).

// Menu ====================================================
thumbnails_tl.addEventListener (Event.CHANGE, onMenuChange);
function onMenuChange (eventObject:Event):void
{
           //trace("The " + eventObject.target.selectedItem.label + " list item was clicked")

           mineral_ta.htmlText = eventObject.target.selectedItem.data;
           mineralName_ta.text = eventObject.target.selectedItem.label;
}

  1. Save and Test (by commenting or uncommenting only one line at a time.)

Result Checkpoint: By clicking on a "item" in the menu list (or using the up/down arrows) the mineral_ta area changes to reflect the content from the index.xml file.

Finishing touches

  1. Add the following code to the bottom of the existing code to set the editable property of the three textfield components to false.
    Why? Currently, if you select any of the text in the textfield component, you could write you own text into any of them. To prevent the user from editing the dynamic text, we will set the editable property to false for all three.

            for (var i:uint=0; i<menu_total; i++)
              {
                   menu_ list.addItem ({label:MenuList.link_item_name[i],
                                                       data:MenuList.main_body[i] });
               }
    body_text.text = MenuList.main_body[0];
    menu_list.selectedIndex = 0;
    title_ta.editable = false;
    intro_ta.editable = false;
    mineral_ta.editable = false;

    or you could "condense" the three lines into one line like this: title_ta.editable = intro_ta.editable = mineral_ta.editable = false;.

    or you can change the editable property for each of these components to false in the Component Inspector panel.

Save and Test.

Result Checkpoint: These three text fields are no longer editable. However, you can still select them.

You may have noticed that we specified the mineral_ta property to "htmlText" instead of the generic "text" property for the other text fields. We did this so that we can allow HTML tag in our XML file. However, we will need to "wrap" a CDATA tag around the main_body text in our index.xml file in order for Flash not to interpret any of the angle brackets as an XML tag.

  1. Edit the index.xml file and "wrap" the CDATA code inside the first main_body tag and add some simple HTML 3.0 tags to the text (See example with highlights in bold below)

    <main_body><![CDATA[ <p><b>Basalt</b> is the most common type of solidified lava. Because of the rapid cooling of lava on the Earths surface, basalt is usually fine-grained. Basalt is formed in areas where tectonic plates diverge. Rapid cooling of basalt lava forms a dark glassy rock.</p>
    <p>Lava bombs are also glassy because they cool quickly while falling through the air after being blown out of a <i>basaltic volcano</i>. Iceland is the only place in the world where a <font color="#FF0000">mid-oceanic ridge</font> is exposed above sea level.  Because of this, <a href="Iceland.html">Iceland</a> is a good place to see many types of basalt. More than ninety percent of all rocks in Iceland are some form of basalt.</p>]]>
    </main_body>

    NOTE: We have added the following tags (<b>, <a>, <u>, <br> and <i>). All HTML tags are not supported – only a few of the simple ones.

  2. Save and Test.

Result Checkpoint: You should now be able to see the simple HTML tags rendered in Flash as HTML text instead of regular text. You can go back and repeat the previous steps for any other tag you like.

Bonus

To see how you can repurpose this XML-based application to create another application.  Add two dashes (--) to the index.xml file and remove the three (---) from the
---index.xml file to make it the new index.xml file that Flash will see. Rerun the swf file again and you will see you have a TOTALLY NEW APPLICATION.