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 =...