reptile7's JavaScript blog
Sunday, July 24, 2005
 
Properties VI: Form Control Elements
Blog Entry #17

As detailed by the Forms sector of the HTML 4.01 Specification, there are at least twelve types of form controls, which we can put into three categories:

(1) Field-type controls, for which the user inputs information, usually a text string, into a rectangular box, including:
(a) the text box;
(b) the textarea box;
(c) the password box;
(d) the file select box;
(e) the hidden field, for which the form author does the inputting, also belongs in this category.

(2) Menu-type controls, for which the user chooses one or more options on a list of items, including:
(a) the radio button;
(b) the checkbox;
(c) the selection list.

(3) Button-type controls, including:
(a) the general push button;
(b) the non-image (regular) submit button;
(c) the image submit button;
(d) the reset button.

As noted in the last entry, we want to be able to utilize a user's responses to a form in JavaScript command statements. In this regard, we are mostly interested in the field-type and menu-type controls, which constitute the meat of a form in relation to user input and, moreover, whose name and value information would be sent to the processing agent if/when the form is submitted.

Each of the controls above is represented in JavaScript by a specific, corresponding object - a Text object, a Textarea object, a Password object, etc. - except for the image submit button*. With respect to the manipulation of form information by JavaScript, we have two general concerns:
(1) How do we refer to form control elements in JavaScript command statements?
(2) How do we determine the user's input?
As you can guess, we will use the properties of form control objects to answer these questions.

*Although supported by Netscape 4.x, the <input type="image"> element has no 'reflection' in JavaScript 1.3's set of client-side objects. Re the following section, programmatic access to this element is browser-dependent on my computer: MSIE/JScript treats it normally but Netscape/JavaScript doesn't recognize it at all.

Referencing form control objects

Each type of form control can be referenced in JavaScript as a member of a form's elements[ ] collection:

document.form_name.elements[i].property_or_method

And except for groups of radio buttons and checkboxes with the same name, each type of form control can also be referenced by its name:

document.form_name.control_name.property_or_method

The name of a control is usually preset by a name="control_name" attribute in the control element's opening HTML tag. However, each type of form control object has a read/write name property that can also be used to set the control's name.

A group of radio buttons or checkboxes with the same name constitutes a control_name collection of the containing form, and the individual radio buttons or checkboxes of the group can be referenced as a member of this collection. For example, consider a form with three radio buttons:

A
B
C

<form name="fr">
<input type="radio" name="letter" value="A"> A<br>
<input type="radio" name="letter" value="B"> B<br>
<input type="radio" name="letter" value="C"> C<br>
</form>

The first radio button can be referenced as:

document.fr.letter[0].property_or_method

The second radio button can be referenced as document.fr.letter[1].property_or_method, etc.

Unlike radio buttons, the individual checkboxes of a checkbox group do not need to have the same name, and if you were to assign different names to these checkboxes, then each checkbox can be referenced by its name, as for other types of controls. Moreover, a solitary radio button or checkbox in a form can also be referenced by its name.

(Note: a group of radio buttons with the same name is supposedly "stored as a single element of the elements array of the Form object" (to quote DevGuru's Radio object page); this isn't how it works on my computer (a Windows implementation, perhaps?), which gives identical returns for document.form_name.radio_group_name[i].property and document.form_name.elements[i].property commands for the same value of i, as shown in the "Radio Button User Input Test Div" demo below.)

Determining user input: field-type controls

The all-important property of all of the field-type control objects that determines - indeed, constitutes - a user's input is the value property. Let's illustrate with a simple example; type your first name into the text box below, and then click outside of it:

Please tell us your first name:

The code for this is:
<form name="fv">
Please tell us your first name: <input name="tv" onblur="window.alert('Glad you could stop by, ' + document.fv.tv.value + '.');">
</form>

in which the command:

document.fv.tv.value

returns the value, or user input, of the text box named tv, in the form named fv, in the document.

Next question: how do you ensure that the user's input is legitimate? Suppose you are running an e-business; how do you prevent the user from entering a six-digit number into the zip code field on your shopping cart page? Now we are getting into the realm of data validation, a topic that is beyond the scope of this blog entry but that we'll get a taste of in HTML Goodies' JavaScript Primers #29.

Determining user input: selection lists

It's easier to determine user input for a selection list than for a group of radio buttons or checkboxes, so we'll deal with selection lists first. The two key properties of the Select object relating to user input are the options property, which represents the collection of option elements composing the selection list and allows us to access those <option>s, and the read/write selectedIndex property, which sets or returns the index number (0, 1, 2, ...) of the currently selected option of the options[ ] collection. (Unique among the form control objects, the Select object does not have a value property.) To complete the picture, we then turn to the JavaScript Option object, whose read/write text property sets or returns the text of a given <option>. We put it all together in two lines of code:

var si = document.form_name.select_name.selectedIndex;
var user_input = document.form_name.select_name.options[si].text;

or one line, if you prefer:

var user_input = document.form_name.select_name.options[document.form_name.select_name.selectedIndex].text;

In summary, we first determine the index of the selected option and then plug that number into the options[ ] collection to determine the text of the selected option. Try it out with the demo below:

Choose your favorite day of the week from the selection list below:

The code for this is:
<form name="fs">
Choose your favorite day of the week from the selection list below:<br>
<select name="favday" onchange="var si = document.fs.favday.selectedIndex; window.alert(document.fs.favday.options[si].text + ' is my favorite day, too!');">
<option>Monday</option>
<option>Tuesday</option>
<option>Wednesday</option>
<option>Thursday</option>
<option>Friday</option>
<option>Saturday</option>
<option>Sunday</option>
</select>
</form>

Determining user input: radio buttons and checkboxes

When a HTML form is submitted, the values of its user-chosen radio buttons, checkboxes, and selection-list options (and of its other "successful controls") are sent to the processing agent. In JavaScript, however, there is no relation between the value property of the Radio, Checkbox, and Option objects and whether the corresponding control elements are 'switched on'.

Moreover, for collections of radio buttons and checkboxes, there is unfortunately no collection-wide selectedIndex-type property that returns the index number of a chosen radio button or checkbox, and even if there was such a property, it would probably have only limited utility with checkboxes; when a selection list is set up with the multiple attribute to allow more than one option to be selected, selectedIndex only returns the index of the first selected option.

The Radio and Checkbox objects do at least have a checked property that returns true if the corresponding control is checked and false if it isn't (the Option object has an analogous selected property). To determine the user input for a group of radio buttons or checkboxes, then, a trial-and-error approach is required; we're going to have to go through the group and determine the checked status of each radio button or checkbox. This might sound like a complicated or tedious process, but it actually isn't. We'll need to use a for loop - the for loop is introduced in Primer #24 - and an if conditional statement - if statements are introduced in Primer #13 - so yes, we'll be getting ahead of ourselves once again, and yet only three lines of code are required, so I'm going to give you the lowdown anyway.

The div below illustrates the determination of user input for a group of radio buttons in a form named fr2.

The Radio Button User Input Test Div

Choose a color below and then click the "You have chosen..." button.
Red
Orange
Yellow
Green
Blue
Indigo
Violet
Black



The code that is triggered by clicking the "You have chosen..." button is: for (var i = 0; i < document.fr2.length; i = i + 1) { if (document.fr2.elements[i].checked) { document.fr2.elements[9].value = document.fr2.elements[i].value; } } Very briefly: (1) The first line sets up a repeating block of code that runs according to a counter variable i. The block of code, delimited by braces, will repeat as long as i is less than document.fr2.length (10 in this case). The value of i is initially set to 0, and i increases by 1 at the end of each run through the loop; when i progresses to 10, the loop stops. (2) The second line asks the question for each value of i: is document.fr2.elements[i].checked true? If so... (3) The third line assigns the value of document.fr2.elements[i] to that of document.fr2.elements[9], the text box to the right of the "You have chosen..." button. (The value of each color-choice control is set to the text following the control.) You may be wondering, "Instead of this for loop business, can't we just add an onclick='document.fr2.elements[9].value = document.fr2.elements[i].value;' attribute to each <input type='radio_or_checkbox'> tag of the form?" In this case, the answer is yes for radio buttons but no for checkboxes. Consider the Black checkbox that concludes the list of color choices. You can click this checkbox and then click the "You have chosen..." button, and "Black" will appear in the text box - so far, so good. But if you reclick and thereby unselect the Black checkbox without making a subsequent choice (radio buttons do not toggle in this way), then the value of the text box is still "Black", which is obviously problematic vis-à-vis determining the user's input. Other properties OK, these are not the only properties of form control objects. But the other control object properties are less crucial. For example, each type of control object has a form property that returns a reference to the form containing the control. In practice on my computer, control_object.form returns "[object FORM]" when using MSIE and "[object HTMLFormElement]" when using Netscape, regardless of whether the form is named or not named. Finally, each type of control object has a type property, which is self-explanatory for the <input> control objects: text_object.type returns "text", radio buttons return "radio", etc.; Textarea objects similarly return "textarea". Curiously, general push buttons that are coded by <button> (as opposed to <input type="button">) return "button" and "submit" for the type property when using MSIE and Netscape, respectively. A Select object returns a type of "select-one" or "select-multiple" for a <select> element without or with a multiple attribute, respectively. I find that the type property is read-only when using MSIE but is read/write in some cases when using Netscape. For example, I am able to click a radio button into a checkbox with the following code: <input type="radio" onclick="this.type='checkbox';"> (The this keyword was briefly discussed in Blog Entry #8.) I am likewise able to change (a) a text box into a password box or a file select box, (b) a regular submit button into a reset button, and even (c) a submit button into a text box or a radio button. However, my attempts to change a text box into a radio button or a submit button caused the browser to crash.
We're just about ready to wrap up our discussion of JavaScript properties, at least for the time being, and move on to Primer #8. I still want to go over some of the properties of the window, History, Location, and Date objects - I don't know if I'll cover them all in one post - I'll start writing and then see how it goes.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)