Archive for the ‘XML’ Category

Flash XML Gallery

Friday, February 27th, 2009

This post will walk through the construction of a simple XML and Flash gallery. If you want to use the images and XML file we are referring to in this example you can download our XML document here and download our images here. Our gallery will simply load the first image and then with each click it’ll load the next image form our XML document.

The Flash plugin is required to view this object.

First of all here is the XML we will be working with:

<?xml version="1.0" encoding="utf-8"?>
<gallery>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0001.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Field at Night</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0002.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Van on the Road</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0003.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Van on the Road Close Up</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0004.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Mountains</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0005.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Edge of a Cliff</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0006.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Another Road</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0007.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Tight Path</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0008.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Yellow Pickup</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0009.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Power Lines</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0010.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Pig</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0011.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Drying Coffee Beans</title>
     </photo>
     <photo>
          <filename>http://adambenjamin.com/blog/wp-content/img_0012.jpg</filename>
          <width>800</width>
          <height>531</height>
          <title>Homes</title>
     </photo>
</gallery>

In this example the only piece of information we will need is the filename. In future posts we may use the image titles and dimensions.

First we need to import a few Classes:

import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;

Next we need a Movie Clip to load images into and apply Tweens to:

var containerMovie:MovieClip = new MovieClip();
addChild(containerMovie);

Then we define a URL Loarder and an XML Object:

var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();

We are going to need two variables: one to keep track of what image we are currently viewing and another to keep track of whether or not we are in the progress of loading the next image.

var galleryCounter:Number=new Number(0);
var galleryStatus:Boolean=new Boolean(false);

Then we are gong to add an Event LIstener to the main Movie Clip to listen for Click Events.

containerMovie.buttonMode = true;
containerMovie.addEventListener(MouseEvent.CLICK,clickHandler);

When some one clicks the main Movie Clip we check to make sure another image isn’t half way through loading; and if it isn’t we add one to the counter Variable, check to make sure it hasn’t gone too high and then load that photo.

function clickHandler(evt:MouseEvent):void {
     if (galleryStatus==false) {
          galleryCounter++;
          if (galleryCounter>=xmlData.photo.length()) {
               galleryCounter=0;
          }
          loadPhotoStep1(galleryCounter);
     }
}

Now that our containers and butons are all set up lets load our XML.

xmlLoader.load(new URLRequest("gallery.xml"));

Once that loading is complete we put the loaded information into our XML Object and start eh first step of loading our image.

xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
function LoadXML(e:Event):void {
     xmlData=new XML(e.target.data);
     loadPhotoStep1(galleryCounter);
}

Setp 1 - we save the loaded image number into our galleryCounter variable and set galleryStatus to true. This prevents our clickHandler function above from loading another image before this one has finished loading. And we Tween the Alpha out of the current image.

function loadPhotoStep1(photoNumber:Number):void {
     galleryCounter=photoNumber;
     galleryStatus=true;
     var tweenOut:Tween=new Tween(containerMovie,"alpha",Strong.easeOut,1,0,15);
     tweenOut.addEventListener(TweenEvent.MOTION_FINISH,loadPhotoStep2);
}

Step 2 - once the first Tween has completed we load empty the container Movie Clip and load in the new image.

function loadPhotoStep2(evt:TweenEvent):void {
     var imageLoader:Loader = new Loader();
     var imageRequest:URLRequest=new URLRequest(xmlData.photo[galleryCounter].filename);
     imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,loadPhotoStep3);
     imageLoader.load(imageRequest);
     emptyContainer();
     containerMovie.addChild(imageLoader);
}

One the image has loaded in we Tween the Alpha back in.

function loadPhotoStep3(evt:Event):void {
     var tweenIn:Tween=new Tween(containerMovie,"alpha",Strong.easeOut,0,1,15);
     tweenIn.addEventListener(TweenEvent.MOTION_FINISH,loadPhotoStep4);
}

Once that Tween is complete we set galleryStatus back to false so the next time the user clicks the Movie Clip i’s good to go!

function loadPhotoStep4(evt:Event):void {
     galleryStatus=false;
}

This last function removes all Children from the containerMovie Movie Clip. It is called by the step 2 function.

function emptyContainer() :void {
     for (var i:int; i < containerMovie.numChildren; i++){
          containerMovie.removeChildAt(i);
     }
}

Download the Gallery Flash File

Download a Version of this Gallery with Thumbnails

My Own Number

Friday, February 27th, 2009

When teaching Flash one of the questions that often comes up is how to generate a menu based on XML. By the time the question gets to me usually the FLA is to the point where he XML is loaded, there is an imported Object from the library for each item in the XML and those Objects are clickable. Where it gets difficult is having each of those items remember what XML item they belong to.

In Actionscript 2.0 this was easy. We could assign whatever properties/variables/functions to whatever and everything would work out fine. Using Actionscript 3.0 we now hove to do this properly….well kind of.

First we need some XML to import. Lets use this very generic XML file.

<?xml version="1.0" encoding="utf-8"?>
<root_element>
     <item>
          <number>1</number>
          <title>Title Number 1</title>
          <image>image1.jpg</image>
     </item>
     <item>
          <number>2</number>
          <title>Title Number 2</title>
          <image>image2.jpg</image>
     </item>
     <item>
          <number>3</number>
          <title>Title Number 3</title>
          <image>image3.jpg</image>
     </item>
     <item>
          <number>4</number>
          <title>Title Number 4</title>
          <image>image4.jpg</image>
     </item>
</root_element>

Download the Example XML Document

Now lets go through two different methods of achieving this.

Method One: Avoiding External AS Files

The proper way to do this would be to create a Custom Class using an external Actionscript file and maybe partner this with a Library Object with the same name. However, this can be achieved without an External Actionscript file…it’s a little dirty but it’ll work.

Open up a new Actionscript 3.0 file and create a new Symbol with the following properties:

In this new Object give it the following timeline:

On the number text box put a Dynamic Text Field with the Instance name number_tb. On the Title layer put a Dynamic Text Field with the instance name title_tb. And on the background layer put some sort of background. IT should look something like this:

Now go back to the Stage and select Frame 1. The first thing we need to do is create a URL Request, a URL Loader and an XML Object:

var exampleXML:XML = new XML();
var exampleRequest:URLRequest=new URLRequest(&quot;flash_number_example.xml&quot;);
var exampleLoader:URLLoader = new URLLoader();

Next we need to load the URL Request using the URL Loader.

exampleLoader.load(exampleRequest);

When the loading is complete we will trigger the completeHandler Function.

exampleLoader.addEventListener(Event.COMPLETE,completeHandler);

And lastly we need to define that function.The first line takes the loaded data from our URL Loader and puts it into an XML object. Before we moved it into an XML Object the data would have been treated as text. This allows us to do all sorts of XML type things with it.

Next we loop through each item in the XML Object and create a copy of an ItemObject. For each ItemObject we set the test in the title_tb Text Field to the title from the XML and the number_tb Text Field to the item number. Next we position the Item Object, give it it’s Button actions and lastly add it to the Stage.

Special thanks to Mazoonist for the mouseChildren line of code. This solution was found in an actionscript.og forum post. This line makes sure the whole button is clickable. If we did not have this line the button would be clickable but you would not get the point mouse whenever your mouse is over a text box.

function completeHandler(evt:Event):void {
     exampleXML=XML(evt.target.data);
     for (var i:int=0; i<exampleXM.item.length(); i++ )
          var nextItem:ItemObject = new ItemObject();
          nextItem.title_tb.text = String(exampleXML.item[i].title);
          nextItem.number_tb.text = String(i);
          nextItem.x = 141 * i;
          nextItem.addEventListener(MouseEvent.CLICK,clickHandler);
          nextItem.mouseChildren = false;
          nextItem.buttonMode = true;
          addChild(nextItem);
     }
}

And of course we need a function to execute on he click of our Buttons. At this point this code just traces it’s own number. Now that each item know it’s number it can go back to the XML object and retrieve anything else it may need.

function clickHandler(evt:Event):void {
     trace(evt.target.number_tb.text);
}

Download the Hack Version FLA

Method Two: External AS Files

In this method we will use a Library Object in Partnership with an external AS file. Start by opening a new Actionscript 3.0 document. Just like the above example insert a new symbol with the following properties:

In that new symbol give it the following timeline:

On the title layer put a Text Field with the Instance name title_tb and on the background layer put some sort of background.

Next we need an external AS file to help define our ItemObject Object. Creating a Custom Class Actionscript file is exactly like creating an object in real life. We give the Object a name and we define what properties the Object has. In our case we are creating an ItemObject. From looking at our last method we know that an ItemObject is a type of MovieClip; which is actually a little over kill. We can go one step back. So our ItemObject is a type of Sprite.

The different between a Sprite and a MovieClip is that a MovieClip is a Sprite with a timeline. So MovieClip have properties like currentframe and all sorts of timeline related stuff.

When creating a Custom Class we use the package syntax and first list all pre-existing Classes the this Custom Class requires. So in our example we need the Sprite and MouseEvent Classes.

package {
     mport flash.display.Sprite;
     import flash.events.MouseEvent;

Next we start our Class and provide the base Class; in this case a Sprite:

     public class ItemObject extends Sprite {

We now need ot list what properties this new Custom Class has. In our example above the ItemObject has two properties that a Spite doesn’t have. We need a place to store the text and a pace to store the number.

          var itemText:String;
          var itemNumber:Number;

Next we need what is called a Constructor. A Constructor is the code that is executed when the Class is created. In the constructor definition we also specify what values are required to initially create an instance of our Custom Class.

In our example we need the text and the number to create an instance of an ItemObject. This function then saves the two provided values in the two properties defined above, adds a Rollover action and sets a few default properties.

          public function ItemObject(itemText:String,itemNumber:Number){
               this.itemText = itemText;
               this.itemNumber = itemNumber;
               this.title_tb.text = this.itemText;
               this.addEventListener(MouseEvent.CLICK,clickHandler);
               this.mouseChildren = false;
               this.buttonMode = true;
          }

Finally we need the clickHandler function called above. In this case we just trace the ItemObject’s number. And close the parenthesis from the open Class and Package lines above.

          public function clickHandler(evt:MouseEvent):void {
               trace(this.itemNumber);
          }

Download the Proper Version FLA

Flash XML Weather Feed

Sunday, February 22nd, 2009

Integrating Flash with XML is increasingly becoming more and more common and useful! Working with XML has also become a whole lot easier with Actionscript 3.0. In this example we will create a Flash file that will display the current weather. We will get our weather information from Boy Genius. The weather feeds are available here. For this example we are going to use the weather from Toronto Ontario Canada.

Here is the XML we will be working with:

<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type="text/xsl" href="/weather.xsl" alternate="no" ?>
<city>
     <name>Toronto</name>
     <state>Ontario</state>
     <temperatures>
          <fahrenheit>27</fahrenheit>
          <celsius>-2</celsius>
     </temperatures>
     <conditions>FLURRIES</conditions>
     <dewpoint>18</dewpoint>
     <relative_humidity>69</relative_humidity>
     <wind>W28G33</wind>
     <wind_english>West 28 MPH Gusts Reaching 33 MPH </wind_english>
     <barometric_pressure>29.88R</barometric_pressure>
     <notes></notes>
     <wind_chill_fahrenheit>11</wind_chill_fahrenheit>
     <heat_index_fahrenheit>Not Applicable</heat_index_fahrenheit>
     <image>http://www.srh.noaa.gov/weather/images/fcicons/na.gif</image>
     <coordinates>
          <latitude>N/A</latitude>
          <longitude>N/A</longitude>
     </coordinates>
     <last_updated>February 22, 2009 18:19:18 GMT</last_updated>
     <last_updated_seconds_gmt>1235344758</last_updated_seconds_gmt>
     <info_courtesy_of>The National Weather Service</info_courtesy_of>
     <source_url>http://weather.noaa.gov/pub/data/raw/as/asus43.kfgf.rwr.fgf.txt</source_url>
     <feed_problems_contact>xml@boygenius.com</feed_problems_contact>
     <xml_generation_script_author>Todd Finney, Boy Genius Incorporated</xml_generation_script_author>
</city>

Writing the Actionscript to import this XML and display it on the stage is a common assignment I give to my students. In this example we are just going to import the city, state and the image.

First lest define a Text Format Object to use with the weather city and state.

var newFormat:TextFormat = new TextFormat();
newFormat.size = 20;
newFormat.color = 0x666666;
newFormat.font = "Arial";

Next we need to define a URL Loader and an XML Object. We will load the XML using the URL Loader and then on the Load Complete Event we will put the content into an XML Object.

When the Loader Complete Event is triggered all the information about that event will go into the variable evt defined in the function definition. Inside that Event variable is the target of the event and in this case the data loaded. We need to put that data, which is just text at this point, and put it in an XML Object. This was Flash can do all sorts of XML type things.

var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();
xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
xmlLoader.load(new URLRequest("http://weather.boygenius.com/feeds/ontario-toronto.xml"));
function LoadXML(evt:Event):void {
     xmlData=new XML(evt.target.data);
}

Inside the loadXML function we need to add code that will create a Text Field, use our Text Format Object defined earlier and display the city and state from the XML document. Add the following code to the loadXML function.

To get the city and state our of our XML Object we simply refer to the XML Object and then add a dot and the item we are looking for. So in this example we want xmlData.name and xmlData.state. This gets a little more complicated when there are multiple copies of items in an XML document. For example pulling information about one image out of an XML document that includes information about many images.

     var nameTextField:TextField = new TextField();
     nameTextField.text = String( xmlData.name ) + ", " + String( xmlData.state );
     nameTextField.selectable = false;
     nameTextField.width = 200;
     nameTextField.x = 10;
     nameTextField.y = 10;
     nameTextField.setTextFormat( newFormat );
     addChild(nameTextField);

And lastly we need to add more code to the loadXML function to load the weather image and add it to the stage.

     var imageLoader:Loader = new Loader();
     var imageRequest:URLRequest = new URLRequest(xmlData.image);
     imageLoader.load(imageRequest);
     imageLoader.x = 10;
     imageLoader.y = 100;
     addChild(imageLoader);

The current weather in Toronto Ontario Canada is:

The Flash plugin is required to view this object.

Download the Flash Weather XML File

For anyone who has had some experience with Flash and XML you will quickly learn about a cross-domain policy. For some reason Flash has added a security feature to Flash which prevents an SWF from loading content from another domain at run-time. There is lots of information about this on the Adobe web site. In theory this isn’t a bad idea; trying to prevent people from using other people’s content and their bandwidth is kind of noble. Except this security feature is so easy to get around they may as well have not built it in.

Our Weather example above will work fine when previewing the file in Flash. As soon as you put the file online Flash will refuse to load the XML from the Boy Genius site because they do not have a cross-domain policy. All we have to do is create a PHP file to grab the weather XML from Boy Genius and regurgitate it. Here is a three line PHP file that will regurgitate what ever XML file you tell it to.

<?php
header ("content-type: text/xml");
$file = file( $_GET['url'] );
echo implode( $file, chr(13) );
?>

Lets say for example we want to load the Toronto weather from the Boy Genius web site. All we need to do is call the above file, lets say it is called xmlCaller.php, and pass it a URL. The XML call in Flash would be:

xmlCaller.php?url=http://weather.boygenius.com/feeds/ontario-toronto.xml