Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Increasing form usability with JavaScript

2.00/5 (2 votes)
10 Apr 2007CPOL4 min read 1   33  
How to increase form usability with JavaScript.

Download the required resources before beginning this tutorial.

Introduction

So you can see what we're aiming to do, check out this fully functioning example.

Start by opening the file 'form-usability-resources-example.html'. This is a sample section of the form we're going to make more usable and attractive using JavaScript.

Even after reading the excellent Applying CSS to forms article, this form still isn't as exciting as it could be. Let's brighten up the form by adding some onfocus() events when an <input> or <label> is activated.

The JavaScript

Open the js.js file you downloaded and let's get started!

Registering an event

The first task is to create an event that occurs when the page has loaded. Rather than trying to execute a function call using <body onload="callfunction()"> within the HTML page, we're going to use Simon Willison's addLoadEvent(func). This will allow us to add function calls once the page has loaded.

Type the following JavaScript into the .js file:

JavaScript
function addLoadEvent(func)
{
  var oldonload = window.onload;
  if (typeof window.onload != 'function') { window.onload = func; }
  else { window.onload = function() { oldonload(); func(); } }
}
addLoadEvent(presentForm);

Collecting form elements

Create an empty function in your JavaScript file called presentForm:

JavaScript
function presentForm()
{
}

The second task is to create collections of the form elements that will be manipulated by the JavaScript. The <form> is nested in a <div> with an id="form". We can use the getElementById command to retrieve the <div id="form"> and assign it to the variable eleDiv. Next, we assign all forms within the <div> to the variable eleForms using the getElementsByTagName command, as follows:

JavaScript
function presentForm()
{
    var eleDiv; var eleForms;
    if (document.getElementById && document.getElementsByTagName)
    {
        eleDiv = document.getElementById("form");
        eleForms = eleDiv.getElementsByTagName("form");
    }
}

Collecting textareas and inputs

All forms contained within <div id="form"> are now assigned to the variable eleForms as an HTML object collection. The next step is to create collections of all the <input>s and <textarea>s in this <form>. We can do this by looping through all the <form>s contained within the <div id="form"> and creating more HTML object collections. We can use the getElementsByTagName command to assign the <input>s to the variable eleInputs and the <textarea>s to the variable eleTextAreas.

JavaScript
function presentForm()
{
  var eleDiv; var eleForms;
  if (document.getElementById && document.getElementsByTagName)
  {
      eleDiv = document.getElementById("form");
      eleForms = eleDiv.getElementsByTagName("form");
      for (var intCounter = 0; intCounter < eleForms.length; intCounter++)
      {
          eleInputs = eleForms[intCounter].getElementsByTagName("input");
          eleTextAreas = eleForms[intCounter].getElementsByTagName("textarea");
      }
  }
}

The presentForm() function is almost complete. Our next task is to actually do something with the <textarea> and <input> collections. We'll do this by passing the collections to a new function that will apply an onfocus() event to each item as follows:

JavaScript
function presentForm()
{
   var eleDiv; var eleForms;
   if (document.getElementById && document.getElementsByTagName)
   {
       eleDiv = document.getElementById("form");
       eleForms = eleDiv.getElementsByTagName("form");
       for (var intCounter = 0; intCounter < eleForms.length; intCounter++)
       {
           eleInputs = eleForms[intCounter].getElementsByTagName("input");
           eleTextAreas = eleForms[intCounter].getElementsByTagName("textarea");
           applyFunctionToFormElements(eleInputs);
           applyFunctionToFormElements(eleTextAreas);
       }
   }
}

Applying the onfocus() event

Next we create a new function called applyFunctionToFormElements(htmlObjectCollection) and loop through the object collection, ready to apply the onfocus() event:

JavaScript
function applyFunctionToFormElements(htmlObjectCollection)
{
    for (var intCounter = 0; intCounter < htmlObjectCollection.length; intCounter++) { }
}

Before applying the onfocus() event, we'll need to make sure it's not applied to the submit button. The submit button in the example provided has class="button" assigned to it which can be used to identify it. Next, we apply the onfocus() event to the remaining <input>s and <textarea>s.

JavaScript
function applyFunctionToFormElements(htmlObjectCollection)
{
    for (var intCounter = 0; intCounter < htmlObjectCollection.length; intCounter++)
    {
        if(htmlObjectCollection[intCounter].className != "button")
        {
            htmlObjectCollection[intCounter].onfocus = function () { }
        }
    }
}

Where it all happens!

Finally we've arrived at the exciting part! Let's use the onfocus() event to change the appearance of the page. We can set the classes of the form elements themselves, their siblings, parents or even grandparents. In this example, we'll change the <label> of the <input> to bold and the background colour of the containing <fieldset>. We'll enter the following code into the onfocus() function:

JavaScript
this.parentNode.parentNode.parentNode.className = "fieldsetHighlight";<
this.previousSibling.className = "labelHighlight"; 

The completed function should look like this:

JavaScript
function applyFunctionToFormElements(htmlObjectCollection)
{
    for (var intCounter = 0; intCounter < htmlObjectCollection.length; intCounter++)
    {
        if(htmlObjectCollection[intCounter].className != "button")
        {
            htmlObjectCollection[intCounter].onfocus = function () {
                this.parentNode.parentNode.parentNode.className = "fieldsetHighlight";
                this.previousSibling.className = "labelHighlight"; }
        }
    }
}

We've assigned a pink background to the fieldset <fieldset> using className="fieldsetHighlight" and a bold state to the label <label> using className="labelHighlight". Both of these are predefined classes contained within the CSS:

CSS
.fieldsetHighlight
{
border: 1px solid #d7b9c9; background: #f3e6ed; }
.labelHighlight
{
font-weight: bold; }

Clearing elements

If you click one of the <input>s or <textarea>s, then the background colour of the fieldset changes to pink and the label to bold.

However, what happens when you click on a second <input> or <textarea> in a different <fieldset>? The first <input> or <textarea> you clicked is still surrounded by the fetching pink but the second item you clicked is also highlighted and bold. The final task is to loop through the <label>s and <fieldset>s and set their colour and font weight back to normal, className="".

So we'll insert a new function call at the beginning of the onfocus() function called clearFieldsetsAndLabels(), as follows:

C#
function applyFunctionToFormElements(htmlObjectCollection)
{
    for (var intCounter = 0; intCounter < htmlObjectCollection.length; intCounter++)
    {
        if(htmlObjectCollection[intCounter].className != "button")
        {
            htmlObjectCollection[intCounter].onfocus = function () { clearFieldsetsAndLabels();
            this.parentNode.parentNode.parentNode.className = "fieldsetHighlight";
            this.previousSibling.className = "labelHighlight";
            }
        }
    }
}

We'll create the clearFieldsetsAndLabels() function and get all <label>s and <fieldset>s contained within <div id="form">:

JavaScript
clearFieldsetsAndLabels()
{
    var eleDiv; var eleFieldsets; var eleLabels;
    eleDiv = document.getElementById("form");
    eleFieldsets = eleDiv.getElementsByTagName("fieldset");
    eleLabels = eleDiv.getElementsByTagName("label");
}

We then need to pass each of the <fieldset> and <label> HTML object collections to a function that resets their class.

JavaScript
clearFieldsetsAndLabels()
{
    var eleDiv; var eleFieldsets; var eleLabels;
    eleDiv = document.getElementById("form");
    eleFieldsets = eleDiv.getElementsByTagName("fieldset");
    eleLabels = eleDiv.getElementsByTagName("label");
    clearEle(eleFieldsets) clearEle(eleLabels);
}

The final function loops through each of the elements in the HTML object collection and resets their class.

JavaScript
function clearEle(elements)
{
    for (var intCounter = 0; intCounter < elements.length; intCounter++)
    { elements[intCounter].className = ""; }
}

Conclusion

And that's it! A simple JavaScript solution that enhances the usability of your feedback forms using unobtrusive JavaScript. Check out this fully functioning example.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)