Form Values

It is often necessary to be able to get or set values of form fields. While it's possible to do so in a cross-browser fashion, you must be careful to use the correct functions and attributes.

This page will only work on browsers which support the DOM and have Javascript enabled. The form on the left will allow you to make changes (except in the fields which show the selected value for the radio buttons or the drop-down menu) which are reflected in the form on the right.

The event objects are retrieved using the procedure demonstrated in the Javascript Events snippet.

Make changes in this form

Changes appear in this form

Text field:

Text area:

Radio buttons:
Selected value:

Checkbox:

Drop-down menu:
Selected value:

In code examples below, it is assumed that obj is the object which triggered the event.

Text Fields and Text Areas

The contents of a text field or text area can be retrieved or set using the .value attribute:

var contents = obj.value;     // Retrieve value
obj.value = 'New contents';   // Set new value

When the contents of a text field are changed, an onchange event is triggered. Unlike other form fields, you must attach the onchange event handler directly to the input field or text area, either with an onchange attribute or via Javscript. For example:

<input type="text" name="textfield" onchange="textchanged()"/>
<textarea name="textarea" onchange="textchanged()"></textarea>

Checkboxes

The status of a checkbox is reflected in the boolean attribute .checked:

var ischecked = obj.checked;  // Retrieve value
obj.checked = true;           // Force checked state

When the form is submitted to the web server, the .checked attribute is sent when the checkbox is in the checked state, and it isn't sent when the checkbox is in the unchecked state. You can retrieve or change this value with the .value attribute, as with text fields.

An onclick event is triggered when the checkbox is clicked. If your event handler returns false, the state of the checkbox will not change on Internet Explorer or Mozilla (and other Gecko-based browsers). On Safari, however, the event handler's return value is ignored.

Radio Buttons

Radio buttons are different than other form objects since there are multiple objects which aren't in a hierarchy. Instead, the objects are distinct, but happen to share the same name. For example:

<fieldset id="radios"><legend id="foo">Choose a letter:</legend>
  <label><input type="radio" name="letter" value="one"/> A</label>
  <label><input type="radio" name="letter" value="two"/> B</label>
  <label><input type="radio" name="letter" value="three"/> C</label>
</fieldset>

The radio buttons are logically grouped with <label></label> tags, as is the description for each choice. When the form is submitted, the variable letter will be passed with the value of the selected radio button, or in this case, either one, two, or three. We also group the radio buttons with a fieldset container which we can later find. The fieldset also draws a box around the buttons, further emphasizing that they are a group.

As with checkboxes, the .checked attribute shows whether a particular radio button is selected, and the .value attribute reflects the object's value. If no value is set either in HTML or Javascript, the value on is returned when a radio button is selected.

Setting a particular radio button is a bit trickier, since you need to find which radio button should be selected. Notice that we do not set individual id attributes in our example, since that would cause the id and name attributes to not match, which will trigger an error with some HTML checkers. One method is to group the radio buttons (as in this example) and set the .checked property as necessary:

var radios = document.getElementById ('radios');
if (radios) {
  var inputs = radios.getElementsByTagName ('input');
  if (inputs) {
    for (var i = 0; i < inputs.length; ++i) {
      if (inputs[i].type == 'radio' && inputs[i].name == 'letter')
        inputs[i].checked = inputs[i].value == 'two';
    }
  }
}

This sample code will select the radio button with value two. If you select one radio button in a group, all other buttons in that group will be deselected.

Selecting a radio button will trigger an onclick event. If your event handler returns false, Internet Explorer will not change the state of any radio buttons. Mozilla will allow the user to select one radio button, but will prevent any subsequent changes. Safari will, as with checkboxes, ignore the return value.

Drop-down Menus

While there are many ways different browsers can reflect the selected value, one which works on different browsers is:

var n = obj.selectedIndex;    // Which menu item is selected
var val = obj[n].text;        // Return string value of menu item

To set the value, if you know the correct .selectedIndex, you can just set that. If you do not, you need to iterate over the various values:

for (var i = 0; i < obj.length; ++i)
  if (obj[i].text == 'Second')
    obj.selectedIndex = i;

If your HTML also sets value attributes for the different menu items, you can read and set the .value attributes for the various option objects.

Setting an event handler is trickier than the other form objects, since different browsers trigger different events.

Below is a small test which will show which events get generated. Each of the <select> and <option> tags has onclick and onchange events declared so you can see the browser's behavior.

One way to handle the event in a cross-browser manner is to set an onclick event handler on the outer select, such as:

<select name="menuchoice" onclick="didselect ()">
  <option>First</option>
  <option>Second</option>
  <option>Third</option>
</select>

You then need to make sure your current object is the same for all browsers:

while (obj && obj.tagName != 'SELECT')
  obj = obj.parentNode;

All browsers will ignore the return value of the event handler.

About This Page

If you look at the source for this page, you'll see that the method of retrieving and setting field values is at times quite different than in the examples in the text above. This is to both set up the two form fields (one for changing values, the other for only mirroring those changes) and to only set event handlers where necessary.

The second form on the right is not actually defined in the HTML, but a duplicate of the form on the left is made and inserted into the document using Javascript.

The event handlers are likewise not declared in the HTML, but are assigned at runtime with Javascript. After the window has completed loading, the following happens:

var f = document.getElementById ('firstform');
f.onclick = itemChanged;

The left form has an id attribute set to firstform, and it gets only an onclick event handler, since we will only use onchange event handlers directly on the text field and text area objects. Those are set with a call to a function which fixes up the master form:

function fixupMaster (obj) {
  if (obj.childNodes)
    for (var i = 0; i < obj.childNodes.length; ++i) {
      var cobj = obj.childNodes[i];
      if ((cobj.tagName == 'INPUT' && cobj.type == 'text') ||
          cobj.tagName == 'TEXTAREA')
        cobj.onchange = itemChanged;
      fixupMaster (cobj);
    }
}

While a separate event handler can be used to manage the onchange events, this page uses the same event handler to demonstrate how one event handler can manage many different events.

After determining the object which triggered the event, the event handler builds a string which represents the event and triggering object:

var switcher = e.type + '/' + obj.tagName +
                  (obj.tagName == 'INPUT' ? '/' + obj.type : '');

For example, when the event handler is called for an onchange event from the text area, the string's value is change/TEXTAREA. An onclick event triggered by the checkbox would set the string to click/INPUT/checkbox. If there were multiple instances of a particular item which needed to have different actions (such as multiple checkboxes), other identifiers could be included in the string. note that the .type attribute is only appended if the object has a .tagName of INPUT, since other objects can use the .type attribute differently than we would expect.

Once we have this selector string, we can act differently depending on how the event handler was triggered:

switch (switcher) {
case 'change/TEXTAREA':
case 'change/INPUT/text':
  // do things for text fields here
  break;
case 'click/INPUT/checkbox':
  // do things for checkboxes here
  break;
case 'click/INPUT/radio':
  // do things for radio buttons here
  break;
case 'click/OPTION':
  while (obj && obj.tagName != 'SELECT')
    obj = obj.parentNode;
case 'click/SELECT':
  // do things for drop-down menus here
  break;
}

Notice that this event handler looks for the surrounding select object if an onclick event is triggered by an option, then falls through to the handler for the select object. This is functionally the same as the sample code above for drop-down menus.