I recently stumbled across mailcheck.js, a little jQuery plugin from Kicksend that suggests domains based on common typos in email forms. For example, 'user@gnail.co' will generate a suggestion for 'user@gmail.com'. It's perfect for preventing errors in user signups, and the authors claim its reduced their email bounces by 50%. After playing around with it, I've decided to bundle it into production for most, if not all of my projects, and this is just a brief demo of what can be done with it.

Getting Set Up

Our goal is to create a simple display that shows email suggestions to the user and offers a way to automatically fill in the field with the suggestion. The plugin is used in two steps - first, it has to be attached to a text field, and then you have to actually do something with its suggestions. Let's get the basic JavaScript structure set up (make sure you include the actual plugin on your page as well!)

<!-- The HTML -->
<input id="email" type="text" placeholder="Email">
<div id="hint"></div>


// The JavaScript
var $email = $('#email'); // Cache jQuery objects into variables
var $hint = $("#hint");

$email.on('blur', function() {
  $(this).mailcheck({
    suggested: function(element, suggestion) {

    }
  });
});

The setup is only a few lines, although it's important to understand what's going on. Our HTML is fairly straightforward - we start with a generic input that we'll be using the plugin on. The <div id="hint"> is an initially hidden div that will contain our suggestions to the user. In our JavaScript, we're first sticking jQuery objects into variables for convenience. Then we're attaching the mailcheck() function to our email field on its blur event, which is called whenever the element loses focus (i.e., the user moves on to the next field). Mailcheck takes two callbacks, suggested() and empty(). suggested() is called whenever a suggestion is available for the field, and empty() whenever the field is left blank. We'll only be using suggested() in this demo, although depending on how you use the plugin it's generally a good idea to use both.

Using the suggestion object

Mailcheck automatically generates our field suggestions for us, but how do we use them? Note that the suggested() method from before is passed in two parameters - element, which is the field that we're checking, and something called suggestion. If you enter user@gnail.co and use your favorite tool to inspect it, you'll notice it's an object with three fields:

The mailcheck suggestion object

We have access to the address (what comes before the @), the suggested domain, and the entire suggested text. We can use these fields to populate and show a hint to the user using the previously mentioned <div id="hint">. Here's how you could go about filling the hint element:

var $email = $('#email');
var $hint = $("#hint");

$email.on('blur',function() {
  $hint.css('display', 'none'); // Hide the hint
  $(this).mailcheck({
    suggested: function(element, suggestion) {
      if(!$hint.html()) {
        // First error - fill in/show entire hint element
        var suggestion = "Yikes! Did you mean <span class='suggestion'>" +
                          "<span class='address'>" + suggestion.address + "</span>"
                          + "@<a href='#' class='domain'>" + suggestion.domain + 
                          "</a></span>?";
                          
        $hint.html(suggestion).fadeIn(150);
      } else {
        // Subsequent errors
        $(".address").html(suggestion.address);
        $(".domain").html(suggestion.domain);
      }
    }
  });
});

Before we do anything with the suggestion, we're making sure to hide the hint element. If there's a suggestion, we'll be repopulating it with the suggested domain, but this handles the case that a valid email is entered after we've already suggested a hint. At the beginning of the suggested() callback, we're checking to see if the hint element is empty (if (!$hint.html()) {...}). If so, then we can assume it's the user's first error. The suggestion variable is a rather nasty string of HTML that we'll be inserting into the hint element. There are other ways of doing this such as template systems or DOM libraries, but this is a quick and dirty solution. On the first error, we first fill in the hint with our suggestion ($hint.html(suggestion)) and fade it in by chaining it to jQuery's fadeIn method. On subsequent errors, instead of fading in the hint, all we have to do is modify its contents to reflect the new contents of the field. At this point, we should have a working hint!

Email suggestion to the user

At this point, we're missing the last piece of the puzzle - I've styled the domain to look like an inviting link, but clicking it doesn't actually do anything. It should be a link automatically fill in the suggestion for you - let's implement it!

// After our other code:
$hint.on('click', '.domain', function() {
  // On click, fill in the field with the suggestion and remove the hint
  $email.val($(".suggestion").text());
  $hint.fadeOut(200, function() {
    $(this).empty();
  });
  return false;
});

The code is much shorter for this bit - we're using jQuery's on() method to attach a click handler to the .domain link. All we're doing is filling in the field with the suggestion text, and fading out the hint, emptying it when it's complete. And that's it! We have a fully functional hint element that displays suggestions to the user and provides a link to automatically fill the suggestion into the field. Be sure to grab the plugin here!