JSFiddle - React, Tailwind, and code Playground

by Michael Barros

HTML

<div id="autocomplete-container">
    <input type="text" autofocus="true" name="autofocus sample" placeholder="search people" id="autocomplete-input" autocomplete="off" />
    <ul id="autocomplete-results"></ul>
</div>

CSS

@import url(https://fonts.googleapis.com/css?family=Roboto+Slab);
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font: inherit;
  font-size: 100%;
  vertical-align: baseline;
}

html {
  line-height: 1;
}

ol, ul {
  list-style: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

caption, th, td {
  text-align: left;
  font-weight: normal;
  vertical-align: middle;
}

q, blockquote {
  quotes: none;
}
q:before, q:after, blockquote:before, blockquote:after {
  content: "";
  content: none;
}

a img {
  border: none;
}

article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
  display: block;
}

html, body {
  background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9Ii0wLjA5MTUwNiIgeTE9IjAuMTU4NDk0IiB4Mj0iMS4wOTE1MDYiIHkyPSIwLjg0MTUwNiI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2FkYWRlYiIvPjxzdG9wIG9mZnNldD0iNTAlIiBzdG9wLWNvbG9yPSIjNmI4ZmIyIi8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjNjY5OTk5Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
  height: 100%;
  width: 100%;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
  font-family: 'Roboto Slab';
}
html::-moz-selection,...

JavaScript

console.clear();

const triggerChars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
// variables
let input = document.querySelector('input');
let autocompleteResults = document.getElementById('autocomplete-results');
let people = [
    //
    'john doe',
    'maria',
    'paul',
    'george',
    'jimmy',
    'john smith',
    'john thomas',
    'john baker',
    'john washington',
    'john doe',
];
let results;

// functions
function autocomplete(val) {
    let people_return = [];

    for (i = 0; i < people.length; i++) {
        if (val === people[i].slice(0, val.length)) {
            people_return.push(people[i]);
        }
    }

    return people_return;
}

// events
input.addEventListener('keyup', function (ev) {
    if (ev.key == 'Escape') {
        autocompleteResults.style.display = 'none';

        return;
    }

    console.debug('ev.key:', ev.key);

    if (!(ev.key.toLowerCase() == ' ' && ev.ctrlKey) && !triggerChars.includes(ev.key)) return;

    let startPosition = this.selectionStart;
    let endPosition = this.selectionEnd;

    console.debug('startPosition:', startPosition);
    console.debug('  endPosition:', endPosition);
    console.debug('');

    let inputVal = this.value; // updates the variable on each ocurrence

    if (inputVal.length > 0) {
        let peopleToShow = [];

        autocompleteResults.innerHTML = '';

        peopleToShow = autocomplete(inputVal);

        for (i = 0; i < peopleToShow.length; i++) {
            autocompleteResults.innerHTML += '<li>' + peopleToShow[i] + '</li>';
        }

        autocompleteResults.style.display = 'block';
    } else {
        peopleToShow = [];
        autocompleteResults.innerHTML = '';
    }
});