I recently had to develop a suggestion feature for an input-field where the first best match would be filled in and the rest of the word selected so that the user can continue writing if that’s not the correct word. At first this seemed like a straight-forward solution but then I realized that to select text programmatically in the document isn’t exactly straight forward (neither is searching inside an array, but that’s another story).
The reason that it isn’t straight-forward is that like som many other features of web technology it’s implemented in different same ways in Internet Explorer as it is in the rest of the major (and W3C compliant) browsers.
I started by first creating a function that actually selects a part of an input field that is given as an element and then the start and end position, this is straight JavaScript
function selectPartOfInput(el, startPos, endPos) {
if (typeof el.selectionStart != "undefined") {
// W3C compliant browsers -> Selection object
el.selectionStart = startPos;
el.selectionEnd = endPos;
} else if (document.selection && document.selection.createRange) {
// Internet Explorer -> Microsoft Text Range
el.focus();
el.select();
var r = document.selection.createRange();
r.moveEnd("character", endPos);
r.moveStart("character", startPos);
r.select();
}
}
Implementing it for a suggestion solution bound to an input field using jQuery could look like the example below. It starts by creating a string from the array containing our suggestions, this string can then be searched using a regular expression.
The keyup-event is then bound to the input field and whenever a key is lifted that isn’t delete or backspace (keycode 8 and 46) a regular expression is created from the input that’s used on the string. The comma-sign in the regular expression is used to only match whole suggestions (and I’m sure there’s a much cleaner way using regular expressions but this is a quick and dity fix that just works).
var qLength = 0;
var suggestions = ["Alpha", "Beta"];
$("#suggestion").each(function(i) {
var arr2str = "," + suggestions.toString();
$(this).keyup(function(e) {
if (e.keyCode == 8 || e.keyCode == 46) {
qLength = $(this).attr("value").length;
} else {
qLength++;
var re = new RegExp("," + $(this).attr("value"),"ig");
var pos = arr2str.search(re);
if (pos != -1) {
var match = arr2str.slice(pos + 1, arr2str.indexOf(",",pos + 1));
$(this).attr("value", match).select();
selectPartOfInput(this, qLength, match.length);
}
}
});
});