jQuery tutorial: Text box hints(edit)

Updated March '08: I've separated the plugin to a separate jquery.hint.js file and included a fix to get around Firefox's autocomplete

You will see a lot of web sites with search boxes have text already populated inside of the field and when you select the input text box it disappears and reappears when it’s not selected.

This tutorial will show you how can add a small amount of jQuery to add this feature to any of your web sites.

The Goal

  1. To create a jQuery plugin.
  2. Show a ‘hint’ inside the input box when it is not in focus†† (aka blurred).
  3. Hide the hint when the text input has focus.

† The hint is what I am calling the text that appears and disappears within the input box.

†† Focus is the term (in this case) to indicate the user’s cursor is in the text field. Blurred is the opposite.

Demo

Our demo shows a input box for a finance web site that allows the user to search by company name or by the symbol (ticker).

See the demo in action

How it will work

  1. We are going to get the hint from the ‘title’ attribute of the input box.
  2. When the input box has focus we will hide the hint - only if the text in the input box matches the title attribute.
  3. When the input box is blurred, and it doesn’t contain any text, we will show the text again.
  4. If the input box is blurred and does contain text, we won’t do anything.

Unobtrusive JavaScript

The first step is to design the HTML so that it will work sensibly without JavaScript turned on, i.e. we’re not going to put our hint in the input box. Since we are planning to put the hint in the title tag we’re set to code.

The Code

HTML


<form action="">
    <div><label for="search">Search:</label>
    <input type="text" name="seach" value="" id="search" title="Company name or ticker" />
    <input type="submit" value="Go" />
    </div>
</form>

Pretty simple - nothing unexpected there.

jQuery Plugin

jQuery.fn.hint = function (blurClass) {
  if (!blurClass) { 
    blurClass = 'blur';
  }

  return this.each(function () {
    // get jQuery version of 'this'
    var $input = jQuery(this),

    // capture the rest of the variable to allow for reuse
      title = $input.attr('title'),
      $form = jQuery(this.form),
      $win = jQuery(window);

    function remove() {
      if ($input.val() === title && $input.hasClass(blurClass)) {
        $input.val('').removeClass(blurClass);
      }
    }

    // only apply logic if the element has the attribute
    if (title) { 
      // on blur, set value to title attr if text is blank
      $input.blur(function () {
        if (this.value === '') {
          $input.val(title).addClass(blurClass);
        }
      }).focus(remove).blur(); // now change all inputs to title

      // clear the pre-defined text when form is submitted
      $form.submit(remove);
      $win.unload(remove); // handles Firefox's autocomplete
    }
  });
};

Here’s a breakdown of some of what’s going on:

return this.each(function() {

Ensure we are applying the plugin to all the matched elements and allowing our plugin to be chained.

var $input = jQuery(this)

Creating a cached copy of the jQuery object so we can use jQuery’s functions for testing, without the overhead of continuously making new jQuery objects.

We're using a $ symbol as a prefix to the variable to give a visual que that the variable contains jQuery functions, rather than a plain DOM element.

$input.blur(function(){

When the element loses focus - execute the function that has been passed in. In our case, we are testing whether the field has been left blank, and if it has - we set it to the title attribute (cached earlier).

We are also adding a class called ‘blur’ to the input box so as to give the user the impression that the text that appears in the box has not been entered by them. Note that we remove this class when the element takes focus.

$input.blur()

We end up with a final call to the blur method - so that all the matched elements are set by default as blurred (i.e. with the title attribute appearing in the text already).

If you’re curious, you can read more about writing jQuery plugins.

Where to take it next

Within the plugin, you could add better validation to ensure we are only applying to input elements where type is ‘text’.

Update June '07: You can view and use the label over plugin for an accessible version of the 'text hints'

There are a couple of places you could look at to improve the plugin. The first that I can think of is to apply the label element to float inside the element (as seen on Digg’s search and explained over at A List Apart: Making Compact Forms More Accessible).

The second upgrade you could make would whether you can use this kind of plugin for a select input type. I haven’t thought it through, but it could be interesting.

Let me know if you have any comments or need to point out any errors.

Comments

comments powered by Disqus