Forms

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.

Forms

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 FORM Tag

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.

... inputs go here ...

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 Tag

The INPUT tags have several different types, which you specify using the TYPE attribute. The types include at least the following:

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.

Radio Buttons and Checkboxes

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:

favorite fruitfavorite tech company
apple Apple
banana Google
orange Microsoft

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.

The SELECT input

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:

Drink:

(The closing </option> tag is optional, like a closing </p> tag or </li> tag.)

The email message will display whichever option the person chose.

The TEXTAREA input

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.

SUBMIT, RESET and BUTTON elements

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.

Structuring Forms

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:

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.

Expandable/Collapsible Forms using JavaScript

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:

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.

Processing Form Data using JavaScript

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 about Form Data and JavaScript

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.

Misconception 1: form inputs versus variables

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:


Try it! Execute that code, and check the error console. Even better, copy/paste the code into Firebug and see it there.

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.

HTML land and JavaScript land, and copying values back and forth

Misconception 2: naming form inputs and variables

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:

  

Form Validation

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:

  1. link in the jQuery library, as always
  2. link in the validation plugin (a JS library)
  3. use HTML/CSS classes to mark the validation requirements. In the simple case, just add a class="required" to each required input
  4. invoke the .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:

We've applied these steps to this validated example form. Try it and view the source to learn more.

CGI

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.

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.

Echoing the Data

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 .

Exercise 1

Emailing the form data from Puma

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:

  1. Make the FORM tag look like this:
    <form name="mailform"
          method="post"
          action="/cgi-bin/eform.cgi">
    </form>
    
  2. make sure there is a recipient for the email message. This is usually done via a hidden input:
    <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.

Wrong Server

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.

Exercise 2

Other CGI Scripts

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.

Solutions to Exercises

Summary

In this lecture, we learned

Optional reading: Meyers Ch. 14-15, Thau Chapter 7.