Automatically Export Multiple Form Values
Published
February 3, 2008
Difficulty
Intermediate - Advanced
Requirements
Flash 8, Apache
Something always annoying in flash is dealing with forms that have many fields. If you are talking about 50 or so text fields, this may mean 50 times doing the same thing - exporting each variable from flash, and retrieving each variable from your server language (for emailing or database queries). At one point a client needed a large flash form, and I wanted an automatic way of exporting/retrieving the data as I hate doing things more than once.
Storing the values in Flash
Flash was the trickiest part and after trialing a few methods I found a great solution. The idea was to use a flash Object(), which acts as an array but we can store values in the key. Using this object I could then cycle through all values and send them to a server language. Additionally I wanted a function that all fields call that does all the necessary object setting. Below is my function what I have added to the first frame:
_global.values = Object(); // set an empty values object at a global level
function field(target, event_type) {
if (target.groupName) { // if RadioButton use the group name
var field_name = target.groupName;
} else { // if not a RadioButton
var path_array:Array = String(target).split("."); // breaks apart the path to the instance name
var field_name = path_array[path_array.length - 1]; // the instance name will be the last element in the array
}
var listener:Object = new Object();
listener.handleEvent = function(obj:Object) {
if (target.groupName) { // if RadioButton
_global.values[field_name] = target.label;
} else if (target.text) { // if TextInput or ComboBox
_global.values[field_name] = target.text;
} else { // if CheckBox
_global.values[field_name] = target.selected;
}
}
target.addEventListener(event_type, listener);
}
The very first line creates an empty global object called values. This is where we will store all our field names and field values. Below that we declare our function called field with two parameters "target" and "event_type". Target will refer to itself or "this" in flash lingo, and "event_type" refers to the necessary event needed to execute the listener. Now lets break down how this works:
function field(target, event_type) {
...
if (target.groupName) { // if RadioButton use the group name
var field_name = target.groupName;
} else { // if not a RadioButton
var path_array:Array = String(target).split("."); // breaks apart the path to the instance name
var field_name = path_array[path_array.length - 1]; // the instance name will be the last element in the array
}
...
The first thing we want to do is find the instance name of the component. The instance name must be clear because it will be used again - more about it later. Depending if the component is a RadioButton or not, the method on how we get the instance name is different. The first line of the if statement is if the component is a RadioButton, and the easiest way to test for this is to check if the target (this) has a groupName. If it does we can use the value to store in our new field_name variable. If it is not a RadioButton, we break apart the _root path to the instance based on the full stop. With this array we use the last element of the array as our field_name variable.
function field(target, event_type) {
...
var listener:Object = new Object();
listener.handleEvent = function(obj:Object) {
if (target.groupName) { // if RadioButton
_global.values[field_name] = target.label;
} else if (target.text) { // if TextInput or ComboBox
_global.values[field_name] = target.text;
} else { // if CheckBox
_global.values[field_name] = target.selected;
}
}
target.addEventListener(event_type, listener);
}
Next we create a new listener object which we can use to add events. So when an event is called (eg. click or change) it will run the handleEvent function. Inside the function the only purpose is to add the components value to the _global.values object. Not quite that simple as each component stores it value differently, so we must do an if statement. I won't go through in detail as it is self explanatory.
function field(target, event_type) {
...
target.addEventListener(event_type, listener);
}
Lastly we run an addEventListener, and this is where we need the functions second parameter "event_type" which is defined on the component when the function is called.
Using this function is really easy, for my example I am using flash's standard components (RadioButton, TextInput, ComboBox and CheckBox) and adding the following to each:
onClipEvent(load) {
_parent.field(this, "change");
}
This script will execute when the component is first loaded. We must go up to the components parent level to read the function. The first parameter will always be "this", but the second will change depending on what component you are using. "change" will be used for TextInput's and ComboBox's, and "click" will be used for RadioButton's and CheckBox's.
Sending the values to PHP
Now we have it so that the components field name and value are getting stored in a flash object, so now we need to send this to PHP. In my example I am using a Button component and adding a few lines should do the trick:
on(click) {
for(i in _global.values) {
this["!" + i] = _global.values[i];
}
loadVariablesNum("database.php", 0, "POST");
}
I used a for loop, which cycles through all elements of the _global.values object. The variable "i" will be the key in the object (field name) and "_global.values[i]" will be the objects value. So with this information I create a new variable on the _root timeline of the field name. I add an exclamation mark at the start for use in PHP later. Finally we are using loadVariablesNum to send the variables to a PHP file by POST method. All variables on the _root timeline will be included in the POST.
Retrieving the values in PHP
The first parameter indicates the URL to the server language file executing our script further. My preferred language is PHP, and with this file we can do things like database dumping or email sending which I will do below. My PHP file is as follows:
<?php
foreach($_POST as $key => $value) {
if (strrchr($key, '!')) {
$field = str_replace('!', '', $key);
$message .= ucfirst($field).': '.$value."\n";
}
}
mail($_POST['!email'], 'Export Multiple Values', $message);
?>
Very simple script all it does is loop through all elements in our $_POST array, retrieving the $key and the $value. Normally there would be many results (eg. _minHeight, invalidateFlag, rolloverSkin) as they are all stored in the _root timeline along with our fields/values. That is why we added an exclamation mark to the start of each variable name, so in PHP we can use strrchr to only use the $_POST elements that have '!' in their $key (field name). With this we create a $field variable and use str_replace to replace all instances of '!' with an empty space. Next we have a $message variable that continually adds to itself displaying the $field variable (uppercase the first letter) and the $value of the field. "\n" is important as it adds a new line after each $message.
Finally we use PHP’s mail function to send the email to the posted email variable, and add a subject plus the $message varialble. Unfortunately the email displays all lines backwards, but I cannot find a way to reverse the $_POST array. If anyone knows drop a comment.
About the Author 'Ryan'
Ryan Davis
http://www.evolutionmultimedia.com.au Ryan Davis is the founder of Multimedia Life. In an industry where the geography of clientele is not important, he freelance his skill to all parts of the world. Ryan is a huge fan of flash, and loves designing, animating, and programming.
More about Ryan »
Post new comment