jQuery tutorial: Text box hints

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.

87 Responses to “jQuery tutorial: Text box hints”

  1. @Ferdy – you’re right – that was some old code, though the link to the plugin was updated some time ago and it doesn’t actually use the selector to get the form. It uses this.form which I think is much more succinct :-)

    None the less, I’ll have to update the code in the tutorial – thanks!

  2. @Remy,

    Link to the plugin? Ahem, didn’t even see that. I just copied and pasted the code straight from this page to a new js file. My bad.

  3. Same issue with the password here in a typical login form. How can you make this work?

  4. @Remy

    Not sure if this is a bug, but it happens on your demo too:

    When you click the browser’s reload, the title becomes a “static” value rendering the function broken. I’m using FF 3.0.5 on MacOS 10.5.5

  5. Thanks for this — it was very useful. I ended up porting the logic to YUI 3, for use in an app.

  6. Clear the input value if it’s the same as title before submiting the form

    
    @@ -15,7 +15,7 @@
                 $win = $(window);
    
             function remove() {
    -            if (this.value === title && $input.hasClass(blurClass)) {
    +            if ($input.val() === title && $input.hasClass(blurClass)) {
                     $input.val('').removeClass(blurClass);
                 }
             }
    @@ -30,6 +30,7 @@
                 }).focus(remove).blur(); // now change all inputs to title
    
                 // clear the pre-defined text when form is submitted
    +            $form.bind("submit",remove);
                 $form.submit(remove);
                 $win.unload(remove); // handles Firefox's autocomplete
             }
    
  7. @FDisk – You don’t need the $form.bind('submit', remove); as it’s the same as $form.submit(remove); – otherwise, nice catch on the remove function – I’ll update the script.

  8. For those asking about how to do it for passwords, you can have an input type=”text” to begin with, and on focus you can switch it out for an input type=”password” and then if they don’t type stuff in it, go back to input type=”text” afterwards. we currently use this technique here: http://www.allyearbooks.co.uk/yearbooks … however, one downside is that now even if my browser ‘remembers’ the username or password, giving the hint means I need to type them both again every time :( any solution to this?

  9. I’m having the same problem as k00k; Firefox 3.0.6 Mac on OS X 10.5.6 will render the text in the box as regular selectable text (just as if it were the value already typed in the box) if you press “reload”. If you select that text, delete it, then click outside the box, the hint text reappears correctly. Hope this can be fixed, as I’ve started to use this code in several websites!

  10. Hey guys m getting error at following statement
    if ($input.val() === title && $input.hasClass(blurClass)) {

    Saying “The entity name must immediately follow ‘&’ in entity reference”

    I am trying above code in Visual web JSF. Please help me out.

  11. Hey,
    I still cannot make it work with jQuery 1.3.2
    I tried with the tutorial’s code above but still get an error like this:
    [Exception... "'Syntax error, unrecognized expression: )' when calling method: [nsIDOMEventListener::handleEvent]” nsresult: “0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)” location: “” data: no]

    Thanks,
    Michaël

  12. Hi Remy,

    are you planning to add a license for this code? That would make it easy for me to use it in my work :)

  13. Cilia Giampiero April 6th, 2009 at 10:10 am

    Hi Remy, thank you for the nice plugin. I’ve a problem with jquery-1.3.2-vsdoc2.js; the plugin have a little bug (Internet Explorer 7), because on load or on postback the hint text is not visible or disappear. Then, if you focus on the input control and then click out, the hint text appears. Any ideas? Thank you. Cilia Giampiero

  14. Hello – I noticed some blinking on my hints, so I changed the order of the addClass/val statement in the blur portion to this:

    $input.addClass(blurClass).val(title);

  15. I’ve problems with the input color. It remains gray even if I type in something.

  16. Very nice, but doesn’t seem to work in Safari 4 on Win if the title has a # in it. I have a title of “issue #” (less the quotes), and it doesn’t work unless I remove the #.

  17. Thanks for this article … it’s very helpful. In my formular i try to display help fields next to my textboxes. How can i get the location of an control to work with it?

    Help :|

  18. Great plugin. Unfortuantely, I cannot get it to work. I am not getting any errors at all and the code is there and is exactly like the code you have given, but there is no hint in my textbox. Now, the one thing that may be different here is that I am using WordPress site with a child theme, though I am not sure why that would make a difference, except for the way I am adding the code (dynamically) to the header – but you can see from the source code that it is there correctly. http://www.paradigmforward.com/

  19. nevermind…it was an easy fix. It turns out I was getting an error, which pointed me to the shortcut $ symbol. Turns out that in WordPress you cannot use the shortcut – so all I had to do was replace my two $ shortcuts with jQuery and it works perfectly. Thanks for the plugin – works great!

  20. Hi Remy,
    I took this plugin and added support for password fields. If someone is interested, take a look: http://github.com/nachokb/jquery-hint-with-password

    nachokb

  21. Thanks for this plug-in.

    If you try to use val() to get the value of an input that the user has not filled out (or worse, has blanked), it returns the hint text instead of an empty string. I’ve posted a tiny fix for this here: http://glyphobet.net/blog/essay/878 .

  22. Hi, great script!

    Been using this but its causing problems with my .Net validators when using an Ajax updatepanel as the values are not been cleared due to the form not being submited.

    Being new to jQuery not sure exactly whats happening – Is there some jQuery/javascript I can call before my my Ajax submit that would clear the values if they are the same as the hint?

    Many Thanks,

    Henry

  23. Here’s a small patch to handle ASP.NET link buttons:


    // Hack to allow the ASP.NET link buttons to work (http://softwareblog.morlok.net/2009/02/23/labelify-for-aspnet-11/)
    $("a[href^=javascript:__doPostBack]").click(remove);

  24. Hi Remi, thanks a lot for this script – makes everything look just that bit slicker!

    I’m having a bit of an issue with trying to change the contents of the title attribute on the fly. It seems as though once it’s initially set, it cannot be changed – I’ve even tried to remove the input box and re-call the hint() script.

    Any ideas?

    Thanks in advance

  25. First off, great script. I’m fairly new to Javascript and Jquery, and I’m trying to figure out how to add a reset button to my form that will clear all user inputted data and revert back to the input hints. Anyone have any ideas?

  26. Excellent work. However, I tried implementing this on my website and, it’s no doubt my lack of basic knowledge, but my test site now has boxes around every input field. Is there a way to limit the scope so that either no rectangular boxes are used or the input box only affects the form in which I desire the hint? Thanks a bunch.

  27. I’m having trouble with chrome when it is a username field. Safari and FireFox will display the username rather than the hinting, but chrome doesn’t. Any ideas?

  28. Great Plugin!!!

    Only problem i faced, if i call

    $('#username').hint()

    , it works in this case and later if i change the title to something else and call

    $('#username').hint()

    , it does not work.

    It shows the previous not the current title as a hint.
    Do you have any work around for it?

  29. Hi:
    When I use these two(jQuery.hint.js and jquery.img.preload.js) together, there are some conflict in the page.for example:the radio button,after i choose one ,the other isn’t work.the input text can’t fill in the space.Any ideas?

  30. Hi all,

    May I know is it possible to change the hint value in text box dynamically? after I have dynamically change the title text? If can , can anyone pls direct me? Thanks.

  31. I’m using your plugin with the jqm modal plugin, but cannot magage to make it work. When the div with the input field is shown, it is empty. If I click outside the field in the div, your plugin works. Maybe its a matter of focusing the field?…

  32. I have successfully given hints to the input boxes but the problem is when I am trying to validate input boxes, its taking the hint as the actual value.
    So i have hard coded the values..In place of
    value==”", i have given value=”E.G.John”
    Is it the correct way or is there anything else?

  33. I think it’s worth adding an additional focused class to this script, as the default ie behavior for tabbing into a text input is to highlight the existing text. With the value being cleared, there is no visual indication to the user what input they are in (there is no cursor indication). Adding a focused class allows you to style input.focus and add a different border color for example. You could also just use input:focus, but i think this is helpful for ie6/ie7 at least.

    
    	return this.each(function() {
    			var $input = $(this),
    				title = $input.attr('title'),
    				$form = $(this.form),
    				$win = $(window);
    
    			function remove() {
    				if ($input.val() === title && $input.hasClass(blurClass)) {
    					$input.val('').removeClass(blurClass).addClass('focused');
    				}
    			}
    
    			if (title) {
    				$input.blur(function() {
    					if (this.value === '') {
    						$input.val(title).addClass(blurClass).removeClass('focused');
    					}
    				}).focus(remove).blur();
    				$form.submit(remove);
    				$win.unload(remove); // handles Firefox autocomplete
    			}
    
    
  34. Cool tutorial!!

    I have embedded the scripts in my website and the people likes this. It’s a good help to show user what kind of information the input fields wants. Is there also a way to use this for textarea objects?

    - Thomas -

  35. Jonah Turnquist June 17th, 2011 at 7:03 pm

    Chrome fails to submit if any inputs have text longer than the maxlength. I had a problem where the input hint was larger than the maxlength, preventing Chrome from submitting. My solution was to set the maxlength to a large number when displaying the hint, and changing it back to the original number when not hinting.

  36. Hi Remy,
    Chrome and Safari have the same problem as Firefox with their autocomplete. However, the unload event doesn’t work in Chrome and Safari, so you need to use the beforeunload event instead. Here’s a patch:

    --- old/jquery.hint.js	Tue Dec 04 16:48:49 2012
    +++ new/jquery.hint.js	Tue Dec 04 16:49:20 2012
    @@ -36,7 +36,7 @@
    
           // clear the pre-defined text when form is submitted
           $form.submit(remove);
    -      $win.unload(remove); // handles Firefox's autocomplete
    +      $win.bind('beforeunload', remove); // handles autocomplete for Chrome, Firefox, and Safari
         }
       });
     };
    
    
  37. Cool this plugin is still popular.

    I need to be able to remove the blur class automatically whenever I update (add or remove) the input values programmatically via jQuery.

    When emptying the input, I think it works doing:

    $(“#myinput”).val(“”).blur( );

    But when filling an input:

    $(“#myinput”).val(“some text”)…….

    I didn’t manage to remove the blur class in a similar manner apart from invoking removeClass directly, it would require to do a full check on === title, and that’s bad.

    Any idea?

Leave a Reply
Not required

CODE: Please escape code and wrap in <pre><code>, doing so will automatically syntax highlight