JSFiddle - React, Tailwind, and code Playground

by Bharat Gupta

HTML

<!-- 
We want you to build an input box which allows users to create a search easily and quickly.

Requirements:

- Create a well designed input box where user can type their search.
- Display suggestions user can pick from a displayed drop down. Suggestions should be fetched and displayed while typing and also when the user focuses on the input box. The suggestions should hide on click out.
- This fiddle contains a mock server API to generate suggestions.
- getSuggestions API returns a promise which can get resolved or rejected at any time ranging from 0 - 200 ms.
- All space delimited words other than the last can be considered to be already tokenized and should not be sent to the get suggestions server API.
- Selecting suggestion should update the input text with the suggestion, and automatically add a space at the end to allow quick typing.
-->
<div class="container">
  <div class="search-input">
    <input type="text" class="search-textbox" />
    <div class="error"></div>
  </div>
  <div class="search-results"></div>
</div>

JavaScript

// ================================= Mock Server Start =============================
var FAILURE_COEFF = 10;
var MAX_SERVER_LATENCY = 200;

function getRandomBool(n) {
  var maxRandomCoeff = 1000;
  if (n > maxRandomCoeff) n = maxRandomCoeff;
  return Math.floor(Math.random() * maxRandomCoeff) % n === 0;
}

function getSuggestions(text) {
  var pre = 'pre';
  var post = 'post';
  var results = [];
  if (getRandomBool(2)) {
    results.push(pre + text);
  }
  if (getRandomBool(2)) {
    results.push(text);
  }
  if (getRandomBool(2)) {
    results.push(text + post);
  }
  if (getRandomBool(2)) {
    results.push(pre + text + post);
  }
  return new Promise((resolve, reject) => {
    var randomTimeout = Math.random() * MAX_SERVER_LATENCY;
    setTimeout(() => {
      if (getRandomBool(FAILURE_COEFF)) {
        reject();
      } else {
        resolve(results);
      }
    }, randomTimeout);
  });
}
// ================================= Mock Server End =============================

function getSearchWord(str) {
	const spaceLastIndex = str.lastIndexOf(' ');
  return spaceLastIndex === -1 ? str : str.substr(spaceLastIndex + 1);
}

function registerClickHandler(resultsContainer, callback) {
	
	resultsContainer.addEventListener('click', (event) => {
		if (event.target.tagName === 'LI') {
    	callback(event.target.textContent);
    }
  });
}

function showSearchResults(resultsContainer, results) {
	if (!results || results.length === 0) {
		return;  
  }

	const resultsElement = document.createElement('ul');
  
  results.forEach(result => {
    const searchElem = document.createElement('li');
    const textNode = document.createTextNode(result);
    searchElem.appendChild(textNode);
    searchElem.classList.add('search-result-item');
    resultsElement.append(searchElem);
  });

  resultsContainer.innerHTML = '';
  resultsContainer.append(resultsElement);
}

function showErrorMessage(errorMessageElem, message) {
	errorMessageElem.innerHTML = '';
  const textNode =...