(X)HTML Forms

There's a large family of (X)HTML elements that I've left out: (X)HTML forms. Forms are a means of input. When you enter a name and a password to log into a website, when you post to a forum, when you fill out information about yourself online, when you take an online quiz, you are using a form.

And they are completely useless without scripting.

All core, language, and event attributes are permissible with these elements, unless otherwise stated. Some have events of their own; since those can be used like attributes, they're mentioned in the attribute lists, but are highlighted by their color.

There are nine elements that are especially for forms, but the form family of elements isn't like other families such as lists and tables, which exist on their own. Many form elements must be nested inside block elements; these block elements are what structure the form.

How JavaScript Accomodates Forms

JavaScript is designed to play extra-special nice with forms. Form elements are given extra properties to facilitate their use. Those properties are tied directly to attributes with the same name. Two of the most important attributes/properties are name and value.

The Name Attribute

The name attribute holds a very important place in forms. Virtually every language created to work with forms (both client-side and server-side) uses these names to extract data. JavaScript is no different. The following form-related elements get the name attribute:

Yes, I know I introduced the button class way back in Inline Elements, but they're usually used in forms.

JavaScript has a neat way of handling the name attribute: the value of the name attribute is treated like the name of a property which contains a reference to that form element node. For example, if I gave a form element the name Form1, then Form1 would be a property of the document node. Any form elements with name attributes of their own within that form element can be referred to using its name as a property of Form1. If multiple elements have the same name value, then JavaScript considers that a node list.

The Value

The value is what's passed on to the script. It can be defined in the value attribute (with the exception of the textarea element, where the value is set through the element's content), but can be overridden by interaction with the input.

The value of an input is accessed through the property of the value property.

Do note: If you set a default value but override it through interaction with the input, you will still be able to get the original value through the getAttribute function (for most inputs) or through firstChild.data for the textarea element, since those methods read right from the webpage code; the webpage code is only altered through methods I will explain in DOM Manipulation. I've used this to my advantage.

The Form Element

Element Name: form

There are form elements, and then there's the form element. When I talked about form elements, I meant the numerous elements that accept input, give the form structure, label the form, and so on and so forth. The form element is the element that contains the form itself.

Required Attributes

action
This contains the URI of the file containing the server-side script that handles all this. If all you're doing with the form is using it with client-side scripting (such as JavaScript), you can just leave this attribute empty.

Implied Attributes

method
Again, this is for server-side scripting. It has two values: GET (the default) and POST, which describes how the information from the form is sent. GET affects the URI, and a ? in the URI is a good indication that this is going on. The server-side script generating the resultant page then gets the necessary information from the URI. POST, on the other hand, just posts information to the server without affecting the URI.
enctype
This lets the server know the content type of form being submitted to the server. It has a default value: application/x-www-form-urlencoded.
accept
This is a comma-seperated list of content-types that the server will handle correctly. A user agent (such as a browser) can use this list to filter out certain file types when an input element is of the file upload type.
accept-charset
This is a list of character sets that can be used with the form.
onsubmit
Run a client-side script when the form is submitted. This may also be set via client-side scripting.
onreset
Run a client-side script when the form is reset. This may also be set via client-side scripting.

Entering Data

For a form to function, it has to have a means of receiving input. The input, textarea, and select elements all provide various means of entering that input.

All input elements must be descendants of block elements within the form element.

Common Attributes

tabindex
As mentioned in Inline Elements, this sets the order in which the focus jumps from one element to another (in this case, the various input elements) when the tab key is pressed.
disabled
This attribute means that the input element cannot be used, and server-side scripts will not read from the input (client-side scripts will, though). It is a boolean attribute and corresponds property disabled.
onfocus
The element got the focus of the browser.
onblur
The element loses the focus of the bowser.
onselect
Some text is selected.
onchange
The value is changed.

onfocus, onblur, onselect, and onchange are all events and may be set through client-side scripting.

The Input Element

Element Name: input

The input element is where you enter the information. It must be contained within a block element, such as p or li.

The input element is an empty element. It has no end tag.

Implied Attributes

The following are used in all input elements. Attributes used in specific types are explained in their own sections.

type
What type of input is needed (more on this later). The default value is text
name
The name of the input (or set of inputs)
value
The default value of the input.
size
The size of the input. For most controls, it's measured in pixels, but with text or password inputs, it's measured in characters.
alt
A short explanation of the input. Very useful for accessible websites.
accesskey
Key used to access the input.
disabled
tabindex
onfocus
onblur
onselect
onchange
Explained above

Input Types

The attribute type is the most important attribute in an input element. It describes what kind of input it is. The type has the following possible values:

  • text
  • password
  • checkbox
  • radio
  • button
  • reset
  • submit*
  • file*
  • hidden
  • image*

* Server-side use only

Every attribute I mention in this section on input elements can be used with any type. However, not all of them will do what is expected. For example, you may use the checked attribute with an input element with type text. It just won't do any good.

The attribute type corresponds with the property type, and may be changed through JavaScript.

Text and Password Boxes

Both of these are text boxes, but the text inside them is handled differently. In a textbox, it's clear for all to see; in a password box, the text is obscured:

Text and Password boxes
Attributes for Text And Password Boxes
value
This attribute sets the default text for the text or password box. Changing this text will change the value of the input.
readonly
This attribute means the text in it can't be directly altered by the user. It is a boolean attribute and corresponds with the JavaScript property readonly.
maxlength
This numeric attribute sets the maximum number of characters that can be entered into a field. The length of the text field is irrelevant.
Getting Text From Text And Password Boxes

The text of a textbox or a password box is known as its value. It's this property that you use to get its information.

Below is a simple form and the script used to get its information:

Demonstration Of Text and Password Inputs
The HTML Form
<form action="../../submit.html" id="JS-Forms-Form" name="Form">
<dl>
<dt>type="text"</dt>
<dd><input type="text" name="Input"></dd>
<dt>type="password"</dt>
<dd><input type="password" name="Input"></dd>
</dl>
<p><input type="button" value="Show Text" name="Click"></p>
</form>
<p>Textbox text: <span id="Text-text">&nbsp;</span></p>
<p>Password text: <span id="Pass-text">&nbsp;</span></p>
The Form's Script
var form = document.Form;
var txt = document.getElementById("Text-text").firstChild;
var pass = document.getElementById("Pass-text").firstChild;
form.Click.onclick = function(){
Write(form.Input[0].value, txt);
Write(form.Input[1].value, pass);
}
function Write(box, span){
span.data = (box)?box:"Null";
}

Notice that I highlighted the contents of the name attributes to show how the form name becomes a property name of the document and the input names become property names of the form; that's what I meant by, In JavaScript, the value of name becomes an property of its respective form element node.

Below is the result:

Text and Password boxes
Checkboxes and Radio Buttons

Checkboxes and radio buttons allow for multiple choice. There is one major difference: More than one checkbox can be chosen, but only one radio button may be chosen.

Radio buttons and checkboxes

If two or more radio buttons share the same name, only one of those buttons can be checked at any time. Below, I have two groups of radio buttons arranged in columns; one is named G1, the other G2.

Two Groups Of Radio Buttons
<table>
<tr>
<th>G1</th>
<th>G2</th>
</tr>
<tr>
<td><input type="radio" name="G1"></td>
<td><input type="radio" name="G2"></td>
</tr>
<tr>
<td><input type="radio" name="G1"></td>
<td><input type="radio" name="G2"></td>
</tr>
<tr>
<td><input type="radio" name="G1"></td>
<td><input type="radio" name="G2"></td>
</tr>
</table>

Three share the name G1, the other three the name G2. Therefore, there are two groups and only one from each group can be chosen (two choices in total).

Two groups of radio buttons

Which is the case.

Attributes for Checkboxes And Radio Buttons
checked
This sets the name of what is automatically selected when the page is loaded. If more than one radio button in a single group has this, the last button with this attribute in the group is the one that is checked. If the inputs are checkboxes, then all checkboxes with this attribute are checked. It is a boolean attribute and corresponds with the JavaScript property checked.
value
This attribute is a lot more important in these controls than they are in text boxes and passwords. The value attribute is a checkbox's or radio button's only means of passing on information beyond whether or not it is checked to the script.
Getting A Value From Radio Buttons And Checkboxes

When you assign the same name to inputs, the name, used as a property, returns an actual node list, which you can then use like an array.

Both types of inputs have a property called checked. If a checkbox or radio button is checked (i.e. selected), the property returns the boolean value true. Otherwise, it returns the value false.

Look at the example below:

Radio buttons and checkboxes

I have one list with checkboxes, and another with radio buttons.

The Inputs Of The Form
<ul>
<li><input type="checkbox" name="Decorate" value="underline">Underline</li>
<li><input type="checkbox" name="Decorate" value="overline">Overline</li>
<li><input type="checkbox" name="Decorate" value="line-through">Strike-through</li>
</ul>
. . .
<ol>
<li><input type="radio" name="Sentences" checked="checked"></li>
<li><input type="radio" name="Sentences"></li>
<li><input type="radio" name="Sentences"></li>
<li><input type="radio" name="Sentences"></li>
</ol>
. . .
<p id="Click_Here"><input type="button" name="Click" value="Show Text"></p>

You can't show both 1 and 2 or 2 and 4 sentences, but you can have the letters underlined, overlined, and struck through. Therefore, radio buttons for the number of sentences, and checkboxes for the text decoration.

Below is the full script:

The Form Script
var form = document.Form1;
var txt = document.getElementById("Display_Text");
var lorem = document.getElementById("Lorem").firstChild.data.split(".");
form.Click.onclick = function(){
var sentence = -1;
var text = "";
var decor = "";
do{
sentence++;
text += lorem[sentence] + ". ";
} while(!(form.Sentences[sentence].checked));
txt.firstChild.data = text;
for(var l = 0; l < form.Decorate.length; l++){
if(form.Decorate[l].checked){
decor += form.Decorate[l].value + " ";
}
}
txt.style.textDecoration = decor;
}

The radio buttons in the Sentences group is handled by a do-while loop.

The Do-While Loop Chooses How Many Sentences To Show
do{
sentence++;
text += lorem[sentence] + ". ";
} while(!(form.Sentences[sentence].checked));

The Lorem Ipsum text is split using the period as a delimiter, resulting in an array of four sentences (lorem). Every time the loop is run (as a do-while loop, it's run at least once), sentence (initially set to negative 1) is incremented by one, the text stored in the slot that corresponds to the variable sentence is added to text, and the while condition keeps everything going so long as the radio button that sentence had corresponded to is not checked.

There's a couple of things I want to point out. First, if no radio buttons in that group were checked, this would technically be an infinite loop (or, rather, would crash when it ran out of nodes), but recall in the HTML, one of the radio buttons has the attribute checked, so even if you don't check a radio button, one will be automatically checked. Second, I omitted the value attribute from the radio buttons— I don't need it. The do-while loop tells the script to keep adding text until it encounters a checked radio button, allowing me to omit value.

Since only one radio button can be checked, the loop doesn't need to run anymore once a checked one is found. Thus, a while loop (or in this case, a variation thereof) is used.

Meanwhile, since any number from none to all checkboxes can be checked, we have to go through all of them. This calls for a for loop, which will check all of them.

The For Loop Chooses Which Styles To Use
for(var l = 0; l < form.Decorate.length; l++){
if(form.Decorate[l].checked){
decor += form.Decorate[l].value + " ";
}
}

This loop thus runs through the node list represented by Decorate, so the if statement checks to see if each one is checked (which, remember, returns a value of true). Each time one is, the variable decor (which starts out empty) is updated, and the final result is later sent to the style property textDecoration. As you know, in CSS the value underline overline strikethrough is perfectly acceptable, and so it is with JavaScript.

Buttons and Reset Buttons

The last two inputs that are commonly used for client-side scripts are the reset button and the regular button. The reset button simply resets the form to its original state, while the regular button is there for something to click on (for example, if you're running a client-side script).

The value attribute of these alter their text. Normally, a button-type input has no text, and a reset button has simply the word Reset.

Button and Reset
Others

There are four types of inputs that I didn't mention, mostly because they're used with server-side scripting:

file
This allows for file input.
submit
Submits the form to the server for processing
image
An image that works like a submit button. It shows up like an image, but when you click on it, the values passed onto the pages specified in the action attribute of the form element are the x- and y-coördinates of where you clicked on the image. Yes, it works like an server-side image map, as explained in Image Maps. It has the following attributes:
src
The source of the image.
usemap
Use a client-side image map.
ismap
Use a server-side image map.
All work the same way as they do in img elements.
hidden
This control isn't seen on the webpage, but is often used to contain information that you want to work with.
The rest of the inputs

The Text Area Element

Element Name: textarea

The textarea element is used to contain large amounts of text, and therefore shows multiple lines (as opposed to the input element, which shows only one).

While this attribute does not have a value attribute (though it does have a value property), this is offset by the fact that this is not an empty element, and may therefore contain text. It cannot have other elements nested in it, though, and treats them like the title element does.

Required Attributes

rows
How many rows of text to display (i.e. height).
cols
How many characters to show per line (i.e. width).

There are other attributes that may be used with the input element, but work best with specific types.

Implied Attributes

readonly
This attribute, when present, must have the value readonly. It means the text in it can't be directly altered by the user.
tabindex
Sets the order of tabbing.

While this element does not have a name element, you can identify it by the id element, which will have much the same effect.

Using A Text Area

The text area presents a special challenge because its contents may include new lines, which I explained back in Text.

In the example below, the script takes the text entered into a text area, and writes the first three lines that contain text to three separate p elements. You will see that the id attribute can be used like a property for these elements.

Text from text area Echoed In p Elements
var form = document.getElementById("Form");
var txt = form.Text;
var write = document.getElementById("Write").getElementsByTagName("p");
form.Click.onclick = function(){
var txt_split = (txt.value.match("\r\n"))?txt.value.split("\r\n"):txt.value.split("\n");
var l = 0;
var pc = 0;
while(pc < write.length && l < txt_split.length){
if(txt_split[l].length > 0){
write[pc].firstChild.data = txt_split[l];
pc++;
}
l++;
}
}

Note the highlighted line. Some browsers see a new line in a text area as a carriage return character (\r) followed by a new line character (\n), while others see a new line as simply a new line character. Here, I have set up the script to choose which to split the line on.

The result is below:

A text area

There are several blank lines, but all have a length of 0, which means that the if statement skips them.

Dropdown Menus

Dropdown menus are yet another means of input. These elements come in a specific set. The elements are:

The Select Element

Element Name: select

The select element contains all the options associated with it. This element must be a child of a block element.

Implied Attributes
size
This numeric attribute sets how many rows of options are visible. The default is one.
multiple
This attribute allows you to make multiple selections rather than just one. It is a boolean attribute.

The Option Element

Element Name: option

The option element is what contains the values that are passed on to the script. Moreover, it is not an empty element, but may contain text, since the contents of the value attribute and the text of the element may indeed differ.

Implied Attributes
label
This allows for a shorter label than the option element's content.
selected
An option element with this boolean attribute is pre-selected. If there is more than one option element within the same select element with this attribute, the last option element with this attribute is preselected. It corresponds with the JavaScript property selected.
value
This contains the information the selected option element (and thus the entire select element) passes on to the script.

The Option Group Element

Element Name: optgroup

The optgroup element contains a group of options. This creates a heirarchy in the list of options; useful for organizing a list of options.

Implied Attributes
label
This contains the label of the option group.

Using A Dropdown Menu

Below is a page that uses all of these elements:

Select an option

Here is the code of the elements in question:

The Code Of A Dropdown Menu
<select name="Selection">
<optgroup label="Words">
<option value="7">Seven</option>
<option value="2">Two</option>
</optgroup>
<optgroup label="Digits">
<option value="5">5</option>
<option value="6">6</option>
</optgroup>
<optgroup label="Roman Numerals">
<option value="1">I</option>
<option value="8">VIII</option>
</optgroup>
<select>

I could have easily arranged them like this as well, eschewing the optgroup altogether:

The Code Of A Dropdown Menu Without optgroup elements
<select name="Selection">
<option value="1">I</option>
<option value="2">Two</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">Seven</option>
<option value="8">VIII</option>
</select>

Below is the script that works with this particular control:

A Script That Reads A Dropdown Menu
var form = document.getElementById("Form");
var txt = document.getElementById("Answer").firstChild;
form.Click.onclick = function(){
var ans = Number(form.Selection.value);
if(ans > 5){
txt.data = "greater than 5";
}else if(ans < 5){
txt.data = "less than 5";
} else {
txt.data = "equal to 5";
}
}

Below, I select a random option, and click the button for a comparison.

Select an option

If I want to get rid of the button, and have simply selecting an option do the comparison, a simple change of the code suffices:

A Script That Reads A Dropdown Menu Automatically
var form = document.getElementById("Form");
var txt = document.getElementById("Answer").firstChild;
form.Selection.onchange = function(){
var ans = Number(form.Selection.value);
if(ans > 5){
txt.data = "greater than 5";
}else if(ans < 5){
txt.data = "less than 5";
} else {
txt.data = "equal to 5";
}
}

I set the event to detect a change in Selection's value, and that runs the script instead, which means I can get rid of the button:

Select an option

Labelling And Arranging The Form

There are two things you can do to make a form easier to work with. First, you can use labels for all your input elements. Second, you can break the form up into smaller, more manageable parts and label those parts. The first is done with the label element, the second with the fieldset and legend elements

The Label Element

Element Name: label

The label element is usually used with the input element, though it can also be used with textarea and select as well.

It is permissible for other inline elements (including input, textarea, select, and other label elements) to be nested inside a label element.

Implied Attributes

for
This is an ID reference attribute; it refers to the ID of another element. Clicking a label that has a for attribute will place focus on the element that the for attribute refers to. In the case of checkboxes and radio buttons, this will actually select them.
onfocus
The element got the focus of the browser.
onblur
The element loses the focus of the bowser.

The Fieldset Element

Element Name: fieldset

The fieldset element is like a div element for forms; it breaks the form up into separate chunks. However, it's not supposed to contain anything but whitespace (enters, tabs, and spaces) and elements nested therein. If given an ID that matches the name given to form elements, it will be considered part of the resulting node list.

Unlike most form elements, it has no special attributes.

The Field Legend Element

Element Name: legend

The legend element gives a title to the fieldset element and must be its first child. Like the fieldset element, legend has no special attributes.

Example Form

Below is a form that is arranged and labelled with the elements mentioned above. Yes, it's an adjustment of the example with checkboxes and radio buttons.

The Form Organized Into groups
<form action="" name="Form1">
<fieldset id="Decoration">
<legend>Text Decoration</legend>
<ul>
<li><input type="checkbox" name="Decorate" value="underline" id="Decor_Under"><label for="Decor_Under">Underline</label></li>
<li><input type="checkbox" name="Decorate" value="overline" id="Decor_Over"><label for="Decor_Over">Overline</label></li>
<li><input type="checkbox" name="Decorate" value="linethrough" id="Decor_Strike"><label for="Decor_Strike">Strike-through</label></li>
</ul>
</fieldset>
<fieldset id="Show_Sentences">
<legend>Sentences To Display:</legend>
<ul>
<li><input type="radio" name="Sentences" id="First_1" checked="checked"><label for="First_1">First Sentence</label></li>
<li><input type="radio" name="Sentences" id="First_2"><label for="First_2">First Two Sentences</label></li>
<li><input type="radio" name="Sentences" id="First_3"><label for="First_3">First Three Sentences</label></li>
<li><input type="radio" name="Sentences" id="First_4"><label for="First_4">First Four Sentences</label></li>
</ul>
</fieldset>
<p id="Click_Here"><input type="button" value="Show Text" name="Click"></p>
</form>

With the stylesheet of the page removed, the form looks like this:

Organizing a form

Do note: I did not change the script at all. These elements don't affect the script in any way. Yes, I know part of the page was truncated; those are the same paragraphs as you saw in the original radio button and checkbox demonstration.

Manipulating Forms

Earlier in this chapter, I mentioned that there were a few attributes that corresponded with JavaScript properties in forms. Those attributes were:

JavaScript reads from these properties, but it can also set them—and through setting them, alter the inputs themselves. To demonstrate this, I created a webpage where you can choose what kind of input an input element will be.

A Webpage That Changes The Input Type
The Form
<form action="" id="Form">
<p><label>Input Types:</label> <select name="Type">
<optgroup label="Text Inputs">
<option value="text" selected="selected" title="Insert text">Text</option>
<option value="password" title="Enter Password">Password</option>
<option value="file" title="file.html">File</option>
</optgroup>
<optgroup label="Checked Inputs">
<option value="radio">Radio Button</option>
<option value="checkbox">Check Box</option>
</optgroup>
<optgroup label="Button Inputs">
<option value="submit" title="Submit Query">Submit Button</option>
<option value="reset" title="Reset">Reset Button</option>
<option value="button">Button</option>
<option value="image">Image</option>
</optgroup>
</select></p>
<p><label>Input To Be Changed</label>: <input name="Input" value="Insert text" src="./arrow.png"></p>
</form>
The Script
var form = document.getElementById("Form");
var inp = form.Input;
var sel = form.Type;
var ops = sel.getElementsByTagName("option");
sel.onchange = function(){
inp.type = sel.value;
inp.checked = true;
var i = 0;
while(!ops[i].selected){i++;}
inp.value = ops[i].getAttribute("title");
}

The important part of the script is highlighted: The input type is set to the value of the select element.

I have used this in actual websites! An input element, set to the button type, had an onmousedown event that ran a whole bunch of error checking to make sure all inputs were properly filled out. If there was a problem, alert boxes would show up and point out the errors and the type remained button (which of course, meant the form wasn't submitted to the server). If all was done correctly, however, the input element's type was set to Submit, which meant the form was submitted to the server for processing.

I have also done something similar with the disabled property. A server-side script ignores inputs that are disabled. It also ignores checkboxes that aren't checked. Using a script that boiled down to input.disabled = !controlling_checkbox.checked (basically, if checked was true, disabled was false and vice versa) I was able to choose which sets of inputs were read from.

To demonstrate, I have created something similar here: a form in which a checkbox decides whether or not the inputs in each fieldset element are disabled or not.

A Webpage That Disables Or Enables A Set Of Inputs
The Form
<form action="" id="Form">
<fieldset><legend>Group 1</legend>
<label>Use These Inputs?</label><input type="checkbox" name="Use_Inputs" checked="checked">
<p><select>
<option>Choice 1</option>
<option>Choice 2</option>
<option>Choice 3</option>
<option>Choice 4</option>
</select></p>
<p><textarea cols="11" rows="1">Block Of Text</textarea></p>
<p><input type="radio"><input type="radio"><input type="radio"></p>
</fieldset>
<fieldset><legend>Group 2</legend>
<label>Use These Inputs?</label><input type="checkbox" name="Use_Inputs" checked="checked">
<p><select>
<option>Choice 1</option>
<option>Choice 2</option>
<option>Choice 3</option>
<option>Choice 4</option>
</select></p>
<p><textarea cols="11" rows="1">Block Of Text</textarea></p>
<p><input type="radio"><input type="radio"><input type="radio"></p>
</fieldset>
</form>
The Script
var form = document.getElementById("Form");
var use_inp = form.Use_Inputs;
for(var i = 0; i < use_inp.length; i++){
use_inp[i].onclick = function(i){return function(){
var field = use_inp[i].parentNode;
var selects = field.getElementsByTagName("select");
var textareas = field.getElementsByTagName("textarea");
var inps = field.getElementsByTagName("input");
for(var ii = 0; ii < selects.length; ii++){
selects[ii].disabled = !(use_inp[i].checked);
}
for(var ii = 0; ii < textareas.length; ii++){
textareas[ii].disabled = !(use_inp[i].checked);
}
for(var ii = 1; ii < inps.length; ii++){
inps[ii].disabled = !(use_inp[i].checked);
}
}}(i);
}

Below, you can see that the checkbox in the first fieldset element is checked and the inputs are active. Meanwhile the checkbox in the second fieldset element is unchecked, and the inputs are disabled.

Disabling Inputs through JavaScript

I would like you to notice something about the highlighted for loop: It starts at 1, not 0. The reason for this is that input element #0 is the checkbox that controls the disabling of the other inputs. If I disable that, I'd have to reload the page to enable those inputs again.

In the same way that you can control the type and disabling, you can set the value of an input using the value property. In textboxes and password and text inputs, it changes the text; in submit, reset and button-type inputs, it changes the text of the buttons, and in select elements, the option element with that value is selected.

Well, that's it for (X)HTML elements. Now that I've explained forms, I've taught every element in HTML 4.01 Strict and XHTML 1.0 Strict. That does not, however, mean I'm done with the (X)HTML DOM, since there's plenty to play with yet...