JavaScript
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback.apply(null, args);
}, wait);
};
}
// Source: https://stackoverflow.com/a/6969486
function escapeRegex(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
const srch = document.querySelector('#txtSearch');
const disp = document.querySelector('#disp');
const inputHandler = debounce((evt) => {
const input = escapeRegex(evt.target.value),
re = new RegExp(input, 'gi');
let acText = '',
markup = '<ul class="plain-list result">';
for (const i of list) {
if (re.test(i)) {
acText = i.replace(re, `<span class="result-ac">${input}</span>`)
markup += `<li>${acText}</li>`;
}
}
markup += '</ul>';
disp.innerHTML = markup;
}, 200);
srch.addEventListener('input', inputHandler);
// 1000 words list. Declared towards the bottom of the source block for convenience.
// Relies on hoisting.
const list = ['ability',
'able',
'about',
'above',
'accept',
'according',
'account',
'across',
'act',
'action',
'activity',
'actually',
'add',
'address',
'administration',
'admit',
'adult',
'affect',
'after',
'again',
'against',
'age',
'agency',
'agent',
'ago',
'agree',
'agreement',
'ahead',
'air',
'all',
'allow',
'almost',
'alone',
'along',
'already',
'also',
'although',
'always',
'American',
'among',
'amount',
'analysis',
'and',
'animal',
'another',
'answer',
'any',
'anyone',
'anything',
'appear',
'apply',
'approach',
'area',
'argue',
'arm',
'around',
'arrive',
'art',
'article',
'artist',
'as',
'ask',
'assume',
'at',
'attack',
'attention',
'attorney',
'audience',
'author',
'authority',
'available',
'avoid',
'away',
'baby',
'back',
'bad',
'bag',
'ball',
'bank',
...