These notes cover how to create forms and use them to email data to a specified email address. They also describe using jQuery and plugins to operate on the form, including validation.
So far in our web pages, we've just been giving the user information. Now, we want to get some from the user. We'll do this by having them fill out a form, just like the ones you did on the first day of cs110 lecture (and whenever you buy something online). Here are some examples; look at the source code to see how they are done.
You can figure out a lot just by looking at the code and making reasonable guesses, but we'll walk through the details in lecture to be sure.
The main tag is the FORM
tag. Like TABLE, UL and a few others, the
FORM tag is just a container; it doesn't do much by
itself.
Note that, for reasons that we'll discuss later, it is often useful
to name each form. The form above is named my_form,
but that's just an example. You can name a form pretty much anything,
though you should stick to the same character set as for JavaScript
variables (letters, digits, and underscores). Don't worry about the
(empty) action attribute; we'll get to that soon enough, when
we talk about CGI scripts.
The body of the form can contain one or more inputs, (in addition
to any other HTML, JavaScript code, text, and images). Many of these
use the INPUT tag, but there are tags called
SELECT and TEXTAREA that also provide input.
We will also name all of our inputs. This is useful when the form data is processed on a server, because only named data is submitted. For example, we will later see how to the form data can be emailed somewhere, but only named fields will be in the email.
The INPUT tags have several different types, which you
specify using the TYPE attribute. The types include at least
the following:
TEXT: allows the user to type in a word
or phrase
PASSWORD: allows the user to type in a word or
phrase, but its value isn't echoed, so no one can look
over their shoulder and see it.
RADIO: allows the user to select from mutually
exclusive options, like station buttons on a car radio.
CHECKBOX: allows the user to say “yes”
or “no” to a
single thing. You can also have a group of checkboxes on
a particular topic, so that multiple selections can be
made by checking more than one box.
HIDDEN: like a text type, but invisible. You as author
of the form can specify the VALUE as an attribute. This
input's name and value are sent along with the other inputs.
Examples:
You can see more examples by looking at the source for the example form. A small warning: if a value isn't selected from a radio button group or a checkbox group, no value is sent to the server, so it won't be reflected in any output, so don't be concerned if you don't see one.
Each radio button input is part of a group of mutually exclusive buttons: if you click on one button, it is selected and whatever used to be selected is de-selected. This is more intuitive to try than it is to describe:
The crucial question is, how does the browser know that when you click on the first “apple,” it should deselect “banana” and “orange,” but not “Apple,” “Google,” or “Microsoft”? The browser is not able to get any clues from the layout of your buttons: you might just as easily have arranged the table horizontally instead of vertically. (Look at the source to see how ugly that might be.)
The rule is that the browser deselects all other inputs that have the same name as the input you selected. Thus, the name of a radio button is crucial: it defines the group of mutually exclusive options.
Although checkboxes are not mutually exclusive the way that radio buttons are, they also form groups based on the name of the input. This is reflected in the email that you are sent: checked boxes are grouped together as one set of responses.
To specify a menu, from which the user can choose only one option,
you use the SELECT
tag inside the form. You specify the NAME of the input in
the SELECT tag, and each menu item is specified using the
OPTION
tag. Here's an example:
(The closing </option> tag is optional, like a closing
</p> tag or </li> tag.)
The email message will display whichever option the person chose.
If you want to allow your user to type in a long response, you
should define a textarea
inside your form. This tag has attributes called ROWS and
COLS that let you specify the size of the area.
<textarea name="thoughts" rows="3" cols="40"> A chicken is an egg's way of making another egg </textarea>
The default value is the region between the beginning and ending tag. Typicaly, you want the default value to be empty, so put the tags right next to each other, as in this example here:
Don't let even a single space creep in, or the initial value will be a string of one space, and not the empty string. That will affect your validation code.
Here are some more INPUT tag types. There's no input from
them, but they otherwise share the common syntax for the
INPUT tag. You need not name these elements, since you
typically don't need to send the value to the CGI script.
SUBMIT: creates a button that allows the form data to
be sent. The VALUE attribute is used for the label on the
button that the user sees. The TYPE attribute is what
makes it work:
RESET: creates a button that allows the user to clear
the form, resetting it to its initial state. Again,
the type attribute makes it work, and the value is what
the user sees. There is no need for a name attribute.
BUTTON: creates a button that can have Event
Handlers that can do interesting things. Buttons are specified
using the INPUT tag because the user is giving input to
the browser. Their main purpose is to have an onClick
attribute that
can do something. We'll see an example in the next section.
<input type="button" value="what time is it?"
onClick="alert((new Date()).toTimeString());">
For clarity and accessibility, it's a good idea to structure a form: grouping related inputs and labeling each input. At the top of these notes, we saw an example-using-fieldset.html.
We'll need to learn the following HTML tags:
fieldset
a wrapper around a set of fields.
legend
the mandatory label that describes a set of fields. The
legend element must be the first element of the
fieldset.
label
element describes a particular form input (even a radio button or
checkbox).
It's also useful to know about the accesskey
attribute,
which provides a shortcut to put a particular input in focus (to type
a value) or to choose a value (as with a radio button or checkbox). This is very convenient for touch-typists and those who have trouble with a mouse.
Using a modern Firefox, Chrome or Safari on a Mac, hold down the control and option keys and type the access key to use the feature. Try it on our example-using-fieldset.html, where the accesskey for each input is given in parens in the label.
In our lecture on Events and Rollovers, we introduced the idea of manipulating elements of the document using JavaScript and the Document Object Model (DOM). At the top of these notes, you may have tried the example-using-fieldset-and-JS.html, which allows each fieldset to be made displayed or not by clicking on the legend. The JavaScript code is pretty simple, making use of a boolean variable (to keep track of whether the fieldset is displayed or not) and the DOM to find the relevant element and modify its display property.
Here are the details of the code:
#contact_info, #order_info, #credit_card_info {
display: none;
}
true or false.
Given the CSS setting above, the variables should be initialized to
false.
<script type="text/JavaScript"> var contact_info_displayed = false; var order_info_displayed = false; var credit_card_info_displayed = false; </script>
...
var elt=document.getElementById('contact_info');
if( contact_info_displayed ) {
elt.style.display='none';
contact_info_displayed = false;
} else {
elt.style.display='block';
contact_info_displayed = true;
}
All three of these event handlers are nearly the same, which is very repetitive. If we changed how we want to do things, we'd have to update all three of them in exactly the same way. In an upcoming lecture, we'll learn how to eliminate this repetitive coding, to improve the brevity and maintainability of the code.
Another important reason for naming inputs is so that we can refer to them from JavaScript code. The general scheme is that an expression like the following gives the value of a text input. You can essentially treat this kind of expression like you would a variable: it has a value and you can store new values into it.
window.document.formname.inputname.value
The window. part is optional in all browsers that we've
experimented with. However, it is standard in various web references, so
we consider it to be (at least) a good idea. However, we will often, for
brevity, omit it in our examples, and we will not consider it incorrect
for you to do so. Just keep the window. part in the back of
your mind.
Here are some examples of processing form data.
To understand the code of the quiz, you have to know that for radio
buttons and checkboxes, you can find out whether the input is checked
by looking at the value of the following expression. It is a boolean
value: true if the input is selected and
false, otherwise.
window.document.formname.inputname.checked
Misconceptions often arise with JavaScript interacting with forms. This section is intended to try to clarify the interaction. You might consider coming back to this section when you're working with forms and JavaScript, in case you've run into one of these.
Form inputs are kinda like JavaScript variables, but not exactly. Let's talk about these aspects of them:
Declaration: With JavaScript variables, you need to make sure
they exist before you use them. That's called declaring
them. Similarly, the form input needs to exist before you can use
it. In order to do that, your page needs to have the proper HTML for
the form. That's it. There's no need to declare
the form
input from JavaScript.
Initialization With JavaScript variables, you need to give
them a value before you can use the value, but form inputs always have
an initial value, either the one you give in the HTML using
the value attribute or the empty string if you omit
the value attribute. For JavaScript variables, consider
the following example, which illustrates both declaration and
initialization:
Getting: To use a JavaScript variable (get its value), you
just have to give its name, say on the right-hand side of an assignment
or as the argument to a function. The value of a form input can be used
in exactly the same way. The difference is that a form input has a
long, complicated reference expression
like: document.form_name.input_name.value. Also, you have
to remember that a form input's value is always a string, so if
you're doing something numerical, remember to
use parseInt() or parseFloat().
Setting: To set (assign) a JavaScript variable, you just have to give its name on the left-hand side of an assignment. The value of a form input can be set in exactly the same way; it just has that long, complicated reference expression.
Here is an example that illustrates all these ideas. Notice the use of
the Gather, Compute, Report pattern in the onClick event
handler. Notice that the form input's value is initialized to
be 1
; we could initialize it to anything we want.
Here is a graphic illustrating what's happening in the preceding code.
The form lives in HTML land
(in a tree
, actually), and the
JavaScript lives in its own land. The green arrow is the gather
step that copies the value from the form input into the JavaScript
variable. The red arrow is the report
step that copies the new
value in the JavaScript variable back into the form input.
Form inputs have names, just like JavaScript variables, and
they can have the same names as JavaScript variables, but
that is as likely to confuse you as to help you. Consider
the following variant of the previous example, where both the form
input and the JavaScript variable are named num:
Is that confusing? Having both an input named num and a
JavaScript variable named num? The reason that it's even
possible for them to co-exist while having the same name is that they
live in different worlds: the form inputs lives in the document,
in HTML land
, while the JavaScript variable lives
in JavaScript Land
. In one sense, it's useful for them to have
the same name, since their role in the web page is similar. On the
other hand, they are different things. And they'll always look
different in the JavaScript code because of the long, complicated
reference expression that the form input has.
If you find this dual-naming confusing, we recommend you devise a
naming scheme to help. That way, things will have similar but
non-identical names, related by the scheme. For example, we could decide
that anything that is a field
in a form will have a name that ends
in Field. The related JavaScript variable will omit
the Field
suffix. Here's how it might look:
A very important reason that we discuss processing form data using JavaScript is form validation, which is using JavaScript to check if a form has been filled out correctly. Form validation could be used to ensure that someone hasn't overlooked a text input, menu or radio button group, and can check that, for example, the zip code is 5 digits (or 9) and that a telephone number is 10 digits, and that an email address looks like an email address.
The form validation JavaScript can actually cancel the submission of the form, so that the data never leaves browser. The reason we validate forms is twofold: to give the user immediate feedback that they've missed something, instead of waiting for the server to respond, and to protect the server from having to handle all those invalid forms. Of course, a determined nefarious person can simply disable our form validation JavaScript and hammer our server with invalid forms, but that's rare. The vast majority of invalid forms are just human error.
Increasingly, simple form validation is not done by custom-written JavaScript, but is instead done by libraries like jQuery. Indeed, there is a jQuery plug-in by Jörn Zaefferer called validation that does a good job and is well described in our book, JavaScript & jQuery: The Missing Manual, pages 278-300. Please read that, and the on-line documentation linked above, for full details. The following subset is just to get you started and whet your appetite.
The basic steps are:
class="required" to each required input
.validate() method on the form; this sets
up a onSubmit event handler that checks the validity of
the form before it's submitted.
Here is a minimal, validated form:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Validated Form</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<script>
$(document).ready(function () {
$('form').validate();
});
</script>
</head>
<body>
<form method="post" action="/cgi-bin/dump.cgi">
<p>Please enter your comments:<br>
<textarea name="comments" class="required"></textarea>
<p>
<input type="submit" value="Submit form">
</form>
</body>
</html>
Note that the error message for a radio button or checkbox group is put after the first element, which looks awful. Our book has a solution, which is a option that changes the placement of error messages for certain input types. You could write even more specialized code for a particular form.
One tricky, poorly documented, thing to know:
value="" attribute, so that, if that's the choice, the
input has a value of the empty string.
We've applied these steps to this validated example form. Try it and view the source to learn more.
What happens when the form is submitted is determined by the
CGI (Common Gateway Interface) protocol, which sets the rules by which
form data is sent to servers and processed by programs, usually called CGI
scripts. A CGI script can do anything it wants: it can send email,
interact with a database, create a document, contact other users, or
whatever. The electronic commerce web sites that you know, like
amazon.com, all work via CGI scripts.
cgi-bin directory.
eform.cgi script, which we'll see below.
(The eform.cgi script is home-grown and available only on
Puma, but something similar exists on many servers.)
A form can specify what script is to process the form data
(via the ACTION attribute), and how it should get
the data (via the METHOD attribute). The example that we
will use in this class is a CGI script that emails the data to some
recipient. When you want the data to be sent to someone with the help
of Puma (acting as a mail server ) you can write:
<form name = "my_data"
method="post"
action="/cgi-bin/eform.cgi">
</form>
The value of the ACTION attribute is a CGI script that
will package up all the form information and email it someplace. There
are two methods, GET and POST. The GET method
collects all the form inputs in the URL. (You've probably seen this sort
of link from sites like Google
Maps .) On the other hand, the POST method collects all the form
inputs into something called “standard input.” Which
method you use is determined by the author of the script. We will
always use the POST method in this class.
The first CGI script we'll consider is not particularly useful by
itself, but is very helpful for debugging forms, as we saw with the
examples at the beginning of the notes. It just echoes the data back
to the browser, in a nicely formatted way. It also tells you a few
other things it knows, such as the IP address you're browsing from and
the time you submitted the form. The script is called
dump.cgi and it lives in /cgi-bin/dump.cgi .
Since CGI scripts can do such different things, each one can have its
own behavior and rules. The one we will use in this course is called
eform.cgi and it is designed to email the information on the
form to someone. It can do this in one of two ways:
You already know how do to the first case. There are two steps:
FORM tag look like this:
<form name="mailform"
method="post"
action="/cgi-bin/eform.cgi">
</form>
<input type="hidden"
name="_recipient"
value="me@wellesley.edu">
(The required input _recipient begins with an
underscore so it is unlikely to conflict with a name
you would like to use for something else in your page;
the script will complain if that input is missing.) That's
all. The downside of this simple approach is that the resulting email
message isn't pretty. It is unformatted, a long string of form contents.
To have a formatted email message is an optional advanced technique for the interested reader. Follow the link to find out how.
To avoid abuse by spammers, eform.cgi requires that
the form be on the server. If your form is not on the
server, you will get an error message saying
Wrong Server
This error commonly occurs when you are testing your form on your local
desktop machine, so that the URL for the form is file:///....
Sorry, but that won't work.
http://cs.wellesley.edu/cgi-bin/eform.cgi
_recipient.
Note that the eform.cgi script lives on the CS server. If
you decide to use it in your projects (which you're welcome to do), you
will eventually have to face the problem of what to do when your site is
delivered to your client. You are welcome to copy our eform.cgi code to
the web hosting service, but they may not support scripts (just passive
web pages). If that's the case, you'll have to find some kind of
equivalent that they do support (they typically provide a script
equivalent to eform.cgi). You can search their support
pages or ask their tech support for more info.
You can still use eform.cgi in your project without
necessarily having solved this problem of an equivalent on the client's
web hosting service. You might be able to solve it later, or omit that
functionality if the web hosting service isn't up to the task.
In this lecture, we learned
window.document.formname.inputname.value (for
textual data) and
window.document.formname.inputname.checked (for radio
buttons or checkboxes, which are either checked or not).
ACTION attribute of the
FORM tag.
eform.cgi, which emails the form data to a recipient.
The recipient is typically defined with a hidden input in the form.
You can also use the dump.cgi script to help debug your
forms.
eform.cgi script is to format the email
Optional reading: Meyers Ch. 14-15, Thau Chapter 7.