Solution
See the Control section if you don't want to read everything.
Layout
If using more than one
form control...
...wrap everything in a <form>
tag and give it an #id.
...separate form controls into groups and wrap them into <fieldset>
tags.
...give the <fieldset>
s and form controls #ids.
Access
For complete control of a <form>
...
Next, collect all of the <form>
tag's form controls using the .elements property:
var fields = formObj.elements
Having done that, you may use HTMLFormControlsCollection to reference any form control like a HTMLCollection by referencing the elements property and #id of the form control:
var set = fields.**fieldsetID**
var sel = fields.**selectID**
var btn3 = fields[2] // third form control
Control
An element's attributes are initially set by hard coding them in HTML:
<fieldset disabled>
Or programmatically by JS methods like setAttribute()
fieldsetObj.setAttribute('disabled', true)
Once an attribute is established, it should be referenced as a property if you want to change it:
fieldsetObj.disabled = false;
Event Handling
Delegate Events by registering events to the <form>
tag.
formObj.addEventListener('change', function)
Events that are the most applicable are:
change, input, click, focus, blur, submit, reset
When all events are delegated to the <form>
tag, the Event Object property Event.currentTarget will always refer to it. The element that was actually clicked, changed, received user input, gained focus, etc. is the origin of the event and can be referenced as Event.target.
Once an event occurs, an event chain will enter the capture phase:
e.currentTarget ===> e.target
<form> ============> <input>
Then the target phase:
e.target changed
<input checked>
Last is the bubbling phase any other elements thereafter will be triggered by event if arranged to do so by its own default behavior, by being registered, or arranged to do so (ex. if x is this, then y is that):
e.target =============> e.currentTarget
<input checked> ======> <form>
Tags
Many (but not all) form controls have special behavior that facilitates the operation of a <form>
and its form controls:
<fieldset>
: apply the [disabled] attribute to it and all of the form controls nested within will be enabled/disabled as well.
<input type="radio">
: apply the [name] attribute to a group of [radios] and they will be mutually exclusive when [checked] (i.e. only one may be checked)
Form controls with a [name] attribute will have their value
sent to a server when the <form>
submits.
<label>
: apply [for] attribute and set its value to another form control's #id will sync said <label>
and form control together. If a click event happens on said <label>
, then the associated form control will behave as if it was clicked as well.
Not all of the inherit traits listed above are used in the Demo but are mentioned because the possibility is there if needed.
Demo
Details commented in Demo
// Reference the form tag
var main = document.forms.main;
// Collect all of #main form controls
var m = main.elements;
// Reference the radio group
var g0 = m.grp0;
// Register change event on #main
main.addEventListener('change', action);
// Define callback passing the Event Object
function action(e) {
// if the changed element's [name] is "grp0"...
if (e.target.name === "grp0") {
// ...if "grp0" value is "on"...
if (g0.value === 'on') {
//...find the #set0 and enable it
m.set0.disabled = false;
} else {
//...otherwise disable #set0
m.set0.disabled = true;
}
//...otherwise if it isn't then ignore it.
} else {
return false;
}
}
/* for future exansion of form#main add if else condition between
|| if and else conditions
*/
<form id='main'>
<fieldset id='ctrl'>
<label>Group 1 On
<input name="grp0" value="on" type="radio" checked/>
Off
<input name="grp0" value="off" type="radio" />
</label>
</fieldset>
<fieldset id='set0'>
<legend>Group 1</legend>
<textarea id="txt"></textarea>
</fieldset>
</form>