Back

Working with Forms

So far, our HTML journey has been eventful to say the least.  We've been exposed to the elements that make presenting a message on the web possible and along the way we've learned some of the basic rules of style that make your web pages "good" - whatever that means!  Of course, from a very real viewpoint, our journey has occurred on a one way street.  We've been designing pages to deliver our message to our target audience but the information path has been one-directional - FROM us TO them.  This tutorial will make our sites truly interactive.

The mailto: Protocol

To begin, we've always had the ability to get information from our users by using the mailto: protocol as the href attribute inside an <a> element.  We could set up a normal hyperlink on our pages that points to a valid e-mail address.  When a user clicks on the link, their default e-mail client is started with the e-mail address we've specified as the "To" part of the message.  Here's an example:

<html>
<head>
<title>Contact Me</title>
</head>
<body>
<a href="mailto:td4729@hotmail.com">Contact Me</a>
</body>
</html>

Here's how it looks:

Contact Me

This is convenient in that it allows the user to use the e-mail program that, presumably, they are familiar with.  The down side, of course, is that the user can send along anything they want!  Often, this isn't the best solution as you will be most interested in certain types of information.  A less obvious caveat is that there may not be a default mail program configured on the user's machine rendering our link useless!

A better solution would be to devise a set of questions with input fields so that the user only sends information that is useful to you.  That's exactly what the <form> element does.  The <form> element allows you to specify different types of input controls using the <input> element and specifying a type attribute.

Working with Forms

Before beginning with the <form> element, you should be aware that when using forms, some server-side intervention is necessary.  Usually, you will send the contents of the form to a script located on your server for processing.  These scripts, called Common Gateway Interface (CGI) scripts are usually written in C or Perl and they reside in a folder on the server that can execute scripts - usually the cgi-bin.  You can also send the results of a form to an Active Server or Java Server Page for processing but these are also technologies that involve a server (hence the name!).  Since this tutorial deals only with client-side technologies, we'll work around this fact by sending our form results to an e-mail address.  That way, we won't have to write any CGI scripts, ASPs, or JSPs!

Let's begin by looking at the attributes of the <form> element:

Attribute Description
action Specifies the URL  to send the form results to for processing.
method Specifies how to send the results to the URL specified in the action attribute.  Possible values are GET and POST.  GET appends the form information to the URL specified in the action attribute and is the default.  POST sends the results in key-value pairs to the action URL.
enctype Specifies the mime-type of the data being sent.  Any valid mime-type is allowed. For a detailed list of valid mime-types see: http://www.isi.edu/in-notes/iana/assignments/media-types/media-types
target frame name

Don't be alarmed (just yet anyway!) as we will specify the following attributes for our forms as follows:

Attribute Description
action "mailto:yourEmailAddress"
method POST
enctype text/plain
target blank

This will allow us to capture the results of any form inside an e-mail message.  The downside (again) is that our forms will only work for users who have a default e-mail client configured.  At least we'll be able to practice writing forms.  Check with your web hosting service for any pre-written scripts to handle forms.  Most generally have a few that they support with instructions for using them.

Examining the attributes of the <input> element isn't as easy.  In fact, the <input> element might be the most versatile element in the HTML tag library!  You must specify a type attribute for the <input> element but, after doing so, the attributes that can follow are different for each type.  Following is a brief synopsis of the variants of the <input> element:

Type Attribute Additional Attributes Description
text or password name
value
size
maxlength
disabled
readonly
Name specifies the name of the control. Value specifies a default value. Size specifies the size of the field. Maxlength specifies the maximum input length. Disabled creates an un-editable field. Readonly disallows user entry.
hidden name
value
Name specifies the name of the control. Value specifies the value to pass to the server.
checkbox name
value
checked
disabled
Name specifies the name of the control. Value specifies the value to send to the server if checked. Checked pre-selects the field. Disabled disables the field.
radio name
value
checked
disabled
Name specifies the name of an entire group of radio buttons.  All buttons can have the same name because their values must be mutually exclusive.  Checked pre-selects a radio button.  Disabled disables the buttons.
file name
value
accept
disabled
Name specifies the name of the control. Value specifies the default value (presumably a file).  Accept specifies a set of accpetable mime types. Disabled disables the control.
image src
alt
align
usemap
disabled
Src, alt, align, and usemap function identically as in the <img> element. Disabled disables the control.  The coordinates of the click event are passed to the server.
button value
onclick
disabled
Value specifies the text of the button.  Onclick is set equal to the name of the script to execute when the button is clicked.  Disabled disables the button
submit value
disabled
Value specifies the text of the button.  When clicked, the form data will be sent to the URL specified in the forms action attribute. Disabled disables the button.
reset value
disabled
Reset resets all of the fields in the form to their default values.  Disabled disables the button.

Additionally, you can use the following attributes with any <input> element:

Attribute Description
accesskey Specifies a shortcut key the user can press to force the focus to the control.
tabindex Specifies the position in the tab order of the page.
id Specifies an identifier for the element

There are a few other elements that can be used with forms besides the <input> element:

Element Attributes Description
<select> name
size
multiple
disabled
accesskey
tabindex
Name, disabled, accesskey, and tabindex all function as above.  Size specifies how many <option> elements will be visible.  Multiple determines if more than a single <option> element can be selected.  If size is set to 1 and multiple is omitted, a drop-down box is created.
<option> value
selected
disabled
label
These attributes function as above.  <option> is a container element.  You specify the the text to display between <option> and </option> tags.  If you specify a label, it will be used in place of the text.
<textarea> name
rows
cols
disabled
readonly
accesskey
tabindex
All of the attributes function as above except for rows and cols.  Rows specifies the number of rows to display (height) while cols specifies the number of columns to display (width).
<button> type
name
value
disabled
accesskey
tabindex
You may specify submit, reset, or button for the type attribute and the button will behave as if you used the type attribute of the <input> element.  Name, disabled, accesskey, and tabindex function as above.  Value specifies the value to send to the server.  <button> is a container element.  If you specify text between the <button> and </button> tags, the text will be the label.  If an <img> element is specified, the image will be used as the button.
<label> for
accesskey
Accesskey works as above.  For is set equal to the id attribute for any field.  In essence, you create a label for a field.
<optgroup> label
disabled
Label specifies the label of the group.  Disabled functions as above.  Not currently supported by either major browser.
<fieldset> none Groups related form input fields.  Not currently supported by either major browser.
<legend> accesskey
align
Names a group of related form fields.  Align specifies where the text of the container appears relative to the form fields.  Not currently supported by either major browser.

Wow!  That's a lot of stuff!  And rightfully so - forms give you the ability to do so many things that they should be a powerful mechanism.  Let's see what an example of some common form fields might look like:

<html>
<head>
<title>Forms example</title>
</head>
<body>
<form method="POST" action="mailto:youremailaddress" enctype="text/plain">
<p>Employment Survey</p>
<p>Name: <input type="text" name="name" size="20"></p>
<p>e-Mail address: <input type="text" name="email" size="20"></p>
<p>Password: <input type="password" name="pwd" size="20"></p>
<p>Sex: <input type="radio" value="male" checked name="sex">Male <input type="radio" name="sex" value="female">Female</p>
<p>Department (check all that apply): <input type="checkbox" name="web" value="on">
Web <input type="checkbox" name="applications" value="ON"> Applications <input type="checkbox" name="wireless" value="ON">Wireless<input type="checkbox" name="hr" value="ON">Human Resources</p>
<p>Choose an SAT word <select size="1" name="SATword">
<option>Apathetic</option>
<option>Enraptured</option>
<option>Loquacious</option>
<option>Prevarication</option>
</select></p>
<p>Send your resume: <input type="file" name="resume" size="20"></p>
<p>Comments: <textarea rows="5" name="comments" cols="40"></textarea></p>
<p><input type="submit" value="Send Now" name="submit"><input type="reset" value="Start Over" name="reset"></p>
</form>
</body>
</html>

And here's what it looks like:

Employment Survey

Name:

e-Mail address:

Password:

Sex: Male Female

Department (check all that apply): Web Applications Wireless Human Resources

Choose an SAT word

Send your resume:

Comments:

If we were to fill this form out and click the Send Now button we'd get the results back in an e-mail message.  It would look like this:

name= 
email= 
pwd= sex=male 
SATword=Apathetic 
resume=C:\resume.txt 
comments= 
submit=Send Now

You may have noticed that the resume field isn't what you'd expect in the results.  That's because it requires a different mime type (multipart/formdata).  The file input type requires action on the server's part  to function properly and is only included here to demonstrate its behavior.  I hope you are beginning to see the power of forms.  The above form is trivial in that it serves no real purpose.  But you can easily get feedback from your users using the forms mechanism.  Let's try a more useful example.

A Contact Form

We've already decided that getting input from users is a good thing when designing a web site.  If you engage your users and react to their concerns, they will generally become repeat visitors - something every site designer desires.  With that in mind, let's create a Feedback form and try to make it more presentable than the above example.  Finally, we'll add some basic JavaScript to validate our form before it is sent along to us.

We'll start our process by asking ourselves what kind of information we'd like to receive from our users.  For our purposes, let's keep it simple and ask the user for basic information like name, address, phone and e-mail address.  We'll also provide the user with a mechanism to pass along questions or comments.  In this example, we'll use a table to present our form so that we have greater control over the alignment of labels and controls.  Here is the code which we'll analyze a little later:

<html>
<head>
<title>Contact Us</title>
</head>
<body>
<form method="POST" action="td4729@hotmail.com" enctype="text/plain">
<p>Contact Us</p>
<table border="0" cellpadding="4" cellspacing="0" width="698">
<tr>
<td width="152" align="right">Your Name</td>
<td width="526"><input type="text" name="name" size="56" tabindex="1"></td>
</tr>
<tr>
<td width="152" align="right">Your Address</td>
<td width="526"><input type="text" name="address" size="56" tabindex="2"></td>
</tr>
<tr>
<td width="152" align="right">Your Phone Number</td>
<td width="526"><input type="text" name="phone" size="56" tabindex="3"></td>
</tr>
<tr>
<td width="152" align="right">Your E-Mail Address</td>
<td width="526"><input type="text" name="email" size="56" tabindex="4"></td>
</tr>
<tr>
<td width="152" valign="top" align="right">Comments</td>
<td width="526"><textarea rows="3" name="comments" cols="48" tabindex="5"></textarea></td>
</tr>
<tr>
<td width="152" valign="top" align="right"></td>
<td width="526"><input type="submit" value="Send Now" name="send" tabindex="6"><input type="reset" value="Start Over" name="reset" tabindex="7"></td>
</tr>
</table>
</form>
</body>
</html>

We are taking advantage of the fact that table cells can hold any html element.  This gives us the ability to position form elements inside our table so that they are aligned properly.  Notice also that the size attributes are all set to the same number.  This makes the form interface not only cleaner but also more professional looking.  Finally, notice that the border attribute of the table is set to 0 and cellpadding is increased to separate the elements from one another.  I've also included a tabindex property for each element.  These really aren't necessary in this case as, by default, the browser will move to the next element when the tab key is pressed.  Here is what our form looks like:

Contact Us

Your Name
Your Address
Your Phone Number
Your E-Mail Address
Comments

That wasn't too difficult.  We are still limited by the mailto: protocol so our form won't work on a computer without a mail program configured.  At some point, we'd like to get a hold of a server-side script to remedy that situation but, for now, we can at least test our form.

The second limitation to our form is the fact that the user can input anything at all into any of the text boxes.  We have no way of checking, for example, whether or not a valid e-mail address is actually entered into the e-mail edit box.  This process of checking the forms fields is called validation.  There are a number of ways to do validation but, for today, we'll introduce a client-side mechanism - JavaScript.

Although we haven't really covered JavaScript, let's go ahead and add a simple script to this form.  For this particular problem, we'd like to get our validation done after the user clicks the Send Now button but before the form is actually submitted.  The action of clicking the button is called an event in programming because it is user driven.  What we'd like to do is capture the click event and handle it - hence the name event-handler.

For this problem, there are two distinct events: the clicking of the button and the submission of the form.  Since clicking on the Send Now button automatically calls the submission action, let's put some JavaScript into the submission event.  Don't worry about the actual syntax of the script just yet.  Rather, focus on what we are trying to accomplish.

OK, let's re-state our problem.  First, we'd like to only receive completed forms.  An empty or incomplete form is useless to us.  So we should at least check for the presence of content in each of the fields.  Second, we'd like to insure that we get a valid e-mail address in the e-mail field.  Finally, we'd like to give the user a chance to complete the form if something is missing.  We'll write our script inside the <head> element.  Add this code to your <head> element:

<SCRIPT LANGUAGE = "JavaScript">
<!-- Hide from older browsers

// Check for email address: look for [@] and [.] 

function isEmail(elm) {
if (elm.value.indexOf("@") + "" != "-1" &&
elm.value.indexOf(".") + "" != "-1" &&
elm.value != "") 
return true;
else return false;
}

// Check for null and for empty

function isFilled(elm) {
if (elm.value == "" ||
elm.value == null) 
return false;
else return true;
}

function isReady(form) {

// is name element filled?

if (isFilled(form.name) == false) {
alert("Please enter your name.");
form.name.focus();
return false;
}

// is address element filled?

if (isFilled(form.address) == false) {
alert("Please enter your address.");
form.address.focus();
return false;
}

// is phone element filled?

if (isFilled(form.phone) == false) {
alert("Please enter your phone number.");
form.phone.focus();
return false;
}

// is address element a real email address?

if (isEmail(form.email) == false) { 
alert("Please enter your email address.");
form.email.focus();
return false;
}

// is comments element filled?

if (isFilled(form.comments) == false) {
alert("Please enter some comments.");
form.comments.focus();
return false;
}

return true;
}

//end hide-->
</SCRIPT>

We have two generic functions.  The isEmail function checks a form element and determines whether or not the element contains the @ and . as part of its text.  Obviously, this isn't the best solution but, at the very least, we know that all valid e-mail addresses contain the @ and . characters.  The isFilled element simply checks whether or not an element contains any text at all.

The third function is the one that actually does all of the work.  The isReady function checks each element in the form by calling either isFilled or isEmail depending on the content of the element.  If the element in question doesn't pass the content test, an alert message is posted to the screen.  When the user dismisses the alert box, the control that caused the error receives the focus (the cursor is placed in the control for quick editing).

OK, so we've designed our event handler, all we need to do now is capture the event.  Fortunately, that's the easy part.  We've already decided to capture the submit event for the form.  Change the <form> element of your page so that it looks like this:

<form name = "mailform" onSubmit = "return isReady(this)" method="post" enctype="text/plain" action = "mailto:tduffy@optonline.net">

That was relatively simple.  We added the onSubmit event to the element.  What we've done is to tell the form to call the isReady() function and pass itself to the function (that's what "this" means).  The isReady function will either return true or false.  If true is returned, the form has been validated and will be submitted.  If false is returned, an alert box will indicate the error(s) and allow the user to fix them and try to submit the form again.  And that's all ther is to it.  Set up your form, create an event handler, capture the event, and handle it.  Cool!

You'll find a simple Contact Form on the source code page.  Feel free to "borrow" the code and modify it to suit your needs.