Dynamic, instant autocompletion via datalist
by rudiedirkx
HTML
<p>Javascript hack: Search for "r", "ru", "rud", "rudi" and "rudo":</p>
<p>
<input list="suggestions" autocomplete="off" autofocus="1" />
<datalist id="suggestions"></datalist>
</p>
<p>
<label><input type="checkbox" id="clean" /> Remove options while searching</label>
<label><input type="checkbox" id="slow" /> Searching is slow</label>
</p>
<p>Normal autocomplete:</p>
<p>
<input list="suggestions2" autocomplete="off" />
<datalist id="suggestions2"><option value="ralph"><option value="ronny"><option value="rudie"><option value="rutte"><option value="rudiedirkx"><option value="rudolf"></datalist>
</p>
CSS
label:after {
content: "\A";
white-space: pre;
}
JavaScript
var input = document.querySelector('input'),
datalist = document.querySelector('datalist');
var clean = document.getElementById('clean'),
slow = document.getElementById('slow');
// Show options to user
function setOptions(options) {
datalist.innerHTML = options.map(function(o) {
return '<option value="' + o + '" />';
}).join();
}
// Async fetch matches
function findOptions(search, callback) {
var respond = function(options) {
setTimeout(function() {
callback(options);
}, slow.checked ? 350 : 100);
};
switch (search) {
case 'r':
respond(['ralph', 'ronny', 'rudie']);
break;
case 'ru':
respond(['rudie', 'rutte', 'rudiedirkx']);
break;
case 'rud':
respond(['rudie', 'rudiedirkx', 'rudolf']);
break;
case 'rudi':
respond(['rudie']);
break;
case 'rudo':
respond(['rudolf']);
break;
default:
respond([]);
}
}
// ondirectsearch, instant, no delay
input.addEventListener('keyup', function(e) {
var lastValue = this.lastValue,
thisValue = this.value;
if (lastValue != thisValue) {
this.lastValue = thisValue;
// Empty autocomplete
if (clean.checked) {
setOptions([]);
}
// Async find matches
findOptions(thisValue, function(options) {
// Re-fill autocomplete
setOptions(options);
});
}
});