Get Adobe Flash player

Contact Form Class

Every web site I design has one common element, and that is a Contact Form of one sort or another. After years of building and rebuilding contact forms, I finally got smart and put together a package with the core features common to every contact form I built. Now I can simply reshape this core into whatever it needs to be for the particular project I'm working on. This approach uses AS Classes. If you are not familiar with using classes, don't run away just yet. It will be a bit foreign to you, but I think you will soon see the advantages to working this way, and, like me, be glad you did.

What you need

To follow along with this tutorial, download the contactForm.zip file. It contains the ContactForm.as file, Main.as file, the contactForm.fla and the contactForm.php script. Without changing anything, this package will give you a basic Contact Form that you can set up in a few minutes. To get you going right away, we'll look at the two ways to use these files, before we dive into how to rearrange them to do anything extra that you need them to.

First, we'll look at a standalone example. You will be using the contactForm.fla, the Main.as and the ContactForm.as files. Please note: Both examples assume that you have all the files in the same folder.

And here is what we will be building:

Standalone

The contactForm.fla is empty. (It is made in CS4, but you can create one in CS3 pretty easily.) There is nothing on the stage, but have a look in the library. There you will find a Button component and a TextArea component. The List, TextInput and UIScrollBar are also there, but they come as part of the TextArea. To get components into the library, simply drag them from the Components panel straight into the library. Now they are available for use in our class files. Also notice under Properties that the Document Class is Main.as. The only other thing to note is that the example fla is 530 pixels wide by 460 pixels high. The form, as it is laid out in the ContactForm.as class, requires a minimum space of 490 pixels wide by 440 pixels high. This sizing of this fla will give you a 20 pixel margin on the left and the right, with a 10 pixel margin on the top and the bottom.

Open up the Main.as file and you will see that it is very simple.

    package{
	import flash.display.*;
	
	public class Main extends Sprite{
		
		private var cf:ContactForm;
    

First we have our package declaration, and then we import the only class we will need here. Next, we declare a new variable called cf to act as our contact form.

cf = new ContactForm("Site Visitors Comments", "xty@xtydigitaldesign.ca", "Xty Digital Design");
cf.x = 20;
cf.y = 10;
addChild(cf);

In the constructor, we create an instance of cf and set it's x and y properties to give the margins we discussed above. There are three parameters to fill in here. The first is the Subject Line of the email the contact form will send, the second is the email address that you want to send the form to and the third is the name of the person or company you want to send the form to.

And that is all you need to do. Publish the movie and weave the html code into your contact page. Upload that contact page, the contactForm.swf and the contactForm.php file to your web server and you're good to go. You don't need to make any changes to the contactForm.php file since you have passed the parameters it requires in the ContactForm itself.

Using it in an existing Flash Movie

The second method of using this is nearly the same, but you won't be using the contactForm.fla or the Main.as file. Instead, you will declare the cf variable and create an instance of it in whatever flash movie you want to add the contact form to. You will need to set up the x and y properties to fit in with your existing movie, but that is the only difference.

Now we will take a look at the ContactForm.as file. The contact form as it is now is very simple, and you may require other information to be collected and passed on. We'll take a look at how to do that below.

In the ContactForm.as file you will see an additional field which is commented out. Use that as an example of what you need to add, and where you need to add it. What you need to keep in mind is that when you add additional fields to the contact form, you will need to add those fields into the contactForm.php file as well. In the contactForm.php file, there is also an example of adding an additional field. The other thing to keep in mind when adding more fields is that the height of the movie will increase. You will need to adjust the contactForm.fla or make allowances in your flash movie for this extra space.

But what if you need to collect extra information that is not part of the core Contact Form? That's what we will take a look at next.

The ContactForm Class

Now we will take a look at the ContactForm.as file. If you are already familiar with writing classes you can skip ahead to the Nitty Gritty section since the following few paragraphs are for the benefit of those who are scratching their heads and saying, Why the heck would you want to write all this code when it's so easy to just draw a text field on the stage?

You are right, of course. It is easy to draw a textfield, but what you will come to see is that once the initial work of creating a text field in code is accomplished, you have much more control over that text field. Here is an example of a scripted text field:

    t1 = new TextField();
    t1.x = xPos;
    t1.y = yPos;
    t1.height = 40;
    t1.width = 490;
    t1.multiline = true;
    t1.wordWrap = true;
    t1.text = "Feel free to contact us with your comments, questions and suggestions by filling out the form below.";
    t1.setTextFormat(titleFormat);
    addChild(t1);

And you have created a TextFormat like so:

    titleFormat = new TextFormat();
    titleFormat.align = "left";
    titleFormat.font = "Arial";
    titleFormat.size = 10;
    titleFormat.color = 0x000000;

Now, let's say you have 10 title fields on the stage. They are using a font color of black with a font size of 10. You get everything set up just the way you want it and suddenly your client says, Gee whiz, wouldn't it be nice if the titles were blue? And maybe just a little bigger? Now you have to adjust each text field one at a time. With the code version you have set up a TextFormat and assigned it to each of the title fields. So all you have to do to change each one of those fields is change the appropriate TextFormat properties - once.

    titleFormat = new TextFormat();
    titleFormat.align = "left";
    titleFormat.font = "Arial";
    titleFormat.size = 10;
    titleFormat.color = 0xFF0000;

Isn't that a wee bit faster?

Another nice advantage to coding your assets is when you have to move them around. To make it really simple, I use these variables:

    private var xPos:int;
    private var yPos:int;

Let's say for some reason you need to suddenly shift the entire contact form 10 pixels to the right. Simply change the starting xPos from xPos = 10; to xPos = 20; and the whole thing moves. No more shifting every text field and component one at a time.

Another reason to code your assets is the additional options that you have available to you. You will find that you have much greater control over the appearance and actions of your assets with code. In the case of a text field, the autoSize property can be very handy when you are bringing in dynamic text of uncertain lengths. Let's take a look at an example.

    t1 = new TextField();
    t1.x = xPos;
    t1.y = yPos;
    t1.height = 40;
    t1.width = 490;
    t1.multiline = true;
    t1.wordWrap = true;
    t1.text = "This was brought in dynamically and you don't know the length of it in advance.";
    t1.setTextFormat(titleFormat);
    t1.autoSize = TextFieldAutoSize.LEFT;
    addChild(t1);

    yPos += t1.height + 10;

    t2 = new TextField();
    t2.x = xPos;
    t2.y = yPos;
    t2.height = 20;
    t2.width = 150;
    t2.text = "This is the text under your autoSize text field.";
    t2.setTextFormat(titleFormat);
    addChild(t2);

The t1 textfield will have it's text brought in dynamically from an XML file perhaps. No matter what length it is, the t1 text field will expand down, but you don't have to worry about the position of the t2 text field because it's y position is automatically adjusted depending on the height of t1. You can't do that on the stage.

And perhaps the biggest reason why I prefer to use this method, is that I have everything at my fingertips. No more clicking on individual fields to find out which one I called a particular instance name, or which one I used the color red on. From a single location I can survey the entire project, and change any aspect of it.

Now let's dig into the ContactForm.as and see what makes it tick.

The Nitty Gritty

Open up the ContactForm.as file and we'll run through it quickly before taking a closer look at it. What we are doing in a nutshell is 1) Collecting information, 2) Verifying that we have all the information required and, 3) Passing that information to a PHP script that will in turn email it to us.

package{
    import flash.display.*;
    import flash.text.*;
    import flash.events.*;
    import flash.net.*;
    import flash.utils.*;
    import fl.controls.Button;
    import fl.controls.TextArea;

    public class ContactForm extends Sprite{
		
    //Minimum width is 490, minimum height is 440
    /*To add an extra field is quite simple. I have placed an example in the code which collects a Company Name.
    The lines of code you need are commented out. Use them as an example of what you need to add and where you need to add it.
    The sample field is also picked up in the contactForm.php file. */
		
    // Create the variables, buttons, textarea, loader and textfields
		
    private var _loader:URLLoader = new URLLoader();
		
        //Variables to hold the incoming variables

        private var _subject:String;
        private var _toEmail:String;
        private var _toName:String;
	
        private var submit:Button;
        private var newCode:Button;
		
        //textArea for the message box
        private var ta:TextArea;
		
        //This stuff is for the Captcha feature
	
        private var randomChars:String = "";
	
        private var char1:Array = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
        private var char2:Array = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
        private var char3:Array = ["1", "2", "3", "4", "5", "6", "7", "8", "9"];
		
        //Text formats 
        private var charFormat:TextFormat;
        private var statusFormat:TextFormat;
        private var titleFormat:TextFormat;
        private var titleRFormat:TextFormat;
		
        //TextFields
        private var t1:TextField;
        private var t2:TextField;
        private var t3:TextField;
        private var t4:TextField;
        private var t5:TextField;
        private var t6:TextField;
        //Below is the extra textfield for the Company Name
        //private var t7:TextField;
	
        private var ip1:TextField;
        private var ip2:TextField;
        private var ip3:TextField;
        //Below is the extra input textfield for the Company Name
        //private var ip4:TextField;
		
        private var statusTxt:TextField;
        private var chars:TextField;
        private var charsIn:TextField;
		
        // variables for the x and y
	
        private var xPos:int;
        private var yPos:int;

We start by declaring the variables we will need in this script.

public function ContactForm(subject:String, toEmail:String, toName:String){
			
    //Transfer the incoming vars to the private ones
			
    _subject = subject;
    _toEmail = toEmail;
    _toName = toName;
			
    //Set up the items on the stage
			
    xPos = 0;
    yPos = 0;
			
    //Here we define the various text formats
    titleFormat = new TextFormat();
    titleFormat.align = "left";
    titleFormat.font = "Arial";
    titleFormat.size = 12;
    titleFormat.color = 0x000000;
			
    titleRFormat = new TextFormat();
    titleRFormat.align = "right";
    titleRFormat.font = "Arial";
    titleRFormat.size = 12;
    titleRFormat.color = 0x000000;
			
    charFormat = new TextFormat();
    charFormat.align = "center";
    charFormat.font = "Arial";
    charFormat.size = 14;
    charFormat.bold = true;
    charFormat.color = 0xff0000;
			
    statusFormat = new TextFormat();
    statusFormat.align = "center";
    statusFormat.font = "Arial";
    statusFormat.size = 12;
    statusFormat.bold = true;
    statusFormat.color = 0xff0000;
			
    //Now start building the form itself
			
    //Change the text in t1 to suit your site
    t1 = new TextField();
    t1.x = xPos;
    t1.y = yPos;
    t1.height = 40;
    t1.width = 490;
    t1.multiline = true;
    t1.wordWrap = true;
    t1.text = "Feel free to contact us with your comments, questions and suggestions by filling out the form below.";
    t1.setTextFormat(titleFormat);
    addChild(t1);
			
    xPos += 70;
    yPos += 60;
			
    t2 = new TextField();
    t2.x = xPos;
    t2.y = yPos;
    t2.height = 20;
    t2.width = 90;
    t2.text = "Your Name:";
    t2.setTextFormat(titleRFormat);
    addChild(t2);
			
    xPos += 95;
			
    ip1 = new TextField();
    ip1.x = xPos;
    ip1.y = yPos;
    ip1.height = 20;
    ip1.width = 255;
    ip1.border = true;
    ip1.type = "input";
    ip1.background = true;
    ip1.addEventListener(Event.CHANGE, txtBoxHandler);
    addChild(ip1);
			
    xPos -= 95;
    yPos += 30;
			
    //To add a new field use the commented section below as an example
	
    /*t7 = new TextField();
    t7.x = xPos;
    t7.y = yPos;
    t7.height = 20;
    t7.width = 90;
    t7.text = "Company Name:";
    t7.setTextFormat(titleRFormat);
    addChild(t7);
			
    xPos += 95;
		
    ip4 = new TextField();
    ip4.x = xPos;
    ip4.y = yPos;
    ip4.height = 20;
    ip4.width = 255;
    ip4.border = true;
    ip4.type = "input";
    ip4.background = true;
    ip4.addEventListener(Event.CHANGE, txtBoxHandler);
    addChild(ip4);
			
    xPos -= 95;
    yPos += 30;*/
		
    t3 = new TextField();
    t3.x = xPos;
    t3.y = yPos;
    t3.height = 20;
    t3.width = 90;
    t3.text = "Your Email:";
    t3.setTextFormat(titleRFormat);
    addChild(t3);
			
    xPos += 95;
			
    ip2 = new TextField();
    ip2.x = xPos;
    ip2.y = yPos;
    ip2.height = 20;
    ip2.width = 255;
    ip2.border = true;
    ip2.type = "input";
    ip2.background = true;
    ip2.addEventListener(Event.CHANGE, txtBoxHandler);
    addChild(ip2);
			
    xPos -= 95;
    yPos += 30;
			
    t4 = new TextField();
    t4.x = xPos;
    t4.y = yPos;
    t4.height = 20;
    t4.width = 90;
    t4.text = "Retype Email:";
    t4.setTextFormat(titleRFormat);
    addChild(t4);
			
    xPos += 95;
			
    ip3 = new TextField();
    ip3.x = xPos;
    ip3.y = yPos;
    ip3.height = 20;
    ip3.width = 255;
    ip3.border = true;
    ip3.type = "input";
    ip3.background = true;
    ip3.addEventListener(Event.CHANGE, txtBoxHandler);
    addChild(ip3);
			
    xPos -= 95;
    yPos += 30;
			
    t5 = new TextField();
    t5.x = xPos;
    t5.y = yPos;
    t5.height = 20;
    t5.width = 140;
    t5.text = "Questions & Comments:";
    t5.setTextFormat(titleRFormat);
    addChild(t5);
			
    yPos += 30;
			
    ta = new TextArea();
    ta.setSize(350, 150);
    ta.move(xPos, yPos);
    addChild(ta);
			
    xPos -= 70;
    yPos += 170;
			
    t6 = new TextField();
    t6.x = xPos;
    t6.y = yPos;
    t6.height = 20;
    t6.width = 260;
    t6.text = "Type the Security Code shown in the blank box:";
    t6.setTextFormat(titleFormat);
    addChild(t6);
			
    xPos += 270;
			
    chars = new TextField();
    chars.x = xPos;
    chars.y = yPos;
    chars.height = 20;
    chars.width = 60;
    chars.background = true;
    chars.backgroundColor = 0xddffff;
    chars.selectable = false;
    chars.setTextFormat(charFormat);
    addChild(chars);
			
    xPos += 70
			
    charsIn = new TextField();
    charsIn.x = xPos;
    charsIn.y = yPos;
    charsIn.height = 20;
    charsIn.width = 60;
    charsIn.border = true;
    charsIn.type = "input";
    charsIn.background = true;
    charsIn.addEventListener(Event.CHANGE, txtBoxHandler);
    addChild(charsIn);
			
    xPos += 70;
			
    newCode = new Button();
    newCode.x = xPos;
    newCode.y = yPos;
    newCode.width = 80;
    newCode.height = 22;
    newCode.label = "New Code";
    newCode.addEventListener(MouseEvent.CLICK, butHandler);
    addChild(newCode);

    xPos -= 205;
    yPos += 40;
			
    submit = new Button();
    submit.x = xPos;
    submit.y = yPos;
    submit.width = 80;
    submit.height = 22;
    submit.label = "Submit";
    submit.addEventListener(MouseEvent.CLICK, butHandler);
    addChild(submit);
			
    xPos -= 205;
    yPos += 30;
			
    statusTxt = new TextField();
    statusTxt.x = xPos;
    statusTxt.y = yPos;
    statusTxt.height = 20;
    statusTxt.width = 490;
    statusTxt.addEventListener(Event.CHANGE, txtBoxHandler);
    addChild(statusTxt);
			
    buildChars();
			
}

Then, from the constructor, we grab the parameters we have passed to the script and assign their values to the variables we have declared. Next we set up the physical parts, such as the textfields and buttons required to operate the script. The last thing we do here is call the buildChars function, which sets up our random Captcha code.

private function buildChars():void{
    var firstChar:String = char1[randNum(0, char1.length-1)];
    var secondChar:String = char3[randNum(0, char3.length-1)];
    var thirdChar:String = char1[randNum(0, char1.length-1)];
    var fourthChar:String = char2[randNum(0, char2.length-1)];
    var fifthChar:String = char2[randNum(0, char2.length-1)];
    randomChars = firstChar + secondChar + thirdChar + fourthChar + fifthChar;
    chars.text = randomChars;
    chars.setTextFormat(charFormat);
}

private function butHandler(e:MouseEvent):void {
    switch(e.currentTarget.label) {
        case "New Code":
            buildChars();
            break;
        case "Submit":
            if(charsIn.text != randomChars){
                statusTxt.text = "The security code you have entered is wrong.";
                statusTxt.setTextFormat(statusFormat);
                charsIn.backgroundColor = 0xFFFFCC;
                break;
            }
            if(ip1.text == ""){
                statusTxt.text = "Please put in your name.";
                statusTxt.setTextFormat(statusFormat);
                ip1.backgroundColor = 0xFFFFCC;
                break;
            }
            //Below is the check for the sample additional field
            /*if(ip4.text == ""){
                statusTxt.text = "Please put in your Company name.";
                statusTxt.setTextFormat(statusFormat);
                ip4.backgroundColor = 0xFFFFCC;
                break;
            }*/
            if(ip2.text == "" || ip2.text.indexOf("@") == -1 || ip2.text.indexOf(".") == -1){
                statusTxt.text = "Please put in a valid email address.";
                statusTxt.setTextFormat(statusFormat);
                ip2.backgroundColor = 0xFFFFCC;
                break;
            }
            if(ip2.text != ip3.text){
                statusTxt.text = "The email addresses do not match. Please retype.";
                statusTxt.setTextFormat(statusFormat);
                ip2.backgroundColor = 0xFFFFCC;
                ip3.backgroundColor = 0xFFFFCC;
                break;
            }
            if(ta.text == ""){
                statusTxt.text = "Please put in a Question or Comment.";
                statusTxt.setTextFormat(statusFormat);
                break;
            }
            //If everything is fine we send the data to the php script
            sendData();
    }
}

In the butHandler function we have 2 buttons to look after, so we use a switch statement to tell us which button has been pressed. In the case of a "New Code" being required for the Captcha feature, we simply call the buildChars function again to create a new random set of letters and numbers. If the "Submit" button has been pushed, we start the process of verifying the information that has been submitted. First we make sure that the Captcha code submitted is the same as the code that was randomly generated. If it is not, then we send a message to our status textfield and highlight the input field where the Captcha code is too be typed. Then we "break" to stop the processing of the form until the problem has been fixed. Next, we look at all the others textfields that we have decided are required, and make sure that something has been entered in them, and, in the case of the email, we can verify that it at least contains an "@" symbol and a ".". This will not ensure that it is a real email address, but at least we know that it is a validly constructed email address. Once all the hoops have been jumped through successfully, we call the sendData function.

private function sendData():void {
    //Create a URLVariable - If you add more fields simply include the new field in the variables. e.g. if you add a phone number - variables.phone = someTextfield.text;
    var variables:URLVariables = new URLVariables();
    variables.fullname = ip1.text;
    //Below is the sample extra field being sent to the php script
    //variables.company = ip4.text;
    variables.email = ip2.text;
    variables.comment = ta.text;
    variables.subject = _subject;
    variables.toEmail = _toEmail;
    variables.toName = _toName;
    variables.sendresponse = "Your message is being sent. Hang on..."
    //Here the sendresponse variable is put into the statusTxt field
    
    statusTxt.text = variables.sendresponse;
    statusTxt.setTextFormat(statusFormat);
		
    //Make a new URLRequest to send the variables to the php form
    var _request:URLRequest = new URLRequest("contactForm.php");
    _request.data = variables;
    _request.method = URLRequestMethod.POST;
     		
    //Set up the _loader. Using this allows for event listeners so that you can get a response back
    _loader = new URLLoader();
    _loader.dataFormat = URLLoaderDataFormat.TEXT;
    _loader.addEventListener( Event.COMPLETE, sendComplete );
    _loader.addEventListener( IOErrorEvent.IO_ERROR, sendIOError );
    _loader.load( _request );
}

In the sendData function we start by creating a URLVariable and assigning the information collected in the form to variables that will be sent to the PHP script. One of those variables is a message: variables.sendresponse = "Your message is being sent. Hang on...". This is displayed in the status textfield just to let the submitter know that something is going on in the background. Now we make a new URLRequest and assign the URLVariables to it's data property. The URLRequest's method property needs to be set to: URLRequestMethod.POST, so that we can deal with it properly in the PHP script. Next, we create a new URLLoader. Be sure and assign it's dataFormat property to ".TEXT". We have added two eventListeners to the URLLoader - Event.COMPLETE, sendComplete and IOErrorEvent.IO_ERROR, sendIOError . This will let us monitor the success or failure of the PHP script and allow us to pass a message back to the contact form. If everything goes according to plan, the sendComplete function will fire and let the submitter know that everything has worked beautifully. If there is a problem somewhere along the way, the sendIOError function will fire and let the submitter know that their message was not sent successfully.

private function sendComplete( e:Event ):void {
    statusTxt.text = "Submission successful! Thank you.";
    statusTxt.setTextFormat(statusFormat);
    clearForm();
     		
    //This little timer clears the message after 3 seconds
    var tmr:Timer = new Timer( 3000, 1 );
    tmr.addEventListener( TimerEvent.TIMER, clearMessage );
    tmr.start();
}
		
//If there was an error sending the form
private function sendIOError( e:IOErrorEvent ):void {
    statusTxt.text = "Error sending e-mail";
    statusTxt.setTextFormat(statusFormat);
    var tmr:Timer = new Timer( 5000, 1 );
    tmr.addEventListener( TimerEvent.TIMER, clearMessage );
    tmr.start();
}

private function clearForm( ):void {
    ip1.text = "";
    ip2.text = "";
    ip3.text = "";
    //ip4.text = "";
    ta.text = "";
    charsIn.text = "";
    buildChars();
}
		
//This is the function the timer sets up
private function clearMessage( e:Event ):void {
    statusTxt.text = "";
}

//This returns the background color of the textfield to white once the user types something in that field
private function txtBoxHandler(e:Event):void{
    e.target.backgroundColor = 0xFFFFFF;
    if(e.target == ip2){
        ip3.backgroundColor = 0xFFFFFF;
        ip3.text = "";
    }
    statusTxt.text = "";
}
		
//This function sets up the randomness for the captcha
private function randNum(minVal:Number, maxVal:Number):Number{
    var randNumb = minVal + Math.floor(Math.random() * (maxVal + 1 - minVal));
    randNumb = Math.round(randNumb / .01);
    randNumb = randNumb/100;
    return randNumb;
}

The contact form as it is now is very simple. For your project you may require other information to be collected and passed on. Let's take a look and see how to do that.

Page 2