synthetic-mind: Greenleaf Designs company blog

New Health Supplement Site in Development.

Talks have begun with a client to design a Web Site advertising a number of nutritional supplements.   It will be heavy on images and information in order to be visually appealing to visitors.

New Flash Microsite in Development

A new website is being developed for an award-winning documentary filmmaker from the Ottawa area.   A Flash micro site will first be created with a more feature-rich site to follow shortly after.   Stay tuned,  more to come in the future..

Flash Banner Ad using XML [Part two]

This is part two of the 2-part tutorial on making a Flash banner advertisement completely driven by XML. In this tutorial, we will dive into the code required to implement a simple backend script to manage the XML file which is used by the Flash banner advertisement. The language we will be using is PHP and some of the topics covered will be manipulating XML using SimpleXML and the DOM (Document Object Model), basic field validation and embedding flash content using swfObject to name just a few. A basic understanding of PHP, HTML and CSS is recommended. Also, the stylesheet makes use of ‘clearfix’. It is a method to clear floats using CSS which doesn’t require additional markup in your code. Google it to find out more, it’s a staple in all of my coding so I use it frequently. Having a back end to edit the XML will surely impress potential employers as no knowledge of XML would be required for anyone using the backend forms. Just add a new item, have the images and descriptions ready to go and it’s set. You can view an example of this code in practice, or download the source files to follow along below.

One other thing…I will not be touching on anything regarding CSS styling. You will notice in a couple of steps where HTML markup is outputted (the ‘add item’ form and the default index view) that I make use of classes. If you aren’t familiar enough with HTML and CSS to understand what is happening, educate yourself further as it is outside the scope of this tutorial. The main points I want to get across are : manipulating and reading XML using PHP [this tutorial] and reading XML and animating using the caurina Tweener class [Part 1 of this series].


Anyways, let’s dispense with the formalities and get this thing going!

STEP ONE – SETUP FOLDER STRUCTURE

First, we lay the groundwork for all of the steps in this tutorial. There will be five folders. The ‘images’ folder will hold, you guessed it, all images relating to this tutorial. The ‘XML’ will hold the ‘items.xml’ file which we will be working with. ‘js’ will contain any scripts being used. ‘flash’ will contain the complied .swf movie and finally ‘css’ will contain the stylesheet we will be using. That’s it, we’re now ready to dive into some coding.

STEP TWO – BEGINNING TO CODE THE INDEX PAGE

Alright, let’s start coding. The first section is by far the most complex area of the document, the code required to add a new item to our ‘items.xml’ file.

if($_POST['action'] == 'update_file')  {	  
   $product = trim($_POST['product']);
   $filename = basename( $_FILES['uploadedfile']['name']);
   $price = trim($_POST['price']);
   $metric = trim($_POST['metric']);
   $description = trim($_POST['description']);

This first section loads up variables the results of our yet-to-be-coded ‘add items’ form. It makes use of PHP’s ‘$_POST function. This function contains information submitted from a form in name/value pairs. For example, if you had a text field named ‘product’ and the user entered ‘beans’, then the name/value pair would be product=beans. Notice that the ‘if’ statement tests to see if ‘action’ has a value of ‘update_file’. The ‘action’ variable is set to ‘update_file’ using a hidden input field in our yet-to-be-coded form. This logic is what instructs the ‘if’ statement that we are looking to update the XML file. The next few lines makes further use of the $_POST function by loading up variables with the data from the submitted form.

$errors = false;
$err_msg = "";
$image_err = false;
$target_path = "images/";
$target_path = $target_path . basename( $_FILES['uploadedfile']['name']);

Next, we create a variable to hold all of our error messages and set it to a blank string. This variable is a string which is populated with messages based on our field validation. As any field tested fails validation, the associated error message is concatenated to the string giving us a listing of errors. the ‘image_err’ is a boolean variable which is set to ‘false’. If a field fails validation, this variable is set to ‘true’ which will basically prevent the a new item being created based on another ‘if’ statement we will see shortly. In our yet-to-be-coded form, one of the fields is a file upload control to upload an image. This presents the user with a ‘browse’ button and enables the user to browse for a file on their hard drive. The last 2 lines seen here set the target path to ‘images/

if ($_FILES['uploadedfile']['type'] != "image/jpeg" || $_FILES['uploadedfile']['type'] != "image/gif" || $_FILES['uploadedfile']['type'] != "image/png") {  
   $err_msg .= "\\nImage must be a .GIF, .JPG or .PNG";
   $image_err = true;
   $errors = true;
}

This is the first of our validation conditions. The ‘if’ statement tests to see if the file selected using the file upload control is either a .JPG, .GIF or a .PNG. If it fails this test, then the error message is concatenated to the ‘err_msg’ variable using .= notation. Then, two boolean variables are set to true.

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {	  
   list($width, $height, $type, $attr) = getimagesize($target_path);
   if($width > 50 && $height > 50) {
      $err_msg .= "\\nImage must be no more than 50 x 50 pixels in size";
      $image_err = true;
      $errors = true;
   }
   if($image_err == true)  { unlink($target_path);  }
}

The next ‘if’ statement checks to ensure that the file designated by the file upload control is a valid upload file (meaning that it was uploaded via PHP’s HTTP POST upload mechanism). If the file is valid, it will be moved to the target path. Keep in mind that until the move_uploaded_file function is executed successfully, the file selected using the yet-to-be-coded form will NOT exist in the target path (the images folder). Next, a list is created which is populated by the results of the getimagesize() function. The getimagesize function is used to retrieve information about an image such as width, height, type etc. We will be using it to determine the images’ dimensions. For this tutorial, we want to ensure that the images are no larger than 50 x 50 pixels. As you can see in the next ‘if’ statement, we test to see that the width and height are no larger than 50 pixels. If they are, then again, an error message is concatenated to the err_msg variable, boolean variables are set to true and execution continues. The last line basically deletes the file using ‘unlink’ if the image_err boolean variable is set to true. For example, if the user used the file upload control to select, say, an .EXE file…the image validations would fail. The image_err boolean would be set to ‘true’ because of this, and the file would subsequently be deleted. Only valid image formats that are no larger than 50 x 50 pixels will be kept..exactly what we want. I’m going to skip the next few lines because they are all basically the same. Using the strlen function, which tests the length of a string, the other fields are validated to make sure they are at least 1 character long. Also, the ‘price’ field is tested to make sure it is a numeric value using the ‘is_numeric’ function.

if($errors == false)  {
   $items = array();
   $items [] = array(
      'name' => $product,
      'id' => rand(0, 1500),
      'image' => $filename,
      'price' => $price,
      'metric' => $metric,
      'description' => $description
   );

This ‘if’ statement check to see if the ‘errors’ boolean variable is set to ‘false’. If all field validations checked out, this will be the case. In the event that the ‘errors’ boolean variable is indeed ‘false’, then a new array is created and populated with all of the necessary information to create a new item in our XML file. Notice the addition of the ‘id’ item. Because we are not using a database to save our information, we don’t have the benefit of a primary key to provide unique identifiers to our data. If the XML file were generated from database data, then this ‘id’ field could be set to some sort of primary key, but in this case I’m making the assumption that database data isn’t entering into the equation so keys aren’t an option. To help out with this, i’m creating an ‘id’ value which will be a random number between 1 and 1500. You could make the range larger but in the case of this relatively small tutorial, I figured an upper-limit of 1500 would suffice. This isn’t as fool-proof as a primary key, but it helps us slightly.

$xml = new SimpleXMLElement('XML/items.xml', NULL, TRUE);
foreach( $items as $item )  {
   $item_xml = $xml->addChild('product');
   $item_xml->addAttribute("name", $item['name']);
   $item_xml->addAttribute("id", $item['id']);
   $item_xml->addChild('image', $item['image']);
   $item_xml->addChild('price', $item['price']);
   $item_xml->addChild('metric', $item['metric']);
   $item_xml->addChild('description', $item['description']);
}
 
$doc = new DOMDocument('1.0');
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml->asXML());
$doc->formatOutput = true;
$doc->save('XML/items.xml');
header("Location: index.php");

Next, a new SimpleXML element is created using the ‘items.xml’ file. A ‘foreach’ loop is instantiated which loops through the contents of the file. Before proceeding, let’s take a look at the structure of the ‘items.xml’ file.

<?xml version="1.0" encoding="utf-8"?>
<advertisements name="Coffee Cups">
  <product name="Hamburger" id="1345">
    <image>burger.png</image>
    <price>9.99</price>
    <metric>1 pound</metric>
    <description>Enjoy our lean-cut, all-beef patties on your BBQ today.  All of our choice-cut meat is 100% Grade-A beef taken from only the most trusted and respectable distributors.</description>
  </product>
</advertisements>

Every product has a name, and a (hopefully) unique identifier, then all of the nested nodes are related to that product. Now back to the code…First, a new ‘product’ node is created then the two attributes ‘name’ and ‘id’ are added using the values of our recently created array. Then the image, price, metric, and description nodes are added. The last few lines basically convert our SimpleXML element to a DOM (Document Object Model) object. The only real reason this is done is because that, if we didn’t, our newly added nodes wouldn’t be nicely indented like the rest of the content in the ‘items.xml’ file. The ‘preserveWhiteSpace = false’ and ‘formatOutput = true’ statements ensure that everything will be nicely indented. The document is then saved and boom, we have our updated XML file. The ‘header(Location: index.php)’ line redirects us back to the index page once the XML file is rewritten. Worth note, the ‘header’ function cannot be used if any markup is displayed before it. Notice that before this line, no markup is outputted to the page. Javascript alerts are displayed if validation fails, but in that case the header function isn’t executed because all of the XML functions don’t execute if any one of the validations fail. Keep in mind that if any markup is displayed before the header function is called, it will throw an error which is not a good thing. Now that the most complex code is done, let’s look at the easy stuff.

STEP THREE – FINISHING THE INDEX.PHP PAGE

Now comes what is one of the easier parts of the code…the ‘delete’ area.

if($_GET['action'] == 'delete')  {
    if(isset($_GET['id']))  {
        $doc = new SimpleXMLElement('XML/items.xml', NULL, TRUE);
	foreach($doc->product as $item)  {
	    if($item['id'] == $_GET['id']) {
	    $dom=dom_import_simplexml($item);
	    $dom->parentNode->removeChild($dom);
	}
    }
    $doc->saveXML('XML/items.xml');
    header("Location: index.php");
    }
}

First, we use the $_GET function to test and see if the ‘action’ variable has a value of ‘delete’. The $_GET function also has a name/value basis but it is not based on form submission, it’s based on URL contents. In this case, if the ‘if’ statement passes the test the URL would look something like this ‘index.php?action=delete’
The question mark signifies the start of name/value content, and then the data follows. Next, if the ‘action’ is in fact ‘delete’, another ‘if’ statement checks to see if a variable ‘id’ has been set. We will see how the ‘action’ and ‘id’ variables are set in the coming steps. Assuming both ‘if’ statements pass, we are now ready to delete the associated XML nodes. First, using SimpleXML we load up the ‘items.xml’ file. Then, we instantiate a ‘for each’ loop to loop through the contents of the file. Within the loop, we test to see whether the XML node ‘id’ equals the ‘id’ from the $_GET contents. If they are equal, the SimpleXML element is firstly converted to a DOM object, and then subsequently deleted on the next line. Lastly, the file is saved again (minus the delete element) and the user is redirected back to the index page.

Then next step will be the default state of our ‘index.php’ page which displayed both the contents of the XML file, and the Flash banner add which uses the data from this file.

STEP FOUR – DEFAULT INDEX STATE

<?php define("IMAGE_LOCATION", "images/"); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="Author" content="Andrew Grant, andrew_grant@rogers.com">
<link rel="stylesheet" href="css/styles.css" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>XML Management Script</title>
</head>
 
<body>
<?php
if($_GET['action'] == 'view' || !isset($_GET['action']))  {
?>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript">
    var flashvars = {};
    var params = {}; 
    var attributes = {};
    swfobject.embedSWF("flash/ad.swf", "flash_content", "336", "280", "10.0.0", false, flashvars, params,  attributes);
</script>
<?php	
    $xml = simplexml_load_file("XML/items.xml");
    echo "<div id=\"left_col\">";
    foreach($xml->product as $item) {
        echo "<div class=\"item_container clearfix\">";
        echo "<img src=\"" . IMAGE_LOCATION . $item->image . "\" class=\"float_left item_image\" />";
        echo "<div class=\"item_container_inner\">";
        echo "<strong>Product</strong> : " . $item['name'] . "<br />";
        echo "<strong>Price</strong> : $" . $item->price . "<br />"; 
        echo "<strong>Metric</strong> : " . $item->metric . "<br />";
        echo "<strong>Description</strong> : " . $item->description . "</div>";
        echo "<div class=\"delete_item\"><a href=\"index.php?action=delete&id=" . $item['id'] . "\">delete this item</a> | ";
        echo "<a href=\"index.php?action=add\">add new item</a></div>";
        echo "</div>";
    }  
    echo "</div>"; 
    echo "<div id=\"flash_content\"></div>";
}
?>

First a constant for our images folder path is created. This is basically a variable that cannot be changed using code. It points to our images folder and will be used to display them. Next our DOCTYPE and other header information is outputted. Recall that in the previous steps, other than the javascript ‘alert’ statements there is no markup being displayed. That’s because all of the code was involved in processing and not the display of data. Now we want to output markup for the display of information so we need this information. Just after the BODY tag, we have another ‘if’ statement. It check to see if either ‘action’ is set to ‘view’ or if ‘action’ is not set at all. Next, we embed the Flash content in our page. First the swfobject script is embedded, and then we actually embed the content using the embedSWF function. I won’t get into the specifics of using swfobject, just know that is much easier on the eyes than the script output by the Flash IDE. The first parameter of the embedSWF function is the path to the movie itself, and the second parameter is the DIV id it will be embedded in. The last few lines again work with the XML file. First, a SimpleXML object is instantiated and set to the contents of the ‘items.xml’ file and then a ‘for each’ loop is started which loops through each elements in the file. After seeing what you have in the tutorial thus far, these lines should be fairly straightforward. After the description is outputted, we then output two links. These will be seen for every item…an ‘add’ and a ‘delete’ link. The ‘delete’ link is formed using the unique ‘id’ from the XML file. The href for the link looks like this : ‘index.php?action=delete&id=’ . $item['id'] First, the question mark signifies that name/value pairs are to follow. Then ‘action’ is set to ‘delete’ and the ‘id’ is set to the items’ id from the XML file. This URL information is then used to delete an item which saw previously. The ‘add’ link is much the same. It uses a name/value pair of ‘action=add’ to tell the script that we wish to add an item to the file. The last bit is the DIV which will hold our embedded .SWF movie. With this setup, we have a nice listing of our file as well as the Flash movie itself floated to the right of it. This way, anytime the content is updated and the user is redirected back to the index page, they will see the animation scrolling through the new content. Okay, we’re almost done…let’s look at the last step.

STEP FIVE – NEW ITEM FORM

This step is fairly easy, we’re just outputting the markup needed to display our form.

<?php
if($_GET['action'] == 'add') {
   echo "<div id=\"update_form\">";
   echo "<form method=\"post\" enctype=\"multipart/form-data\" action=\"index.php\">\n";
   echo "<div class=\"input_label\">Product</div><div><input type=\"text\" class=\"input_field\" name=\"product\" /></div>";
   echo "<input type=\"hidden\" name=\"max_file_size\" value=\"50000\" />";
   echo "<div class=\"input_label\">Image [50 x 50 - .PNG .JPG .GIF]</div><div><input name=\"uploadedfile\" class=\"input_field file_upload\" type=\"file\" /></div>";
   echo "<div class=\"input_label\">Price</div><div><input type=\"text\" class=\"input_field\" name=\"price\" /></div>";
   echo "<div class=\"input_label\">Metric [1 pound, 5 dishes etc..]</div><div><input type=\"text\" class=\"input_field\" name=\"metric\" /></div>";
   echo "<div class=\"input_label\">Description</div><div><textarea class=\"input_field textarea\" name=\"description\" cols=\"10\" rows=\"20\"></textarea></div>";
   echo "<div><input type=\"hidden\" name=\"action\" value=\"update_file\"/></div>";
   echo "<div class=\"submit\"><input type=\"submit\" value=\"Add Item\" /></div>";
   echo "</form></div>";
   echo "<div class=\"update_link\"><a href=\"index.php\">View All Items</a></div>";
}
?>
</body>
</html>

First we have an ‘if’ statement checking to see if the ‘action’ variable has been set to ‘add’ (which is done using the ‘add’ link in the last step). Notice that in the FORM declaration, there is an ‘enctype=multipart/form-data’ statement. This is needed for the file upload control to work. Everything else is pretty straightforward. Form elements are added, each with their own unique names. The name will be the variable name in the $_POST name/value pair. The values will be what the user inputs in the form. The last item worth mention is the hidden text field. These fields are not visible to the user in the form but are still included in the name/value pair listing of POST data. This field is what tells our script that we want to update the file.

That’s basically all there is to it. We now have a decidedly basic backend to edit and view our XML file and Flash animation.

One other note : I will not be touching on any of the CSS styling. You will see in the steps where markup is outputted (the ‘add new item’ form and the default view) that I make use of classes. Pour over the stylesheet to see the stylings. If you aren’t familiar enough with HTML and CSS then you might want to educate yourself further as it is outside the scope of this tutorial.

Balls Deep Under Development

The website for Balls Deep, a local recreational soccer team, is under development. The site will include a full back-end to edit player information and scores, a photo and video gallery, a news feed and user forums all wrapped in an original custom HTML/CSS layout. This dynamic website will be the most complex project undertaken by Greenleaf Designs to date and it promises to be a fantastic one. Stay tuned for more details!

Random Scrolling Content in Flash

Hi there,

This is a simple tutorial which illustrates how to scroll content into view randomly. The code also prevents the same item from being displayed twice in a row. There is one MovieClip in the library which contains one dynamic MovieClip. This textfield will be set at runtime to help differentiate each clip from one another. Be aware that I have not included the caurina Tweener package in the .ZIP archive of files. Visit google code to download the package and view the documentation. Also, I have used swfObject to embed the Flash in the example index.html file. It’s very straightforward to use and MUCH cleaner than the garbage HTML which Flash generates by default. You can also visit google code to find out more about it.


Also, here’s an example using XML data

Now let’s get to it.

STEP ONE – The Import and Global Variables

import caurina.transitions.Tweener;
 
var last_item:Number;
var first_item:Boolean = true;
var rand_num:Number;
var timer:Timer = new Timer(4000, 1);
 
// Create MovieClips
for(var i=0; i<8;i++) {
	var newNum = i + 1;
	var clip = new Array();
	clip[i] = new item();
	clip[i].name = "clip" + newNum;
	clip[i].x = 337;
	clip[i].dyn_text.text = newNum;
	addChild(clip[i]);
}
 
// Begin scrolling of content
auto_scroll();

First, we import the caurina Tweener package. This will be used to animate the scrolling of our MovieClips. Next, a number of global variables are instantiated. last_item will store the name of the last presented clip. first_item is a boolean variable which is initially set to true. Once the first clip is animated into view, it will be set to false. rand_num will hold a random number between 1 and the total number of clips, which in the case of this tutorial, will be 8. Then a timer variable is instantiated. This will help offset the time that each clip is visible, in this tutorial it will be 4 seconds. Lastly, a ‘for’ loop is started. This loops 8 times, each time creating new MovieClips, setting various properties then adding each to the stage. The name of each clip is set, it’s ‘x’ property set and then the dynamic text field within each is set to the ‘for’ loops current counter number. Now we have 8 clips each with a different number visible ready to be animated. The last line calls the ‘auto_scroll’ function which will animate all of the scrolling of content.

STEP TWO – Scrolling of Content

function auto_scroll():void  {
	//Generate random number between 1 and array length
	rand_num = randomNumber(1, clip.length);		
	//Generate another random number until is doesn't equal the last one
	while(rand_num == last_item)  {
		rand_num = randomNumber(1, clip.length);
	}
	//Only scroll in content if item is the first one
	if(first_item == true)  {
		Tweener.addTween(getChildByName("clip" + rand_num), {x: 10, time:1, transition:"Linear"});						   
		first_item = false;
		last_item = rand_num;
	}
	timer.addEventListener(TimerEvent.TIMER, transition_items);
	timer.start();
}

Here is our auto_scroll function. First, the rand_num variable is set to the result of a call to the randomNumber function. This function, which we will see shortly, accepts 2 parameters : the lower number limit and the upper number limit. It will return a random number in between the 2 limits. Next, a ‘while’ loop is begun which tests whether the last clip (it’s number) displayed is equal to the random number which was generated. If they are equal, the randomNumber function is called again in effect generating a new random number. This ‘while’ loop ensures that the next clip to be displayed will never be the same clip that was just displayed. Now an ‘if’ statement tests to see whether the ‘first_item’ variable is ‘true’. If it is, then content is only scrolled in, not out, because no items are currently being displayed. The first_item boolean variable is then set to ‘false’ because the first item has now been displayed. last_item is then set to the value of rand_num in preparation for further scrolling. Lastly, an event listener is added to the timer telling is to call the transition_items function once the preset time elapsed (4 seconds) and the timer is subsequently started.

function transition_items(event:TimerEvent):void  {
	// Scroll last item out of view and scroll new content in
	Tweener.addTween(getChildByName("clip" + last_item),   
                {x: -336, time:1, transition:"Linear", 
                onComplete: function():void  {
	              getChildByName("clip" + last_item).x = 337;} });
 
	Tweener.addTween(getChildByName("clip" + rand_num), 
                {x: 10, time:1.2, transition:"Linear", 
                onComplete: function():void  {
	              last_item = rand_num;
	              auto_scroll()} });
 
}
 
function randomNumber(low:Number=0, high:Number=1):Number  {
	return Math.floor(Math.random() * (1+high-low)) + low;
}

Here we have the transition_items function. We make use of the caurina Tweener package to animate the scrolling. The first parameter the addTween function accepts is the targeted MovieClip for the animation. In this case, we use the getChildByName(“clip” + last_item) statement to target the clip to be scrolled out. Remember that in the ‘for’ loop from Step One, we assigned the name of each clip to the word ‘clip’ followed by a number. In this case, that number will be the contents of the last_item variable. Next, the addTween function accepts which property and coordinate it should animate to : x:-336. This will make the tween animated off screen to the left of the stage. Then the ‘time’ it should take to animate, and the transition type are used. An optional parameter onComplete..this instructs the tween to execute a function on completion. I’ve opted to use what is called an anonymous function..I basically create function without a name which is executed when the tween has completed. In this case, the clip which was just scrolled off-screen is moved off and to the right of the stage in preparation to be scrolled into view again. Next, we again make a call to the addTween function, this time targeting a random clip. The clip is scrolled in along the x-axis to position 0, basically putting it right in view. It also has an onComplete anonymous function. This time it sets the last_item to the value of rand_num because this clip will now be scrolled out as the code executes further. The auto_scroll function is then called again, repeating all of our code which keeps the train rolling. The last function is randomNumber. It speaks for itself and the code is pretty straightforward.

That’s it folks, a decidedly basic tutorial on how to randomly scroll content into view. Ideal for banner advertisements and the like. For all you keeners out there, this could be applied to the Flash Banner Ad using XML tutorial I posted awhile ago. Instead of adding each item to a big container which is subsequently scrolled, each item could be scrolled into view randomly using this technique.

Evesca Completed

Evesca.com has recently been completed. Evesca is an online marketing company with offices in New York NY and Ottawa, Ontario Canada. It offers a host of services which includes Search Engine Optimization, Email Marketing Solutions, and Web Design services. General inquiries can be submitted using an online support form and free Web Design quotes can be requested using the same facilities. For those who wish to subscribe to any one of the many services offered, recurring monthly payments can be instantiated using PayPal’s checkout service via ‘Buy Now’ buttons located on any one of the pages on the site. It’s our hope that the new website will increase it’s online presence and add new clients to the already impressive list of customers who use their services. Check out the site today!

All Tails Under Development

AllTails.ca is again under development. All Tails was a static HTML/CSS site advertising the services of it’s owner Alan Golden. It had service descriptions and rates, a photo gallery and a video area which users could log into and view videos of their cherished pets. After careful consideration, Alan has a few recommendations on how the site could offer a more dynamic and robust user experience and the current site has temporarily been taken offline. Moving forward while a few options are being considered, implementing a Content Management System is more than likely one of the top priorities. WordPress, Joomla or Drupal are amongst the considerations but there are a few other possibilities. There is surely more to come. You can subscribe to our RSS feed to stay on top of future updates regarding this and other sites.

Flash Banner Ad using XML [Part one]

Hello there,

Have you been charged with designing a banner advertisement but size restrictions are getting you down? Well, this tutorial could help you out a bit. All information is grabbed from an XML file, and images are loaded externally cutting down on overall file size. There is not one asset in the library for this project. I make use of the caurina Tweener class, but if you want to use the built-in Flash Tween class it could further decrease overall file size. I opted for the Tweener package because over time I have found the native Flash Tween class to be a bit buggy and unreliable. If you make use of the Transition Manager it compounds the problem as animations freeze many times. Anyways, in part one of our tutorial we will show users how to grab the data from XML, preload many of the images and present it in a scrolling movieclip. Part two will involve designing forms and code in PHP to let users add and remove elements from the XML file. Well, let’s get to it!


STEP ONE – Image Creation

I chose to create an advertisement using the size of a large rectangle (336 x 280). This allows for the presentation of textual information in a fairly pleasing manner. You can forego image creation until the end if you like, but I prefer to have as many visual assets at my disposal before diving into Flash. You could always use the images included in the archive as well. Be aware that product images were relatively small (50 x 50) and all are 8-bit .PNGs. Choose whichever format you deem best for the task.

STEP TWO – Setting the Stage

You’ll want to edit the document properties to be in line with the advertisement size which has been chosen. There won’t be any visual assets in the library at all. You’re going to want to put you’re directory structure in place as well. There’s an images folder for, you guessed it, the graphics we’ll be using. A flash folder to hold the .FLA and generated .SWF files, and lastly an XML folder which will hold our XML file. Once that is complete, go ahead and save the .FLA in the flash folder and we can proceed.

STEP THREE – Begin Creating the Elements

Allrighty! Now we begin coding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import caurina.transitions.Tweener;
// Load XML data
var xml_basepath = "../XML/";
var xmlLoader:URLLoader = new URLLoader();
var xmlData:XML = new XML();
xmlLoader.addEventListener(Event.COMPLETE, LoadXML);
xmlLoader.load(new URLRequest(xml_basepath + "items.xml"));
// Load BG image
var image_basepath = "../images/";
var BGImageLoader:Loader = new Loader();
var BGImage:URLRequest = new URLRequest (image_basepath + "BG.jpg");
BGImageLoader.load(BGImage);	
 
var speed:int = 0;

In line 1, we import the Tweener package. We will be using this to scroll the content once it’s loaded. Lines 3 to 7 are the necessary steps to load the XML file into Flash. Notice the xml_basepath variable… you would change the basepath to the appropriate directory the file resides in. It is always relative to the directory the generated document which embeds the .SWF resides in. In this case, we want to go into the ‘XML’ and ‘images’ folders respectively. You will find that if you compile and test the project within Flash, you will have to add ‘../’ to each basepath in order to traverse the directory structure correctly. Because it isn’t being embedded in this case, the basepaths are relative to the .SWF itself so you have to actually go up a directory THEN go into each respective directoy, hence the ../ notation. We add an Event Listener to execute the LoadXML function once all data has been retrieved from the XML file. This function is where all of our code will be executed. The last few lines setup variables necessary to load the main background image as well as set the speed of the scrolling animation. Notice that a) no event listener was added and b) the image hasn’t been added to the stage yet. I opted not to add Event Listeners for the images given their relatively small file sizes. Let’s keep this moving, on to the LoadXML function..

STEP FOUR – The LoadXML function

This is where all the magic happens. Let’s take a look..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function LoadXML(e:Event):void {
	xmlData = new XML(e.target.data);
	var xml_data:XMLList = xmlData.product; 
	var counter = 1;
	var yVal:int = 0;
	var yMax:int = 0;
	var output = "";
	var main_container:MovieClip = new MovieClip();
 
	main_container.x = 0;
	main_container.y = 280;
 
        // Create BG image container and add BG image
	BGImageLoader.alpha =.2;
	var BGcontainer:MovieClip = new MovieClip();
	BGcontainer.addChild(BGImageLoader);
	addChild(BGcontainer);

Line 2 creates a new XML object from the data which was passed to the LoadXML function after it completed loading. Line 3 parses this data into an XMLList object using every ‘product’ node (and it’s child nodes) in the XML Document. Lines 4 to 8 create variables which will be used later in the function. Line 9 created a new MovieClip which will be the main container for all of the products which will be displayed. Finally the next two lines position it just below the stage which will be the starting point for the scrolling animation. The last lines set the alpha transparency of the background image to .2, creates a new MovieClip then adds the background image to it, and finally this newly created MovieClip is added to the stage. In effect, we’ve added our first visual asset to the stage. All done using coding…feels good doesn’t it?

Pretty easy so far, let’s keep going.

STEP FIVE – The FOR EACH Loop

This is by far the most complex step in the tutorial. All of the ‘meat’ of the project takes place in this loop. Let’s take a look..

1
2
3
4
5
6
for each (var xml_item:XML in xml_data) {
 
		// Create Array and populate with unique container variable names
		var part:Array = new Array();
		part[counter] = "container" + counter;
		part[counter] = new MovieClip();

The first line instantiates the loop. It takes two parameters, the first is the variable name which is of type XML. The second is the data source which, if you remember, was the xml_data variable which was created at the start of the LoadXML function. This is of data type XMLList. The first few lines of the loop create the ‘part’ Array. It will contain unique variable names for each product container. It makes use of the ‘counter’ variable which was instantiated and set to 1 at the start of the LoadXML function. Every time the loop completes (once for each product in the XML file), the counter increases by one in effect giving us unique variable names for each product container contained in the ‘part’ array.

1
2
3
4
5
6
7
8
9
10
11
12
// Create dynamic text field and set properties
		var xml_format:TextFormat = new TextFormat();
		xml_format.size = 12;
		xml_format.font = "Arial";
		var xml_text:TextField = new TextField();
		xml_text.width = 260;
		xml_text.wordWrap = true;
		xml_text.x = 20;
		xml_text.y = 20;
		xml_text.defaultTextFormat = xml_format;
                xml_text.autoSize = TextFieldAutoSize.LEFT
		part[counter].addChild(xml_text);

Next up, the dynamic text field which will contain the information retrieved from the XML file. First, a TextFormat object is instantiated. This will help us set properties like the font type and font size. Then the actual text field is created. We set properties like the width, starting x and y coordinates and wordWrap to equal true. If wordWrap weren’t set to equal true, our text would just extend to the right until the end. The final property to be set is autoSize. This ensures that the height of the text field automatically changes based on how much text there is…this is an important point which comes into play later in the loop when we want to determine the height of the main container. The last 3 lines set the defaultTextFormat to be our TextFormat values which were set. The newly formatted TextField is then added to the ‘part’ container for the product. Now we’re cooking with fire!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Load up variables with XML element data
		var item_data:Array = new Array();
		item_data[0] = xml_item.attribute("name");
		item_data[1] = xml_item.image;
		item_data[2] = xml_item.price;
		item_data[3] = xml_item.metric;
		item_data[4] = xml_item.description;
 
		// Load product image
		var imageLoader:Loader = new Loader();
		var image:URLRequest = new URLRequest (image_basepath + item_data[1]);
		imageLoader.load(image);
		imageLoader.x = 235;
		imageLoader.y = 20;
 
		// Load item separator image
		var separatorImageLoader:Loader = new Loader();
		var separatorImage:URLRequest = new URLRequest (image_basepath + "separator.png");
		separatorImageLoader.load(separatorImage);

Now, an array is created to hold the XML element data for the product called item_data. Each array position is set to a specific element in the xml_item variable which is an XMLList. Every product node in the file has a ‘name’ attribute which identifies the name of the product which is grabbed using the xml_item.attribute(“name) syntax. Every other element are simply text between opening-and-closing element tags so they are all grabbed in the same way. Next, we create the necessary items to retrieve each product image. First the loader is created, then a URLRequest is made which is the basepath with the filename added to it. Then the image is loaded. Notice that we haven’t added it to the container clip yet. We also set the x and y coordinates of the image placing it in the top-right corner of every ‘part’ container.

We then do much the same thing for the separator image. This will be the background image for every ‘part’ container lending a sense of separation between each product.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Set output variable
		output = "<b>Product</b> : " + item_data[0] + "\n";
		output += "<b>Price</b> : $" + item_data[2] + "\n";
		output += "<b>Metric</b> : " + item_data[3] + "\n";
		output += "<b>Description</b> : " + item_data[4] + "\n\n";
 
		// Set dynamic text field htmlText to that of output variable
		part[counter].getChildAt(0).htmlText = output;
 
		// Add separator image to container
		part[counter].addChild(separatorImageLoader);
		// Add product image to container
		part[counter].addChild(imageLoader);
		// move separator image to the back of display list for part[counter] movieclip
		part[counter].setChildIndex (part[counter].getChildAt(0), (part[counter].numChildren - 1));
		part[counter].x = 13;
 
		// only offset every item after the first one
		if(counter > 1)  {
			yVal = this.getChildAt(this.numChildren - 1).height + 45;
			part[counter].y = yVal;
		}
 
		// Add product to main scrolling movie
		main_container.addChild(part[counter]);
		// Add main scrolling movie to the stage
		addChild(main_container);
		yMax = main_container.height;
                speed = yMax / 30;
 
		counter++;

The next part assigns string content to the output variable. Notice that bold tags were used to style each product label…text can be styled using a limited number of CSS tags (bold) being one of them. The htmlText property of the dynamic text field is set to the contents of the output variable. HTML can only be styled if it is htmlText. If we chose instead to set the .text to equal the output string, the labels wouldn’t be in bold face. This assignment is done using part[counter].getChildAt(0).htmlText = output; Because the text field was the last item added to the ‘part’ container, we can access it using that code. It basically accesses the most recent child clip of the ‘part’ container and sets the htmlText property to the contents of the output variable. Having previously loaded the product image and separator image, we then add these items to the ‘part’ container. This line of code : part[counter].setChildIndex (part[counter].getChildAt(0), (part[counter].numChildren – 1)); essentially moves the separator image to the back of the ‘part’ display list. If we didn’t execute this, the separator image would appear above the text field and product image making things look decidedly weird. The IF statement which follows is used to offset each product, except the first one, by the height of the previous ‘part’ container plus 45 pixels. If we didn’t include this bit of code, every ‘part’ container would be stacked on top of each other again making things look weird.

This last few lines basically add all of the main generated content to the stage. First, the ‘part’ object is added to the main container. Remember that we’re doing this within a FOR EACH loop so every product node in the XML file has a corresponding ‘part’ object which is added until the end of the document is reached. After that, the main container is added to the stage and we’re basically done. The yMax variable is set to the height of the main container, the speed variable is set (which is used by the auto_scroll function to determine scrolling speed) and the counter variable is iterated as the loop moves through the XML content. Now all that is left is to scroll the content, which we’ll do now.

1
2
3
4
5
6
7
8
9
10
11
12
// Begin scrolling of main container
	auto_scroll();
 
	function auto_scroll():void  {
		// Scroll content to maximum y value
		Tweener.addTween(main_container, {y:-yMax, time:speed, transition:"Linear", onComplete:reset_container });
	}
	function reset_container():void  {
		// Return main container to starting position and begin scrolling again.
		main_container.y = 280;
		auto_scroll();
	}

We then call our auto_scroll function. This begins the scrolling animation of our main container. Remember that we positionned the main container just below the threshold of the stage so it’s just out of view right now. We then define the auto_scroll function which makes use of the Tweener package. It takes a number of parameters. First, the targeted movie clip we want to animate, which is the main_container. Next is the y-value we want to animate to. This is set to the negative value of yMax, yMax being the height of the main container. The origin of our movie is (0,0), the top-left corner of the movie. If we want to move up, a negative y-value is needed which is why we want the negative value of yMax. The time value is the amount of time it should take for the animation to complete. In this case it is set by the predetermined ‘speed’ variable which was calculated at the end of the LoadXML function. Transition could be one of many preset transition types which could be used and finally, the onComplete statement calls the reset_container function which basically moves the main container back to its starting position once scrolling is complete. You can read the documentation on the caurina Tweener class here.

That’s basically all there is to it. Comb over the code and soak up the references. File constraints shouldn’t be a factor now…most ad servers impose anywhere from 30KB to 50KB size restrictions for Flash animations. The overall filesize (with Tweener package) is just about 12KB. This same project with visual assets in the library would be upwards or 50KB+ depending on how big the XML file is and the number of accompanying images. No matter how many items there are, the filesize will always remain constant using this approach. Tune in for Part Two of the tutorial coming soon. We will detail how to create a simple back-end application to edit the XML file using PHP. Concepts such as using both SimpleXML and Document Object Model (DOM) to add or delete XML elements, uploading and saving image files and simply viewing your XML file will be covered.

Click herefor part two of this tutorial. Thanks for tuning in!

Maestro Limousine Completed

The website for Gatineau’s premiere limousine and shuttle bus rental company has now been completed. The website was redesigned from the ground-up and includes various package information, gallery and form mailing functionality. As with every website designed by Greenleaf Designs, the site is fully XHTML 1.0 Strict compliant and is optimized for view in all major browsers. Visit the site today!

Omega Homes Completed

Omega Homes has been completed and is now live. The site showcases homes built by the company in the Ottawa area and offers ways to subscribe to promotional information as well as forms to contact the owners. There is also a photo gallery showcasing the company’s craftsmanship and as well as links to relevant home-building information. It’s our hopes that the site will increase awareness in their services and help bring prosperity to the business in the future. Visit the site