Create an Input Hint - Exercise

Contact Us or call 1-877-932-8228
Create an Input Hint - Exercise

Create an Input Hint

Duration: 15 to 30 minutes.

Open the file ClassFiles/jqy-events/Exercises/index.html in your browser. Use the file ClassFiles/jqy-events/Exercises/js/inputHint.js. Your task is to use the text of the label for the search input to create "hint" text for the search input.

The concept here is that the page loads in a usable fashion, but, if the user has JavaScript enabled, we can improve their experience. If the user does not have JavaScript, the page still works acceptably.

  1. Set the value of the search input to the text of the label element.
  2. Add a class of hint to the search input.
  3. Remove the label element from the page (since our script now handles the hint, we will not need this element any more).
  4. Bind a focus event to the search input that removes the hint text and the hint class.
  5. Bind a blur event to the search input that restores the hint text and hint class.

Challenge

It's somewhat annoying that any text the user enters goes away when they leave the box. It would be nicer if we only replaced the value if it is different from the hint, or if the box is empty. As a challenge, revise the code so that the hint is only performed if the box is empty, and that the box is cleared only if the current text is the hint text.

As a second challenge, how could you set up a scenario where there were multiple text boxes in a form, and some subset of those should receive this treatment?

Solution:

jqy-events/Solutions/js/inputHint.js
$(document).ready(function() {
	var $search = $('#search');
	var $input = $search.find('input.input_text');
	var hint = $search.find('label').remove().text();

	$input
		.val(hint)
		.addClass('hint')
		.focus(function() { $(this).val('').removeClass('hint'); } )
		.blur(function() { $(this).val(hint).addClass('hint'); } );
});

This version is straightforward, but not very useful. We add a focus handler that empties out the text box and removes the hint class. A blur handler puts the hint back and adds the hint class. In this version, we used a closure to store the hint value.

Challenge Solution:

jqy-events/Solutions/js/inputHint-challenge1.js
$(document).ready(function() {
	var $search = $('#search');
	var $input = $search.find('input.input_text');
	var hint = $search.find('label').remove().text();

	$input
		.val(hint)
		.addClass('hint')
		.focus(function() {
			var entry = $input.val();
			$input.removeClass('hint');
			if (entry == hint) $input.val('');
		})
		.blur(function() {
			if (!$.trim($input.val())) $input.val(hint);
			if ($input.val() == hint) $input.addClass('hint');
		});
	}
);

In this version, we check the value in the text box before making any changes.

Challenge Solution:

jqy-events/Solutions/js/inputHint-challenge2.js
$(document).ready(function() {
	var $search = $('#search');
	var $input = $search.find('input.input_text');
	
	$input.each(function() {
		var hint = $search.find('label[for=' + this.name + ']')
			.remove()
			.text();
		var $this = $(this);
		
		$this
			.val(hint)
			.addClass('hint')
			.focus(function() {
				var entry = $this.val();
				$this.removeClass('hint');
				if (entry == hint) $this.val('');
			})
			.blur(function() {
				if (!$.trim($this.val())) $this.val(hint);
				if ($this.val() == hint) $this.addClass('hint');
			});		
	});
});

We have made the code more generalized by using the input_text class as a marker for text boxes to get this treatment. In an each loop, we build a find query by dynamically inserting the textbox name for the for attribute.

Challenge Solution:

jqy-events/Solutions/js/inputHint-challenge2a.js
// Uses one event handler and data to remember associated hint text
//  as opposed to an individual event with a closure for each item
$(document).ready(function() {
	var $search = $('#search');
	var $input = $search.find('input.input_text');
	$input.each(function() {
		var $label = $search.find('label[for=' + this.name + ']');
		var hint = $label.text();
		$label.remove();
		$.data(this, 'hint', hint);
		this.value = hint;
	});

	$input
		.addClass('hint')
		.focus(function(e) {
			$this = $(this);
			var entry = $this.val();
			$this.removeClass('hint');
			if (entry == $.data(this, 'hint')) $this.val('');
		})
		.blur(function(e) {
			$this = $(this);
			if (!$.trim($this.val())) $this.val($.data(this, 'hint'));
			if ($this.val() == $.data(this, 'hint')) $input.addClass('hint');
		});
	}
);

This is similar to the previous listing, except that we have used data instead of a closure. The key benefit is that we have moved the event handling setup out of the initial each loop, so that there is only one event handler function, as opposed to each item having its own customized handler function.

Next