Skip to content

Instantly share code, notes, and snippets.

@dncrht
Created May 11, 2016 15:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dncrht/769db568bd6d137a293c7ede7e32bf08 to your computer and use it in GitHub Desktop.
Save dncrht/769db568bd6d137a293c7ede7e32bf08 to your computer and use it in GitHub Desktop.
domainSuggestions is a jQuery plugin to show a list of domain suggestions for email fields
/**
*
* domainSuggestions shows a list of domain suggestions… for email.
*
* Inspired by autoEmail http://www.cxpartners.co.uk/cxblog/towards-an-easier-way-to-enter-email-addresses/
* which is based upon https://github.com/chrisyuska/auto-email
*/
(function($) {
function DomainSuggestions(settings) {
this.domains = settings.domains;
this.maxResults = settings.maxResults;
this.selectCallback = settings.selectCallback;
}
DomainSuggestions.prototype = {
call: function($el) {
this.$el = $el;
this.$suggestions = $('<ul class="domain-suggestions" style="display:none;"></ul>').insertAfter($el);
},
hide: function() {
this.$suggestions.hide();
},
select: function(domain) {
this.$el.val(domain);
this.$el.focus();
this.hide();
this.selectCallback(domain);
},
keyup: function(e) {
var $newHighlight;
switch (e.keyCode) {
case 13:
var $selected = this.$suggestions.find('.domain-suggestions_active');
this.select($selected.text());
break;
case 27:
this.$suggestions.empty();
this.hide();
break;
case 38:
$newHighlight = this.$suggestions.find('.domain-suggestions_active').prev();
$newHighlight.addClass('domain-suggestions_active');
$newHighlight.siblings().removeClass('domain-suggestions_active');
break;
case 40:
$newHighlight = this.$suggestions.find('.domain-suggestions_active').next();
$newHighlight.addClass('domain-suggestions_active');
$newHighlight.siblings().removeClass('domain-suggestions_active');
break;
default:
var exactMatches = [];
var errorMatches = [];
this.hide();
var emailsDirty = this.$el.val().split('@');
if (emailsDirty.length < 2 || emailsDirty[0] == "") {
return;
}
var emailDomain = emailsDirty[1];
if (emailDomain.length === 0) {
for (var i in this.domains) {
exactMatches.push(this.domains[i]);
if (i == (this.maxResults - 1)) {
break;
}
}
} else {
for (var i = 0; i < this.domains.length; i++) {
var testString = this.domains[i].substr(0, emailDomain.length);
if (emailDomain === testString) {
exactMatches.push(this.domains[i]);
} else if (this.getEditDistance(emailDomain, testString) < 2 && emailDomain.length > 1) {
errorMatches.push(this.domains[i]);
}
}
}
if (exactMatches.length > 0) {
this.$suggestions.empty();
for (var i = 0; i < exactMatches.length; i++) {
// take first domain match for autocomplete
var subStr = exactMatches[i].substr(emailDomain.length, exactMatches[i].length);
// insert exact match into list
this.$suggestions.append('<li>' + this.$el.val() + '<b>' + subStr + '</b></li>');
}
this.addListeners();
}
}
return false;
},
addListeners: function() {
var $results = this.$suggestions.find('li');
$results.first().addClass('domain-suggestions_active');
$results.mousedown(function(e) {
this.select($(e.currentTarget).text());
e.preventDefault();
}.bind(this));
$results.mouseenter(function() {
$(this).addClass('domain-suggestions_active');
$(this).siblings().removeClass('domain-suggestions_active');
});
this.$suggestions.show();
},
// Compute the edit distance between the two given strings
// http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
getEditDistance: function(a, b) {
if (a.length === 0)
return b.length;
if (b.length === 0)
return a.length;
var matrix = [];
var i;
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
var j;
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) == a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
} else {
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1,
Math.min(matrix[i][j - 1] + 1,
matrix[i - 1][j] + 1));
}
}
}
return matrix[b.length][a.length];
}
}
$.fn.domainSuggestions = function(options) {
// IE9+ only
if (!document.addEventListener) { // http://stackoverflow.com/a/18871780
return;
}
$(window).keydown(function(e) {
if (e.keyCode == 13) {
e.preventDefault();
e.stopPropagation();
}
});
var settings = $.extend({
domains: ['gmail.com', 'hotmail.com', 'yahoo.com'],
maxResults: 6,
selectCallback: function() {}
}, options);
var $this = $(this);
var domainSuggestions = new DomainSuggestions(settings);
domainSuggestions.call($this);
$this.keyup(domainSuggestions.keyup.bind(domainSuggestions));
$this.blur(domainSuggestions.hide.bind(domainSuggestions));
return this;
};
})(jQuery);
/*
Style (Sass)
.form-group
position: relative
.domain-suggestions
position: absolute
width: 100%
padding: 7px 9px
top: 78px
z-index: 7
list-style: none
background: $color-white
border: 1px solid $color-border-gray
border-top: none
border-radius: 3px
color: $color-gray
li
padding: 4px 0
cursor: pointer
.domain-suggestions_active
color: $color-blue
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment