Advertisement

Build a Dynamic Guest Book with XML and ActionScript 3.0

by
Student iconAre you a student? Get a yearly Tuts+ subscription for $45 →

Guest books are a great thing to enhance the online experience your viewers receive. The ability for the viewer to talk to you and others, respond to questions you've raised, comment on your work or just to socialize means a guest book is a must have for most web sites. Let's see how we can build our own guest book with ActionsScript 3.0, XML and PHP.

Introduction

There are two main ways I can think of to power a guest book; the more commonly used MYSQL database driven, or the less common XML type. They both rely on server-side scripting to work, however the advantage that I see from using the XML version, is the simple fact that you need not worry about whether your host supports MYSQL and you also don't have to program in 3 different languages. So what will you gain from reading this tutorial I hear you ask?

  • You'll learn how to program in ActionScript 3.0 (which took me a long time to learn...)
  • You'll learn how to get data from an XML file and convert it into arrays to work within Flash.
  • You'll learn how to use these arrays to populate the text field.
  • You'll learn how to program buttons and a scroll bar.
  • Finally, you'll also learn how to convert text into xml and send it to a php file where it will be written to the xml file.

Quite a mouth full! Let's get started.

Step 1 - Getting Started

You should already know how to open flash, or at least I hope you do... You can set up flash however you choose, there are no specific requirements for Frame Rate or Stage Dimensions, however, make sure you have set it to "Action Script 3.0". If you want to go ahead and copy me word for word I will show you how mine is set up (how nice).

Setup Screen

Step 2 - Stylize

As you can tell from the image below, I have fantastic creative skills! This is the point where we design the guest book, or moving into the modern era, a guest computer or guest phone. I'm sure you'll do a better job in making yours look more professional than mine does, but just for those who are new to flash, I'll quickly run through how I created my unique design.

Select the "Rectangle tool", click on "Properties", set the "Stroke" to be "3" and the "Corner Radius" to be "10". Then click and drag to create your rectangle. Make another smaller one on top of that in a different color, this is where the messages will be displayed. Select the new shape and hit "F8" to convert it to a Movie Clip. Then go to "Filter" and apply a "Drop Shadow". Then draw yet another rectangle off to the side; this is where the input fields will go.

Guestbook Design

Step 3 - Loading the XML

So we venture into the unknown for the first time! Start by creating a new file with the extension ".xml". Then inside that write the following:

<messages>
</messages>

Save the file as "messages.xml" in the same folder as your flash file. Now, back in flash, create a new Layer called "Actions" and hit "F9" to bring up the "Actions Panel". It will be much more beneficial to you if you type in the code I give you by hand rather than copying and pasting it, so by hand type:

var urlRequest:URLRequest = new URLRequest("messages.xml");
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener (Event.COMPLETE,fileLoaded);
urlLoader.load (urlRequest);

This bit of code is setting up a variable called "urlRequest" which is holding the path to our ".xml" file. It then creates another variable called "urlLoader" which will be used to load our file. The "addEventListener" is telling flash to wait until the "url" has been loaded before running the "fileLoaded" function. The final line is just telling the "urlLoader" to load "urlRequest" which is our ".xml" file.

var myXML:XML = new XML();
myXML.ignoreWhitespace = true;
var xmlList:XMLList;

These lines create a new variable called "myXML" which is going to store all of the data from our ".xml" file. It then tells the variable to "ignoreWhitespace" which doesn't do much, but it helps with validation. The last line creates a variable called "xmlList" which will store the messages and information which we will extract into arrays.

Step 4 - Arrays

var arrayName:Array = new Array();
var arrayTitle:Array = new Array();
var arrayDate:Array = new Array();
var arrayFull:Array = new Array();

This bit of code is setting up the arrays which will hold all of the data. For now it would be best to keep yours the same as mine so you don't get any errors later. You should note that "Full" is what I have used to represent the long message that the user writes.

function fileLoaded (event:Event):void {
	myXML = XML(event.target.data);
	xmlList = myXML.children();

This is the function "fileLoaded" which is called when the ".xml" file has been loaded. In the function we give the "myXML" variable the data from the ".xml" file. We then give "xmlList" the data stripped from "myXML" which is everything except from the "messages" holder we wrote earlier. Obviously there is nothing else apart from that so "xmlList" will be empty.

	for (var i:int=0; i<xmlList.length(); i++) {
		var xmlName:String = xmlList[i].name;
		var xmlTitle:String = xmlList[i].title;
		var xmlDate:String = xmlList[i].date;
		var xmlFull:String = xmlList[i].full;
		arrayName.push (xmlName);
		arrayTitle.push (xmlTitle);
		arrayDate.push (xmlDate);
		arrayFull.push (xmlFull);

This is the main part of the function. It goes through the data stored in "xmlList" and places it into different arrays. The code starts with a "for" loop, which is saying: while the variable "i" is smaller than "xmlList.length()', run this code. "xmlList.length()" will be how many people have submitted messages, so if it is equal to 5, this code will run 5 times.

Then, for each attribute (name, title, date and the message) we create a "String Variable" equal to the corresponding attribute inside the "xmlList". The first time the code is run, providing there are some entries, "i" will be equal to 1 and "xmlName" will be equal to which ever name is first in "xmlList". The second time it goes through, "i" will be equal to 2 and "xmlName" will be equal to which ever name is second in "xmlList".

What then happens is that each of the variables is added to the arrays. The value of "xmlName" will be added to "arrayName" by the ".push" method. This means that as the code is run through, all of the names that are stored in "xmlList" are added into the array. The same applies for title, date and full.

		if (i == xmlList.length() - 1) {
			updateText ();
		}
	}
}

This is the ending part of the function. It states that if "i" is ever equal to the total amount of entries - 1, run the function "updateText".

Step 5 - Showing the Messages

Now, after that grueling piece of coding, we get to something a little easier, he says...

On a new layer called "textBox" use the "Text Tool" to create an "Input Text" field over the lighter rectangle. Make sure that you select the "Render text as HTML" box under "Properties > Character" and give it an "Instance Name" of "messageText".

Text Field

Go back to the actions window and underneath all of the code type the following:

messageText.htmlText = "Be the first to post!";
var maximumMessages:Number = 5;
var currentMessages:Number = 0;
function updateText () {
	messageText.htmlText = "";

The first line is incase no one has written anything. The variable "maximumMessages" is the amount of messages the we want to be displayed at one time. The "currentMessages" is the last message that has been displayed in the text field. Then we start the function which is called after the arrays have finished being created. The first thing this does is to clear the text field as we don't always want that message to be at the top.

	for (var i = currentMessages; i<maximumMessages; i++) {
		messageText.htmlText += ("<b><u>Name:</u></b> " + arrayName[i]);
		messageText.htmlText += ("<b><u>Title:</u></b> " + arrayTitle[i]);
		messageText.htmlText += ("<b><u>Date:</u></b> " + arrayDate[i]);
		messageText.htmlText += ("<b><u>Message:</u></b> " + arrayFull[i]);
		messageText.htmlText += (".....................................................");
	}
	currentMessages=i;
}

This is another "for" loop. This time we are using it to populate the "messageText" field. Here we are setting "i" to equal "currentMessages" which at the moment is equal to 0. Then if "i" is less than "maximumMessages" which is equal to 5 we run this code. It will therefore run 5 times.

The first time it runs it will add "Name:" to "messsageText" and then whichever name is in the arrayName array at the place of "i" which will be equal to 0. It will do this for title, date and full before ending with a line of dots to separate the messages. The second time it runs through, "i" will be one greater, so it will add more text with results after the first set in the arrays. At the end we set "currentMessages" to equal "i".

Step 6 - Components

At this point you're probably doing well if you don't have a head-ache. So let's do something easy. Go to "Window > Components" and from the list drag out two "Buttons" and one "UIScrollBar". Position them like so:

Components

Then go to "Window > Component Inspector" and with the left button selected, click on the "label" and rename it "Previous". With the button on the right, rename it "Next". Then define the "Previous" button's instance name as "prevBt", the "Next" button's as "nextBt" and the "UIScrollBar's" instance name as "scroller".

Now, under the "currentMessage=i;" piece of code write the following:

scroller.scrollTarget = messageText;

This tells the "UIScrollBar" to act as a scroller for "messageText", incase there are too many words to fit in the designated space. We now need to check if the buttons are being pressed, so underneath all of the code write:

nextBt.addEventListener (MouseEvent.MOUSE_UP,nextFunc);
prevBt.addEventListener (MouseEvent.MOUSE_UP,prevFunc);

This adds a listener to see if the mouse cursor has been released over the buttons (if they have been pressed) and if they have, the listener calls a function which we'll write in the next step.

Step 7 - Coding the buttons

If the "Next" button has been pressed we want the "messageText" to remove what's in it and load the next messages. If the "Previous" button is pressed we want it to load the previous messages. At the bottom of all of the code write:

function nextFunc (event:MouseEvent) {
	messageText.htmlText="";
	maximumMessages+=5;
	updateText ();
	prevBt.enabled=true;
}

This is the "Next" function. When triggered, it clears the text field, adds 5 to "maximumMessages", runs the function "updateText" and enables the "Previous" button. By adding 5 to "maximumMessages" and running the "updateText" function, it loads the next 5 messages into the text box because now, "maximumMessages" is equal to 10 and "currentMessage" is still equal to 5 from the last time the function ran. Therefore, this time the text field will display the next 5 messages in the arrays.

function prevFunc (event:MouseEvent) {
	messageText.htmlText="";
	maximumMessages-=5;
	currentMessages-=10;
	nextBt.enabled = true;
	updateText ();
	if (currentMessages<=5) {
		prevBt.enabled=false;
	}
}

This is the function for the "Previous" button. This again clears the text field, it also subtracts "maximumMessages" by 5 and "currentMessages" by 10. This is so that when the "updateText" function runs, it displays the previous 5 entries. It also enables the "Next" button. If "currentMessage" is less than or equal to 5, the "Previous" button is disabled so that the user can't display false information; there are no messages lower than 0.

Just under "function updateText () {" write:

	if (arrayName.length <= maximumMessages) {
		maximumMessages = arrayName.length;
		nextBt.enabled = false;
	}
	if (currentMessages < 0) {
		currentMessages = 0;
		maximumMessages = 5;
		nextBt.enabled = true;
	}

The first "if" is checking if the total number of messages is less than or equal to the maximum. If this is the case, we are displaying the last entry and don't want the user to be able to click the "Next" button, so we disable it. It also makes "maximumMessages" equal the total amount of messages so that we do not display extra unneccesary information.

The second "if" is checking if we have gone into minus numbers. If we have, it defaults back to the start and displays the first 5 entries. Also after this code:

if (i == xmlList.length() - 1) {
	updateText ();
}

add the following:

if (i > 4 ) {
	nextBt.enabled = true;
}

This is checking if there are more than 5 entries. If there are then we enable the "Next" button. Remember that it's 4 because "i" starts at 0 not 1. Finally, at the top enter the following:

nextBt.enabled = false;
prevBt.enabled = false;

This is disabling both buttons.

Step 8 - First Test

Okay, open your ".xml" file and type:

	<message>
		<name>Chris</name>
		<title>Hello</title>
		<date>7th</date>
		<full>this is very complicated =-(</full>
	</message>

Type it between the tag we wrote earlier, so the whole ".xml" file should only contain:

<messages>
	<message>
		<name>Chris</name>
		<title>Hello</title>
		<date>7th</date>
		<full>this is very complicated =-(</full>
	</message>
</messages>

Save the ".xml", then test the flash file and you should see this:

First Test

Step 9 - Submit Boxes

Now that we have the first part working, without a break, let's steam into the second section.

It's time to create the area that the user fills in to submit a message. Use the "Text Tool" and create 4 "Static Text Fields" saying "Post a Message", "Name:", "Title:" and "Message:".

Then create 3 "Input Text Fields" and put one next to each element that you want to be filled in. Be sure to make the "Message:" input box larger than the others.

Select the text field where the user will enter their name and give it an "Instance Name" of "inputName". Do this for the title and message boxes, giving their Instance Names "inputTitle" and "inputFull". On all of my three boxes I have selected the "Selectable" and "Show border around text" boxes. Then, open the "Components" panel again and drag out another Button. This time open the "Component Inspector" panel and change its "label" to "Submit" and its "enabled" to false. Give it an Instance Name of "submitBt".

Input Box

Step 10 - Setting Up Variables

inputName.text = "";
var newName:String = "";
inputTitle.text = "";
var newTitle:String = "";
inputFull.text = "";
var newFull:String = "";

Place this code under all of your other code. This is saying that each of the "Input Fields" which we created in the previous step are blank. It's also creating a variable for each element and specifying it as a "String" with the value of nothing.

function onEnterFrame (ev:Event):void {
	if (inputName.text != "" && inputTitle.text != "" && inputFull.text != "") {
		submitBt.enabled = true;
	}
}

Place this function after all of the code. This function is checking that all of the "Input Fields" contain text. "!=" means does not equal and "&&" is saying "and". So the function is saying: if all of the "Input Fields" are not blank (meaning that the user has filled them in) enable the "submitBt" button. Now we need to be able to call this function all of the time so we need another listener.

addEventListener (Event.ENTER_FRAME, onEnterFrame);

This is saying that every time flash enter the frame (which for me is 30 times a second) call the "onEnterFrame" function.

Step 11 - Date

Now that the submit button is active we need to check if it's been clicked, so we need another listener.

submitBt.addEventListener (MouseEvent.MOUSE_UP,sendData);

When released, this listener will call the function "sendData", so now we need to write the function.

function sendData (event:MouseEvent):void {
	var dateToday:Date = new Date();
	var thismonth:uint = dateToday.getMonth();
	var month:Array = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
	var dateStr:String = (dateToday.getDate()+" "+month[thismonth]+" "+dateToday.getFullYear());

The first line is opening the function. We then set "dateToday" as a variable and if I then immediately trace "dateToday" it would show "Fri May 5 10:07:32 GMT+0100 2009".

The next line sets the variable "thismonth" as the number which is equal to the current month stored inside "dataToday" As we're currently in May which is the 5th month, if I traced "thismonth" it would reply 4, because it starts at 0, not 1. We then create a new array, storing all of the months in order. Then the "dateStr" is going to store the final date which will be displayed on the guest book.

"dateToday.getDate()" extracts the integer of the current day, so for the 5th, it will extract 5. Then we put in the value of the "month" array that is equal to "thismonth", so it swaps a number for a string of the month. Then the "getFullYear()" extracts the current year in 4 digit format. So if we now trace "dateStr" we get "5 May 2009".

Step 12 - Creating new XML

Now that the user has hit submit, we need to transform the details into xml format so they can be written to the ".xml" file.

	newName = inputName.text;
	newTitle = inputTitle.text;
	newFull = inputFull.text;

This is turning the variables we defined earlier to equal what the user has entered into the boxes.

	var newItem:XML = XML("<message><name>" + newName + "</name><title>" + newTitle + "</title><date>"+ dateStr+ "</date><full>" + newFull + "</full></message>");

This daunting piece of code is creating a new variable called "newItem" which is going to store xml data. We then set it to equal an xml formatted string. We start the string with "<message>" which is going to hold all of the details for the user. We then put in the Name, Title, Date and Full variables that we created before, closing it with "</message>".

	myXML.appendChild (newItem);

We are now using "appendChild" to add a "newItem" to the "myXML" which is storing all of the information for the xml file.

Step 13 - Sending The XML.

Now that "myXML" is updated with the new message we need to send it to php.

	var request:URLRequest = new URLRequest("messages.php");
	request.data = myXML;
	request.contentType = "text/xml";
	request.method = URLRequestMethod.POST;

Here we are creating a new variable called "request" which is holding the location of our php file. We haven't created this file yet, but I can tell you what we will call it (lucky you!). We'll save it in the same folder as all of our files and call it "messages.php". The next line is telling the "request" that it's sending off the information inside "myXML". We are then telling it that this data is in "XML" format and that we are using "post" to send the data.

	var loader:URLLoader = new URLLoader(  );
	loader.load ( request );
	loader.addEventListener ( Event.COMPLETE, loaderDone );
}

Now we are creating a new "loader" to handle the sending of the data, just like earlier when we were receiving the data. We add a listener to check if the data has been sent and if so, it triggers the "loaderDone" function.

Step 14 - Refresh Flash.

Before we move into php there is one last thing we must do inside flash:

function loaderDone (evt:Event):void {
	arrayName = [];
	arrayTitle = [];
	arrayDate = [];
	arrayFull = [];
	inputName.text = "";
	inputTitle.text = "";
	inputFull.text = "";
    submitBt.enabled = false;
	maximumMessages = 5;
	currentMessages = 0;
	messageText.htmlText = "";
	urlLoader.load (urlRequest);
}

This function is clearing the arrays, clearing the Input Text Fields and clearing the messages from the message box. It is also telling "urlLoader" to reload the xml file. This will then trigger the guest book to go back to the start, reload the xml file which has our new entry, populate the arrays and display the first 5 messages once again.

Step 15 - Moving to PHP

Now that we've finished in flash save it and publish the new version. Open up a new php file called "messages.php".

<?php 
if (isset($GLOBALS["HTTP_RAW_POST_DATA"])){
    $xml = $GLOBALS["HTTP_RAW_POST_DATA"];
    $file = fopen("messages.xml","wb");
    fwrite($file, $xml);
    fclose($file);
} 
?>

This code creates the variable "xml" and assigns it the value of the data that has been sent from flash. It then creates the "file" variable which stores the location of the xml file. "fopen" tells php to open the file, "fwrite" then uses "file" to write the contents of the variable "xml" into it. "fclose" then closes the xml file with the new message safely stored in it, ready to be read by the flash guest book once again.

Conclusion

Finally, upload the files onto your server! Remember these will not work on your hard drive unless you have php installed. Locate the guest book and see if it works, hopefully it will! Thanks for your time, I hope you learned something useful!

Finished
Advertisement