Hello there. I am Terry and I am a full-time undergraduate based in Singapore. I take photos, write a blog and design websites.

And no, I'm not a teddy bear.

Better Form Usability with jQuery

The <label> tag is a rather commonly omitted element in HTML forms. Although the tag does not render text in it differently from those outside the tag, it provides a usability improvement for mouse users by duplicating common GUI features. More importantly, it couples an input element with a label for users of speech browsers.

The <label> tag can be used as is, but it has an extremely useful attribute – the for attribute. This attribute allows one to associate a form control with the element, when its value matches the ID of the form control. Here’s a sample of a usable, but not the best, form, without the use of the <label> tag:

<form id="form-1">
	<p>
		<span>Name</span>
		<input type="text" name="author" tabindex="1" />
	</p>
	<p>
		<span>Email</span>
		<input type="text" name="email" tabindex="2" />
	</p>
	<p>
		<span>URL</span>
		<input type="text" name="url" tabindex="3" />
	</p>
	<p>
		<span>Comment</span>
		<textarea name="comment" tabindex="4" />
	</p>
	<p>
		<input type="submit" name="submit" tabindex="5" value="Submit" />
	</p>
</form>

When we add the the for attribute to the <label> element and assign it a value that is identical to the id attribute of the form control, we will improve the usability of the form. For visually-impaired users, the speech browsers are able to draw a link between a form control and it’s label, which will provide important information and even instructions in filling up the form. For those using visual browsers are, in turn, able to focus on a specific form control when its associated label is clicked on.

Here is the improved form:

<form id="form-1">
	<p>
		<label for="author">Name</label>
		<input type="text" name="author" tabindex="1" id="author" />
	</p>
	<p>
		<label for="email">Email</label>
		<input type="text" name="email" tabindex="2" id="email" />
	</p>
	<p>
		<label for="url">URL</label>
		<input type="text" name="url" tabindex="3" id="url" />
	</p>
	<p>
		<label for="comment">Comment</label>
		<textarea name="comment" tabindex="4" id="comment" />
	</p>
	<p>
		<input type="submit" name="submit" tabindex="5" value="Submit" />
	</p>
</form>

What does jQuery have to do with this?

You must be puzzled – afterall, what you need to do so far is to manually inject the for and id attributes into the <label> and <input> elements respectively. In fact, I was actually doing these manual changes to my theme files and other web-based projects because it will only take me at most a few minutes’ worth of time.

However, I recently faced a problem that I felt using jQuery as a workaround wasn’t a bad idea afterall. Many people would advice against using JavaScript in cases like this for two reasons: some users, albeit a minority, don’t allow JavaScript to run on their browser; and on a related note, with the possibility that JavaScript being disabled in mind, we shouldn’t use it to implement essential features.

The problem was that I was working with some WP plugins that generates HTML forms dynamically and on the fly. Although some would dive into the realm of PHP and make the necessary changes such that the generated forms are more user-friendly, I would prefer using the jQuery way, which is easier and does not require muddling with the source code of the plugin files.

There are a few steps that we have to do:

  1. Retrieve the value of the name attribute of the <input> element.
  2. Assign a unique ID to the <input> element.
  3. Assign the same value (the unique ID) to the for attribute of <label>.

For those copy-happy folks, here’s the code:

jQuery(function ($) {
 	$("#form-1 > p").each(function(count) {
		var input_id = $(this).children("input").attr("name") + (count + 1);
		$(this).children("input").attr("id", input_id);
		$(this).children("label").attr("for", input_id);
	});
});

Dissecting the code

$("#form-1 > p").each(function(count) {

This line searches the document for the paragraphy element, <p> that is a direct descendant of an element with an ID of #form-1. The .each() function makes sure that we look the subsequent function across all elements that satisfy the selection criteria. The count variable is declared and it will be used in each iteration.

var input_id = $(this).children("input").attr("name") + (count + 1);

This line defines the variable input_id, and assigns it the value of that is the that of the name attribute of the <input> element combined with a unique number. The number is increased by a value of 1 after each iteration of the loop so that we will generate unique IDs, even in face of an unprobably scenario that two input fields on the same page share the same value of the name attribute.

$(this).children("input").attr("id", input_id);
$(this).children("label").attr("for", input_id);

These two lines do the same thing – the finds the <input> and <label> elements in the same parent element, and assigns the generated value to the id of the former and for attribute of the latter.

Note

Note that this technique only works if each <label> and <input> pair is located in the same parent element, and each parent element has only one pair of label and input field in it. Of course, there is a solution for those forms that do not wrap each pair in a parent element, but I will not dwell into it.

Be Sociable, Share!

Burn after reading » Now you're done reading. What's next?

Related

Related posts that might interest you:

Popular

Posts that are popular among visitors: