Advertisement

Building a Mobile-Friendly Form with Email Domain Suggestion

by

This tutorial will teach you how to create a responsive web form which goes above and beyond setting <input type="email"> to help users enter email address information. This form will assist users (primarily mobile) by automatically suggesting popular email domains.


Introduction

Designing for mobile is becoming big in web design. With an ever increasing number of users accessing content from mobile devices, design methods such as responsive web design are becoming standard practices in improving usability.

The aim of this tutorial is to do precisely this — incorporate responsive web design techniques to improve a usability concern from a mobile perspective.

So, let's dive right in by first understanding the usability concern we are addressing.


The Problem

Let's face it, filling out forms on a mobile device can be frustrating. As a general rule of thumb, you could probably state that as the number of fields in your form increase, the likelihood that the user will actually complete the form decreases. Why? Because entering lots of information from a mobile device is simply more difficult than with a traditional desktop or laptop due to factors such as smaller and/or virtual keyboards.

Solving With Software

Mobile device makers recognize this problem with device input and have created software solutions to better assist users. For example, think of Apple's iPhone. Because the iPhone's keyboard is virtual, the characters it displays can change at any given time depending on context. So, developers can label an <input> element's type attribute and the keyboard will display characters relevant to the form field's requested data type.


As you can see, if you're entering just normal text, you get the standard keyboard. If you're entering an email address, the "@" symbol and the "." (period) become prominent. Or, if you need to enter a number, the keyboard will change to give you numbers first!

Understanding the Anatomy of an Email Address

Consider the anatomy of an email address — what does every email address have in common? Each email has three key parts:

  1. A username
  2. The "at" symbol (@)
  3. A domain
    1. Every domain has a period (.)

So, when users encounter a form field that asks for an email, we know that they will be required to use the @ symbol and a period, because those are common to every email address. That's why setting <input type="email"> assists users! It gives them easy access to the essential components of any email address.

Why Stop There?

It's possible we could provide a little more assistance to users entering their email address. A large percentage of users are using email domains that are very common. A quick Google search will show some of the most popular email domains are:

  • @aol.com
  • @hotmail.com
  • @gmail.com
  • @yahoo.com
  • and so forth

If a large portion of your user base is using the same email domain, why make them fill it out? What if we provided a kind of "auto suggestion" to the user as they filled out the email portion of the form? That way, as they began to type the "y" in "yahoo.com", they would get a suggestion saying "hey, are you trying to enter "yahoo.com"? If so, just tap here and we will fill in the rest for you!" This is all possible from a design perspective and that is what we are going to do in this tutorial.


Step 1: Getting Started With HTML

Let's get started by getting some basic HTML.

 
<!DOCTYPE html> 
<html> 
<head> 
	<title>Email Domain Autocomplete</title> 
</head> 
 
<body> 
	 
</body> 
</html>

Step 2: Adding the Dependencies

Now, let's add the links to the markup's dependencies. First we will include a link to Google's hosted version of jQuery as well as a link to "script.js" which will hold our javascript code we create later on. Let's put these right before the closing </body> tag.

 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> 
<script src="script.js" type="text/javascript"></script>

Let's also include a link to our CSS file (which we haven't created yet). You can put it in the <head> element.

 
<link href="styles.css" rel="stylesheet" />

Step 3: Designing Flexibly

Because this page will be responsive and flexible down to mobile, we must make sure to set the viewport so mobile devices render our page properly. If you want a more in-depth analysis of what this code is doing precisely, check out Ian Yates' article on the viewport meta tag. Otherwise, simply add this snippet of code in your <head> element.

 
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

Step 4: Creating the Container

Let's start by adding a main container and a description of what our page's purpose is:

 
<div id="container"> 
	<h1>Email Domain Auto-Suggest</h1> 
	<p>This form automatically suggests the popular email domain addresses. Although compatible on desktop computers, this feature is designed primarily for mobile devices. It will assist users who use popular email services such as gmail and hotmail.</p> 
</div>

Our basic markup looks like this:



Step 5: Creating the Form

Now let's insert the markup for our form. We will use an unordered list to help give structure and semantic meaning to our form.

 
<h2>Examples:</h2> 
<form> 
	<ul> 
		<li> 
			<label>Try @aol.com:</label> 
			<input type="email" id="aol" /> 
		</li> 
		<li> 
			<label>Try @gmail:</label> 
			<input type="email" id="gmail" /> 
		</li> 
		<li> 
			<label>Try @msn or @me:</label> 
			<input type="email" id="msn_me" /> 
		</li> 
		<li> 
			<button type="submit">Submit</button> 
		</li> 
	</ul> 
</form>

Note: Don't worry too much that we haven't given our <label> and <input> elements all the normal attributes. Since this tutorial will not be covering form handling and submission, we won't worry about that too much.

Another Note: Our markup for the actual domain suggestion will be injected using javascript, that's why we don't have it here.


Step 6: Page Structure With CSS

Let's start by giving our page some styles with CSS. First, we'll style the <body> element:

 
body { 
	background:#f6f6f6; 
	font: 16px/1.5em "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; 
	font-weight: 300; 
	margin:0; 
	padding:0; 
	color:#333; 
}

Here we set the background color and some defaults for our typography such as the type size, color, and line height. We also set a good font-stack of Helvetica for our body text.


Step 7: Going Responsive (Liquid)

We want our page to be flexible all the way down to mobile. So, the two key components we'll use to achieve this are: percentages and the max-width rule.

The Old Way (Fixed Width)

By looking at our HTML, you'll see <div id="container"> is the main container for our page's content. So, let's look at how we would do this traditionally:

 
#container { 
	margin:20px auto;  
	background:#fff; 
	width:500px; 
	padding:0 20px; 
	border:1px solid #c0c0c1; 
	border-bottom-color:#a8aaac; 
	border-top-color:#ccc; 
	box-shadow:0 1px 0 #dfe0e1; 
	border-radius:3px; 
}

We used CSS to add some basic styling. We also used a fixed width of 500px with some padding for our content and the margin: 0 auto centers our div in the middle of the page. The problem with setting the div's width at a fixed value (in pixels) is that when we get below our fixed width (500px) some of our content gets cut off:


The Better Way (Liquid Width)

To make our container flexible, we'll take out our fixed widths and use percentages instead. Here's the values we will add/change:

 
#container { 
	width:80%; 
	padding:0 5%; 
	max-width:500px; 
}

Here we set our container's width to be 80% of the browser's viewport with 5% padding on each side. You might be saying "but that only adds up to 90%!" and you're right! The other 10% is actually being used as a margin (5% on each side). We don't have to specifically set it because it's being determined by margin: 0 auto

Also, we added max-width:500px because we don't want our form ever being any bigger than that. So if someone has a 2100px browser window, our container div won't be 80% of that. Rather, it will just stop expanding at 500px! Cool no?


Now you can see how our content properly resizes according to screen size.


Step 8: Typographic Styling (CSS)

You probably noticed the <h1> type running over itself when the browser size gets small and the text goes to the next line. We'll fix that by adding a few typographic styles to our headers:

 
h1, h2 { 
	padding:10px 0px; 
	border-bottom:1px solid #eee;  
	padding-left:0; 
	font-weight:300; 
	line-height:1.1em; 
} 
h1 {color:#018ff3;}

Now you'll see it's starting to come together.



Step 9: Styling the Form (CSS)

Let's strip away the default list styling that's surrounding our form elements and give them some spacing:

 
ul { 
	list-style-type:none;  
	margin:0;  
	padding:0;  
	position:relative; 
} 
li { 
	margin:1.5em 0;  
	position:relative; 
}

Note We used relative positioning on the li element because our suggestion field will be positioned absolutely inside of it later on.

Now we will add some styling to our form and its fields:

 
form { 
	width:100%; 
	margin: 20px 0; 
} 
input { 
	display:block;  
	width:100%;  
	padding:0.3em 0.1em; 
	text-indent:5px; 
	border: 1px solid #e1e3e3; 
	border-bottom-color:#e5e5e6; 
	box-shadow: 0 -1px 0 #a7aaad; 
	border-radius:3px; 
	font-size:16px; 
	font-family:inherit; 
	box-sizing: border-box; 
    -moz-box-sizing: border-box; 
    -webkit-box-sizing: border-box;	 
}

You'll notice we set the <input /> fields with 100% width. With our additional padding, that will actually make the inputs extend beyond their parent container! To solve this, we use the box-sizing:border-box rule. This tells the browser to calculate the element's width at 100%, irrespective of any padding or borders it might have; thus making it always fit inside its parent container. To learn more about this property, see Ian Yates' article Encourage Responsive Form Elements to Play Nice

Now we've got a pretty decent looking form as far as structure and spacing!



Step 10: Submit Button Styling (CSS)

Now let's apply some styling to our submit button. We'll make it rather visually prominent as many submit or call to actions buttons are:

 
button { 
	width:80%; 
	max-width:300px;  
	display:block; 
	margin:20px auto; 
	border:1px solid #0c6eb3; 
	box-shadow:0 1px 0 #ced0d1, 0 1px 0px #8cd1fd inset; 
	padding:10px; 
	color:#fff; 
	font-weight:bold; 
	border-radius:3px; 
	background: #159efd; /* Old browsers */ 
	background: -moz-linear-gradient(top, #159efd 0%, #018ff3 100%); /* FF3.6+ */ 
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#159efd), color-stop(100%,#018ff3)); /* Chrome,Safari4+ */ 
	background: -webkit-linear-gradient(top, #159efd 0%,#018ff3 100%); /* Chrome10+,Safari5.1+ */ 
	background: -o-linear-gradient(top, #159efd 0%,#018ff3 100%); /* Opera 11.10+ */ 
	background: -ms-linear-gradient(top, #159efd 0%,#018ff3 100%); /* IE10+ */ 
	background: linear-gradient(top, #159efd 0%,#018ff3 100%); /* W3C */ 
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#159efd', endColorstr='#018ff3',GradientType=0 ); /* IE6-9 */ 
}

Here's a description of what we did here:

Button Size
We set the width at 80% which will work great at smaller sizes. But when it's in a desktop browser we don't want the button spanning the entire form. So, we used our handy max-width rule to tell the browser not to render the button wider than 300px.
Center
We set the display to block and gave it auto margins. This centers the button in the parent div.
Visual Styling
We added some visual styles using borders, box-shadows, etc. We also used the CSS3 background gradient feature. You can find excellent generators for this kind of code online.


Step 11: Creating the Suggestion Markup

At this point we've got a pretty nice looking form that works all the way down to mobile without even using media queries! Now we'll create the markup for the email domain suggestion and style it.

Remember, this markup is something we will insert with our javascript. So once we put it in our document and get it styled how we like it, we'll actually take it back out. Doing it this way is just easier for development purposes.

So let's insert a <span> element right after our <input /> element:

 
<span class="suggestion">test@gmail.com</span>


Step 12: Styling the Suggestion Field (CSS)

As you can see, our suggestion just looks like text right now. So, let's add some CSS styles so it will look more like a suggestion field:

 
.suggestion { 
	line-height: 1.2em; 
	font-weight:bold; 
	font-size:12px; 
	position:absolute; 
	top:-18px; 
	left:100px; 
	color:#fff;  
	border-radius:5px;  
	box-shadow:0 1px 0px #75797a inset, 0 1px 2px #555;  
	border:1px solid #000; 
	padding:8px 10px; /* must be same as li */ 
	background: #3a3e3f; /* Old browsers */ 
	background: -moz-linear-gradient(top, #3a3e3f 0%, #323637 50%, #292a2c 51%, #212224 100%); /* FF3.6+ */ 
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#3a3e3f), color-stop(50%,#323637), color-stop(51%,#292a2c), color-stop(100%,#212224)); /* Chrome,Safari4+ */ 
	background: -webkit-linear-gradient(top, #3a3e3f 0%,#323637 50%,#292a2c 51%,#212224 100%); /* Chrome10+,Safari5.1+ */ 
	background: -o-linear-gradient(top, #3a3e3f 0%,#323637 50%,#292a2c 51%,#212224 100%); /* Opera 11.10+ */ 
	background: -ms-linear-gradient(top, #3a3e3f 0%,#323637 50%,#292a2c 51%,#212224 100%); /* IE10+ */ 
	background: linear-gradient(top, #3a3e3f 0%,#323637 50%,#292a2c 51%,#212224 100%); /* W3C */ 
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3a3e3f', endColorstr='#212224',GradientType=0 ); /* IE6-9 */ 
}

Here's a description of what we did here:

Line Height
Giving our suggestion field a line-height rule rather than a height rule will center the text vertically in the box.
Positioning
As you can see, we used absolute positioning for our suggestion field. We offset it from the left a little and from the top so it doesn't cover the input field.
Visual Styling
We added some visual styles using borders, box-shadows, etc. We also used the CSS3 background gradient feature (as we did earlier on the button element).


Step 13: Suggestion Field Popover Styles (CSS)

Now we have the suggestion field all styled, but we want to make it appear like a suggestion over the input field. We'll use a little triangle to accomplish this. To make the field appear clickable, we'll also make sure the hover state shows the field as being clickable:

 
.suggestion:hover {cursor:pointer;} 
.suggestion::after { 
	content: "\25BC"; 
	font-size:12px; 
	position:absolute; 
	bottom:-10px; 
	left:50%; 
	color:#000; 
}

The triangle could be added using images, but we did it using pure CSS. Because we're using a pseudo selector, we have to use the triangle's corresponding escaped unicode since we're using the content:"" rule. Then we just use positioning to get it where we want it.


Now we have something like this:



Step 14: Adding the Suggestion Field Hover/Active States (CSS)

Now we want to add a little interactivity to our suggestion field. We'll make a hover and active state by simply coloring the background. This will make sure we tell the user they can and have interacted with the field.

 
.suggestion:active, .suggestion:hover { 
	background: #34abe8; /* Old browsers */ 
	background: -moz-linear-gradient(top, #34abe8 0%, #007fd1 100%); /* FF3.6+ */ 
	background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#34abe8), color-stop(100%,#007fd1)); /* Chrome,Safari4+ */ 
	background: -webkit-linear-gradient(top, #34abe8 0%,#007fd1 100%); /* Chrome10+,Safari5.1+ */ 
	background: -o-linear-gradient(top, #34abe8 0%,#007fd1 100%); /* Opera 11.10+ */ 
	background: -ms-linear-gradient(top, #34abe8 0%,#007fd1 100%); /* IE10+ */ 
	background: linear-gradient(top, #34abe8 0%,#007fd1 100%); /* W3C */ 
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#34abe8', endColorstr='#007fd1',GradientType=0 ); /* IE6-9 */ 
	box-shadow:0 1px 0px #83c7f0 inset, 0 1px 2px #555; 
	border:1px solid #0075c0; 
	border-left-color:#0168a9; 
	border-right-color:#0168a9; 
	border-bottom-color:#014773;  
}

We have to make sure that we change the little triangle's color as well!

 
.suggestion:active::after, .suggestion:hover::after { 
	color:#0075c0; 
}

Now we have something that looks like this:


Congrats! Now we are all finished with the HTML/CSS markup. Now we just need to add the javascript interactivity!

Note: Don't forget to remove the <span> element now. We'll insert it using jQuery later on.


Step 15: Understanding the Interactive Aspect

Before we actually dive into writing our domain suggestion script, let's make sure we outline and understand what we are trying to accomplish.

Creating the Email Domain Stack

What we want our script to do is detect if the user is trying to enter an email domain that matches some of the more popular email services on the web. A quick Google search will reveal that the following are some of the most used email service domains on the web:

  • @aol.com
  • @comcast.net
  • @gmail.com
  • @hotmail.com
  • @me.com
  • @msn.com
  • @yahoo.com

Obviously you could add/subtract as many email domains to this list if you want, but this is a good start for what we're trying to accomplish.

Suggesting a Domain

So what if the user is trying to enter one of these domain addresses? Then we will use our script to suggest it! This will allow the user to simply click/tap on the suggestion and have the desired email domain appended to what they have already entered. If it is not what they want, they can simply ignore the suggestion.


Step 16: Setting up jQuery

Let's create our "script.js" file and start off with the following code to implement jQuery:

 
$(document).ready(function() { 
	//script code will go here 
});

Step 17: Adding the Suggestion Box to the DOM

If you remember, we inserted a <span> element with a class of "suggestion" after each input element and styled it just how we wanted our suggestion boxes to appear. Once we styled it correctly, we removed the markup from our HTML

Well, now we are going to insert that markup using jQuery. We will use the insertAfter() method:

 
$('<span class="suggestion"></span>').insertAfter('input[type=email]').hide();

This line of code will find every input element on the page that has an attribute of "type=email" (which is used on each of our input elements). It then inserts the markup we specified (<span class="suggestion"></span>) after each element (hence the name). Then we hide all occurrences of the suggestion box (because we have nothing to suggest yet!)

Adding it with javascript works well because it's markup that only needs to be there IF the user has javascript enabled on their computer.


Step 18: Catching the User's Input Value

In order to determine which email domain to suggest, we need to know what value the user is entering. So we need to watch the input field that's in focus and every time the user presses a key on the keyboard we'll catch the new input value and store it in a variable.

We can find out what the user is entering by using the keyup() event. By attaching keyup to each input element, we can trigger our script to get the value on the input field each time a new character is entered.

 
$("input[type=email]").keyup(function () { 
	var value = $(this).val(); 
});

So now every time the user adds another character to the input field, jQuery will grab the value and store it in the "value" variable.


Step 19: Checking for the @ Symbol

Now the user's input is being stored in the "value" variable. However, we don't really care what their email username is. If our value variable equals "joe" that doesn't help us because we don't know what domain the user is trying to enter. But, if our value variable equals "joe@a" then we can guess that maybe the user is trying to enter "joe@aol.com" and we can suggest "@aol.com".

So, what we want to do is check the value variable on each keyup() event and see if it contains a "@" symbol. If it does have an "@" symbol, we know the user is ready to enter in their email domain address.

So we are going to store the position of the "@" symbol in a variable for use later. We will do this using the indexOf() method. We simply create a new variable (a_pos) and set it equal to the index value of the "@" in the value variable.

 
var a_pos = value.indexOf('@'); // value will default to -1 if not entered

Note that if the "@" symbol hasn't been entered yet, our variable a_pos will default to a value of -1. Otherwise, we get the character's position in the string.


Step 20: Storing the Parent Element for Context

We also want to store the parent element of whatever input element is in focus by the user. This will be useful when we show our suggestion markup because we won't want to show all of the suggestion boxes on the page. Rather, we will only show the one that is in focus (more on this later).

 
var parent =  $(this).parent();

Step 21: Suggesting an Email Domain

Now we have everything in place to see if the user is actually entering an email address! So what we'll do now is setup an if/else statement.

If the "a_pos" variable has a value of -1 we know that the user hasn't entered the "@" symbol yet. If it has any other value, we know that the "@" symbol has been entered. So let's setup the following if/else:

 
if (a_pos != -1) {  
	// @ has been entered 
} else { 
	// @ has not been entered yet 
}

Predicting a Domain

If the '@' symbol has in fact been entered, we want to check and see what the character AFTER the @ symbol is. If it's a "g" we could suggest "gmail.com" to the user. If it's a "y" we could suggest "yahoo.com" and so forth.

So we're going to stick this in our "if" statement from above:

 
if ( value[a_pos+1] == 'a' ){ 
	$('.suggestion', parent).text('aol.com').show(); 
}

This code is saying "if the first character value AFTER the position of the '@' symbol is equal to 'a', then suggest 'aol.com' to the user."


Note: You'll notice we are selecting the .suggestion class. Because we have multiple 'suggestion' classes, this will select every 'suggestion' class on the page, which we don't want. This is why we set the 'parent' variable and use it as our selector's context: $('.suggestion', parent). jQuery will now only select items with a class of 'suggestion' in the context of the focused input field's parent!


Step 22: Completing all Email Domain Suggestions

Now that we have the code to suggest email domains, we just need to test for other values, such as 'g' for 'gmail.com' and 'y' for 'yahoo.com'. Since we're using an if statement, let's append all the other domain address suggestions using an else if statement.

So, let's add one for 'comcast.net':

 
else if ( value[a_pos+1] == 'c' ){ 
	$('.suggestion', parent).text('comcast.net').show(); 
}

Now one for 'gmail.com':

 
else if ( value[a_pos+1] == 'g' ){ 
	$('.suggestion', parent).text('gmail.com').show(); 
}

Now one for 'hotmail.com':

 
else if ( value[a_pos+1] == 'h' ){ 
	$('.suggestion', parent).text('hotmail.com').show(); 
}

Now one for 'live.com':

 
else if ( value[a_pos+1] == 'l' ){ 
	$('.suggestion', parent).text('live.com').show(); 
}

Now one for 'yahoo.com':

 
else if ( value[a_pos+1] == 'y' ){ 
	$('.suggestion', parent).text('yahoo.com').show(); 
}

Suggesting Domains Whose First Letters Match

Now we want to suggest 'msn.com' and also 'me.com'. Both start with 'm' so we will do a nested if/else statement. We're going to assume 'msn.com' is the more widely used domain address, so we will suggest it first:

 
else if ( value[a_pos+1] == 'm' ){ 
	if ( value[a_pos+2] == 'e' ){ 
		$('.suggestion', parent).text('me.com').show(); 
	} else { 
		$('.suggestion', parent).text('msn.com').show(); 
	} 
}

This piece of code is saying "if the character AFTER the '@' symbol is 'm' then run the code inside". The code inside is saying 'if the SECOND character AFTER the '@' symbol is 'e' then suggest 'me.com'. Otherwise, suggest 'msn.com'.

What if There Are No Matches?

What if the user enters something like "john@z"? We don't have any email domain suggestions that start with the letter 'z'. So, at the end of our if/else if statements, we will put an else statement that hides the suggestion box. This basically says "if there are no suggestions matching what the user has entered, hide the suggestion box."

 
else { //if none match, hide the tooltip 
	$('.suggestion', parent).hide(); 
}

Step 23: Closing the a_pos if/else Statement

If you remember from earlier, we had an if/else statement like this:

 
if (a_pos != -1) {  
	// @ has been entered 
} else { 
	// @ has not been entered yet 
}

We have put in all the email domain suggestions IF there is an '@' symbol that has been entered. If the '@' symbol has not been entered, we will simply hide the suggestion box.(This means if the user types "john@y", the "yahoo.com" suggestion box will pop up. But, if the user hits the delete key the suggestion box will disappear).

 
else { 
	$('.suggestion', parent).hide(); 
}

Our Entire Keyup Code

So, our entire block of code for when a user makes a keystroke looks like this:

 
// Every keyup watches for the entering of a domain 
$("input[type=email]").keyup(function () { 
 
	// We need to define the following variables 
	//		1. Define the parent element. We use this in selecting the context of the input[type=email] in focus 
	//		2. Get the current input value 
	//		3. Get the position of the '@' symbol 
	 
	var parent =  $(this).parent(); 
	var value = $(this).val(); 
	var a_pos = value.indexOf('@'); // value will default to -1 if not entered 
	 
	// If the @ symbol has been entered, execute the suggested function			 
	if (a_pos != -1) {  
		 
		// If the character AFTER the '@' symbol matches any of the following email domains, suggest them 
		if ( value[a_pos+1] == 'a' ){ 
			$('.suggestion', parent).text('aol.com').show(); 
		} 
		else if ( value[a_pos+1] == 'c' ){ 
			$('.suggestion', parent).text('comcast.net').show(); 
		} 
		else if ( value[a_pos+1] == 'g' ){ 
			$('.suggestion', parent).text('gmail.com').show(); 
		} 
		else if ( value[a_pos+1] == 'h' ){ 
			$('.suggestion', parent).text('hotmail.com').show(); 
		} 
		else if ( value[a_pos+1] == 'm' ){ //  "msn" is more popular, so it is the default suggestion for just the letter 'm' 
			if ( value[a_pos+2] == 'e' ){ 
				$('.suggestion', parent).text('me.com').show(); 
			} else { 
				$('.suggestion', parent).text('msn.com').show(); 
			} 
		} 
		else if ( value[a_pos+1] == 'l' ){ 
			$('.suggestion', parent).text('live.com').show(); 
		} 
		else if ( value[a_pos+1] == 'y' ){ 
			$('.suggestion', parent).text('yahoo.com').show(); 
		} 
		else { //if none match, hide the tooltip 
			$('.suggestion', parent).hide(); 
		} 
		 
	} else { 
		$('.suggestion', parent).hide(); 
	} 
});

If you test this in the browser, you'll see suggestions appear according to the email domain address you attempt to enter. Clicking on them won't actually do anything though — that's our next step!



Step 24: Appending the Suggested Email Domain

So what happens if the user clicks on one of our email domain suggestions? We need to append the suggested domain to whatever they have entered so far.

So, for example, let's say the user has entered "john@a". That will trigger the "aol.com" domain suggestion to appear. If the user clicks that suggestion, we want to save them the effort of typing the rest of the address and append it to whatever they've entered so far. So the input field's value will go from "john@a" to "john@aol.com"!

To accomplish this, we will need to watch for when a user clicks on a suggestion box. So let's have jQuery watch for that:

 
$('.suggestion').click(function() { 
	//code here if user clicks on the suggestion box			 
});

Step 25: Declaring the Variables We'll Need

In order to properly append the suggested email domain the user selects, we'll need some variables.

Parent Context

First we'll need to select the parent of whatever suggestion box was clicked on. Once again, this will be used for making selections in context of the input field that is in focus.

 
var parent = $(this).parent();

The Email Domain Suggestion

We need to know what the actual suggestion is that we are making to the user. So for example, if we are suggesting "aol.com", let's store that value in a variable. Since we are inside the currently clicked suggestion box, we'll use jQuery's $(this) and text() method to get the value of whatever is being suggested.

 
var suggested_val = $(this).text();

The User's Current Input Value

We need to know what the user has entered so far. So, if they have entered "john@a", we'll store that value in a variable. This is where we use the parent variable we set earlier for selection context (since we don't want to select all occurrences of the 'suggestion' class, we only want the one that was clicked on).

 
var input_val = $('input[type=email]', parent).val();

Position of the '@' Symbol

Once again we need to know the position of the '@' symbol in the string the user has entered. So we'll use the indexOf method we used earlier. This will check the input_val variable (what the user has entered so far) and look for the position of the '@' symbol.

 
var a_pos = input_val.indexOf('@');

Email Username

If the user clicks on "aol.com" we know that their email domain is "@aol.com". So we have to get everything they've entered BEFORE the '@' symbol. That is their email username. Once we have that value, we can append the suggested email domain to it.

To do this we'll create a variable called before_a and set it equal to the result of the substr method.

The substr method is used on the input_val variable (the user's currently entered value in the input field). It will extract the characters from a string, beginning and ending at the parameters we specify.

 
var before_a = input_val.substr(0, a_pos);


Step 26: Appending the Suggestion

Now that we have all our variables in place, we can append the suggested email domain the user clicked on. We'll do this by selecting the input box they are focused on (we can do this in the context of it's parent, as explained before) and then setting the input's value using the variables we setup:

 
$('input[type=email]', parent).val(before_a+'@'+suggested_val);

This sets the input's value to whatever the user had entered up until the '@' symbol, the '@' symbol itself, and then the suggested email domain they clicked on.

Don't forget to hide the suggestion box once the user clicks on it:

 
$(this).hide();

For a more visual representation of what we've done here, check out this image:


Our Entire Code for Appending the Suggested Email Domain

 
$('.suggestion').click(function() { 
 
	// Define the following variables: 
	// These will be used to concatenate the suggested email domain to whatever the user has entered thus far: 
	//		1. Email domain suggestions  
	//		2. Current input value from user 
	//		3. Position of the '@' symbol 
	//		4. Current value before the '@' symbol 
	 
	//		Also get the parent element for context of input[type=email] 
	var parent = $(this).parent(); 
	var suggested_val = $(this).text(); //currently suggested email domain 
	var input_val = $('input[type=email]', parent).val(); //current input value by user 
	var a_pos = input_val.indexOf('@'); //position of '@' symbol in input value 
	var before_a = input_val.substr(0, a_pos); //value of email address before '@' symbol 
	 
	 
	 
	// Concatenate the suggested email domain to the current value suggested by the user 
	$('input[type=email]', parent).val(before_a+'@'+suggested_val); 
	$(this).hide();			 
});

Step 27: Hiding the Suggestion Box

What if the user is typing in an email address and doesn't use the email domain suggestion we provide? When they click outside the input field (blur event) we need to hide the suggestion, as it's no longer relevant. So we'll do that using the following code:

 
$('input[type=email]').blur(function() { 
	$('.suggestion').hide(); 
});

However, there's a problem with this. If the user clicks on the suggestion, not only will that fire the $('.suggestion').click function, but it will also fire the $('input[type=email]').blur function (since the suggestion box is outside the input element). This will result in our suggested email domain not actually being appended. So we'll have to fix this.


Step 28: Hiding the Suggestion Box: A Fix

We can solve this problem by tracking mouse events on the suggestion box using a boolean variable.

We'll create a variable called "mouseOver". It's pretty self-explanatory. If the user hovers over the suggestion box, we'll set its value to "true". If they mouseout (or don't hover over the suggestion box) the "mouseOver" variable will be reset to false (it's default value).

 
var mouseOver = false; 
$('.suggestion').mouseover(function() {  
	mouseOver = true;  
	}) 
.mouseout(function() { 
	mouseOver = false;  
});

Adjusting the Function That Hides the Suggestion Box

Now that we'll know if the user is actually hovering over the suggestion box and is about to click on it, we'll adjust the code from the previous step:

 
$('input[type=email]').blur(function() { 
	if ( !(mouseOver) ){  
		$('.suggestion').hide(); 
	} 
});

What We've Done

The idea here is discovering the user's intent. If they are hovering over the suggestion box, we know they plan on clicking on it. But, if they aren't hovering over it, and then click outside the input field (blur) we can execute the code to hide the suggestion box, because we know the user wasn't planning on clicking on it!

So now our code for hiding the suggestion box should look like this:

 
// we need to track mouse events on the suggestion field. If the user is hovering over the suggestion,  
// 		it will execute the insert_suggestion 
//		otherwise, on mouseout it will hide the suggestion  
var mouseOver = false; //default state is false 
$('.suggestion').mouseover(function() {  
	mouseOver = true;  
	}) 
.mouseout(function() { 
	mouseOver = false;  
}); 
 
 
//hide suggestion when field is out of focus 
$('input[type=email]').blur(function() { 
	if ( !(mouseOver) ){  
		$('.suggestion').hide(); 
	} 
});

Step 29: Our Final Complete Code

Our final javascript code, with commenting, now looks like this:

 
$(document).ready(function() { 
	 
	// Insert the <span> tag. This will be the suggestion box  
	$('<span class="suggestion"></span>').insertAfter('input[type=email]').hide(); 
	 
	// Every keyup watches for the entering of a domain 
	$("input[type=email]").keyup(function () { 
	 
		// We need to define the following variables 
		//		1. Define the parent element. We use this in selecting the context of the input[type=email] in focus 
		//		2. Get the current input value 
		//		3. Get the position of the '@' symbol 
		 
		var parent =  $(this).parent(); 
		var value = $(this).val(); 
		var a_pos = value.indexOf('@'); // value will default to -1 if not entered 
		 
		// If the @ symbol has been entered, execute the suggested function			 
		if (a_pos != -1) {  
			 
			// If the character AFTER the '@' symbol matches any of the following email domains, suggest them 
			if ( value[a_pos+1] == 'a' ){ 
				$('.suggestion', parent).text('aol.com').show(); 
			} 
			else if ( value[a_pos+1] == 'c' ){ 
				$('.suggestion', parent).text('comcast.net').show(); 
			} 
			else if ( value[a_pos+1] == 'g' ){ 
				$('.suggestion', parent).text('gmail.com').show(); 
			} 
			else if ( value[a_pos+1] == 'h' ){ 
				$('.suggestion', parent).text('hotmail.com').show(); 
			} 
			else if ( value[a_pos+1] == 'm' ){ //  "msn" is more popular, so it is the default suggestion for just the letter 'm' 
				if ( value[a_pos+2] == 'e' ){ 
					$('.suggestion', parent).text('me.com').show(); 
				} else { 
					$('.suggestion', parent).text('msn.com').show(); 
				} 
			} 
			else if ( value[a_pos+1] == 'l' ){ 
				$('.suggestion', parent).text('live.com').show(); 
			} 
			else if ( value[a_pos+1] == 'y' ){ 
				$('.suggestion', parent).text('yahoo.com').show(); 
			} 
			else { //if none match, hide the tooltip 
				$('.suggestion', parent).hide(); 
			} 
			 
		} else { 
			$('.suggestion', parent).hide(); 
		} 
	}); 
	 
	 
	 
	// Add the domain to the currently entered value 
	$('.suggestion').click(function() { 
	 
		// Define the following variables: 
		// These will be used to concatenate the suggested email domain to whatever the user has entered thus far: 
		//		1. Email domain suggestions  
		//		2. Current input value from user 
		//		3. Position of the '@' symbol 
		//		4. Current value before the '@' symbol 
		 
		//		Also get the parent element for context of input[type=email] 
		var parent = $(this).parent(); 
		var suggested_val = $(this).text(); //currently suggested email domain 
		var input_val = $('input[type=email]', parent).val(); //current input value by user 
		var a_pos = input_val.indexOf('@'); //position of '@' symbol in input value 
		var before_a = input_val.substr(0, a_pos); //value of email address before '@' symbol 
		 
		 
		 
		// Concatenante the suggested email domain to the current value suggested by the user 
		$('input[type=email]', parent).val(before_a+'@'+suggested_val); 
		$(this).hide();			 
	}); 
	 
	 
	// we need to track mouse events on the suggestion field. If the user is hovering over the suggestion,  
	// 		it will execute the insert_suggestion 
	//		otherwise, on mouseout it will hide the suggestion  
	var mouseOver = false; //default state is false 
	$('.suggestion').mouseover(function() {  
		mouseOver = true;  
		}) 
	.mouseout(function() { 
		mouseOver = false;  
	}); 
	 
	 
	//hide suggestion when field is out of focus 
	$('input[type=email]').blur(function() { 
		if ( !(mouseOver) ){  
			$('.suggestion').hide(); 
		} 
	}); 
 
});

Congratulations! You've created a responsive web form that assists users with popular email domain addresses. There are some enhancements that could be made to this script. For example, what if the user enters "john"@microsoft.com"? The "@msn.com" suggestion will actually appear until they are not focused on the input field anymore. You could add a line of code that hides the suggestion if the user doesn't click on it within a certain amount of characters. For example, if they type, "john @micro", we can assume they don't want to use the suggestion we've provided. At that point, we could hide our suggestion.

Play around with the script and HTML and see what additions you could make to improve the user experience of filling out forms!

Advertisement