Click here to Skip to main content
Click here to Skip to main content

Increasing form usability with JavaScript

, 13 Jan 2007
Rate this:
Please Sign up or sign in to vote.
It's easy to increase the usability of forms using JavaScript - find out how.

Introduction

Forms are used for the most important processes on websites. They are used to submit searches, purchase products, services, and provide feedback about the site. So why are they often dull, unusable, and uninspiring?

This article demonstrates how you can use unobtrusive JavaScript to improve the usability of your feedback forms.

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

The JavaScript

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.

We'll use the following 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:

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 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:

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.

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:

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:

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.

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:

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

The completed function should look like this:

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:

.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:

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">:

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.

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.

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)

About the Author

Paul Webcredible

United Kingdom United Kingdom
This article was written by Paul McCartny. Paul's crazy about CSS and using JavaScript for good (not evil) - so crazy that he works for Webcredible helping to make the Internet a better place for everyone. He knows an awful lot about DOM scripting & accessible JavaScript and accessible web design.

Comments and Discussions

 
GeneralYour working example link is broken PinmemberBrian Caldwell19-Jul-08 11:07 
GeneralBad Link PinmemberLeftend13-Jan-07 13:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140718.1 | Last Updated 13 Jan 2007
Article Copyright 2007 by Paul Webcredible
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid