I would like to create an input field for a username where it should be possible to choose from a large number of names / usernames. It should be possible to enter a partial string contained in the name or username. I would like to not load the list initially but after the user has typed a minimum of a number of characters (e.g. 3) because the list is ultimately very large and should be reduced to a subset by the initial 3 characters.
This works perfectly if using <input>
with <datalist>
in Chrome or Chromium, but does not work as expected in Firefox. I have not tested other browsers yet.
The expected behaviour (and the way it works in Chromium) is I type my characters and after the third character the drop-down autosuggest list is loaded and automatically displayed. If I continue typing, the list continues to get filtered. Additionally, I can make the list disappear with escape and reappear with arrow down or arrow up.
In Firefox, the list does not automatically appear. I have to type another character and then backspace. Also, I cannot make it appear with arrow down or arrow up. (The solution does work in Firefox though, if the list is created initially and not lazy-loaded, but this is not an option as described above).
What I would like to find is a way to make the suggest list automatically open (or on key press) or solve this differently (without datalist
).
<input class="my-input-class" placeholder="Enter '123' ... or 'one' ... " list="myDatalist" size="100">
<datalist id="myDatalist">
<option value="1">one</option>
<option value="12">one two</option>
<option value="123">one two three</option>
<option value="1234">one two three four</option>
<option value="12345">one two three four five</option>
<option value="123456">one two three four five six</option>
</datalist>
var previous = null;
function delayedCallback(callback, ms) {
var timer = 0;
return function() {
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
callback.apply(context, args);
}, ms || 0);
};
}
function generateSelectList(inputElement) {
var value = inputElement.val();
var optionList = {
'123': 'one two three',
'1234': 'one two three four',
'12345': 'one two three four five',
'123456': 'one two three four five six',
'1234567': 'one two three four five six seven',
}
$('#myDatalist').remove();
dl = document.createElement('datalist');
inputElement.attr('list', 'myDatalist');
dl.id = 'myDatalist';
for (var key in optionList) {
var option = document.createElement('option');
option.value = key;
option.append(optionList[key]);
dl.append(option);
}
inputElement.append(dl);
}
$(document).on('input', '.my-input-class', delayedCallback(function(event) {
var inputElement = $(event.target);
var value = inputElement.val();
// only get result list if
// - minimum 3 chars
// - same result list has not already been fetched (if string starts with previous string)
if (value.length >= 3) {
if (previous && value.startsWith(previous) && $('#myDatalist').length) {
console.log("DO NOT fetch list (again) value=" + value + " previous=" + previous);
} else {
console.log("fetch list: value=" + value);
generateSelectList(inputElement);
previous = value;
}
}
}, 500));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="my-input-class" placeholder="Enter '123' ... or 'one' ... (at least 3 characters)" list="myDatalist" size="100">
I searched for some solutions or if others had the same problem. I did find some complaints about datalist
not working as expected or not working the same in different browsers and also suggestions to use some jquery libraries. While I could just use one of the suggested solutions, I am not sure if they will solve my problem or if there is a way to make this work with datalist
and other browsers (besides Chrome).
As per canIuse there is a bug in Firefox which requires autocomplete to be set to off for datalist to work properly. Maybe this would help?