Revised, Fall 2013, by Scott.
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.
Don't worry about the method
attribute and
(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. Here are some of the types:
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.
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.
email
: like a text type, but should look like an
email address. This is a new type added with HTML5.
date
: for entering dates. This is a new type added
with HTML5.
Examples:
You can see more examples by looking at the source for the example form. If you submit this form, the data is "echoed" back to you.
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.) Any option
can have a separate "value" attribute; if none is specified, the value is
the option itself.
Specifying a non-option
as the first item in the list helps to
tell whether someone has actually made a choice or just overlooked this
menu. Making the non-option have a value of the empty string helps with
validation.
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. Typically, 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 any code that cares about the default or original value, such as certain kinds of validation
Here are some more INPUT
tag types. The user doesn't use
them to enter any data, 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 event handler attached
to them. HTML5 also has a button
tag that can be used
similarly.
Here's an example of such a button. See below for the JS code to add the behavior.
function alert_time() { var dobj = new Date(); var timestr = dobj.toTimeString(); alert(timestr); } $("#showtime").click(alert_time);
In our lecture on Events and Rollovers, we introduced the idea of manipulating elements of the document using JavaScript. Here, we will introduce a form that is mostly hidden, but can be revealed when desired.
First, try the example-form-toggled.html to see the desired behavior.
Here are the details of the code:
form_contents
.
toggle_button
on
the button
element that preceded
#form_contents
.
$('#form_contents').hide();
formState
and gave it a value
of "hidden"
(a string).
var formState = "hidden";
function toggleForm() { if( formState == "hidden" ) { $("#form_contents").show(); formState = "shown"; $("#toggle_button").attr("value","hide form"); } else { $("#form_contents").hide(); formState = "hidden"; $("#toggle_button").attr("value","show form"); } }
$("#toggle_button").click(toggleForm);
If we wanted to do this to multiple parts of a long, complex form (think FAFSA or IRS form 1040), we could certainly do so with some copy/paste/edit of the code, but that doesn't scale up well. Look in the additional material, below, for the code to do this.
jQuery makes retrieving form data pretty easy. We need to learn a new method, the val method. As you'd expect, it's used like this:
$(selector).val();
The main thing is that if the selector specifies a form input,
the jQuery val
method gives us the value of that input.
Here is an form with several different kinds of inputs:
Here's the actual form, so you can change the values of inputs:
Now, let's look at how to get the values of an input. The text inputs,
the select
menu and the textarea
are all easy
because there's just one element and one value to worry about. The
jQuery selector can either be the ID of the element or a syntax using
the TYPE and NAME of the input.
For example, the following expression evaluates to the pet's name:
$("#petname").val()
Here is an equivalent, using the name of the element:
$("[name=petname]").val()
Here are some live examples:
Here are some examples of processing form data.
Soon, we'll talk about submitting the form data to a server for more elaborate processing, but before we do that, we should discuss validation. What is form validation? Essentially, it means checking to see that the form has been filled out correctly (as far as we can tell).
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.
Form validation 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.
Obviously, the browser can't tell whether you entered your correct
phone number, but it can check that you typed the right number of digits
(and only digits). Similarly, it can't check that your spelled your
name correctly (and whether your name really is Mickey Mouse
),
but it can check that you didn't leave that input blank.
With HTML5 and modern web browsers, form validation has gotten a lot easier. In the past, web developers would write JavaScript code that would look at the values in the form to check for bogus values. They wrote libraries and jQuery plug-ins to make the job easier for others. 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.
However, the vast majority of form validation can be done with a few simple things:
required
to any input that you want
to require the user to fill out.
Here's a demonstration. (Note that I didn't re-use the input names from the earlier example because the JavaScript code above referred to the inputs by name, and so we need to make those unique. I could also have used a nested selector and given each form its own ID.)
Here's the actual form, so you can change the values of inputs:
Try to submit an incomplete form!
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.
The following sections are not required, but are included for the interested student.
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.
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.
To be written. See the somewhat more complex code in example-using-fieldset-and-jq.html, which you're welcome to explore on your own (or ask us during office hours).
As we mentioned, radio buttons and checkboxes are trickier. Let's
start with radio buttons, like our grades
radio button set
above. Here, we can't use an ID, because there are six buttons, and
each would have to have its own ID. We can use just the name, since
they all share a name. We can't use val
just by itself,
though, because all six of them have a different value. However, jQuery
provides us a pseudo-class
called :checked
that will
narrow the selection to just the checked button.
Thus, the following expression will evaluate to the checked grade:
$("input[name=grade]:checked").val()
Try it:
Checkboxes are even trickier, because more than one of them might be
checked, so there's more than one value. If you just want
the first checked value, jQuery makes that easy, because
the val
method returns the value of the first selected
element.
alert($("input[name=spells]:checked").val());
Thus, the following expression will evaluate to the first checked spell:
$("input[name=spells]:checked").val()
However, if you want all the checked values,
the val
method needs to return a set of values. It does
that with arrays, which we've read a tiny amount about, and
which we'll learn more about at later time.
Here's an example form, using checkboxes: