Swiftype Auto Suggest
Google-like auto suggester
by ninty9notout
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
<div class="swiftype-autosuggest">
<div class="swiftype-autosuggest__control">
<input type="text" class="swiftype-autosuggest__input" placeholder="e.g. dudamel">
<button type="submit" class="swiftype-autosuggest__button">Search</button>
</div>
<div class="swiftype-autosuggest__results">
<ul class="swiftype-autosuggest__list">
<!-- intentionally empty -->
</ul>
</div>
</div>
SCSS
body {
background: #34495e;
font-size: 16px;
}
.swiftype-autosuggest {
background: #2c3e50;
padding: 2.5rem;
position: relative;
}
.swiftype-autosuggest__control {
font-size: 0;
display: flex;
flex-direction: row;
border-radius: 0.25rem;
overflow: hidden;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
}
.swiftype-autosuggest__input,
.swiftype-autosuggest__button {
font-size: 16px;
padding: 1rem;
border: 0;
margin: 0;
}
.swiftype-autosuggest__input {
flex: 1;
}
.swiftype-autosuggest__button {
background: #3498db;
color: #ffffff;
}
.swiftype-autosuggest__input:focus,
.swiftype-autosuggest__button:focus {
outline: none;
}
.swiftype-autosuggest__results {
background: #ffffff;
position: absolute;
width: calc(100% - 5rem);
border-radius: 0 0 0.25rem 0.25rem;
overflow: hidden;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
border-top: 1px solid #ecf0f1;
display: none;
font-size: 0;
}
.swiftype-autosuggest__list {
list-style: none;
padding: 0;
margin: 0;
font-size: 0;
}
.swiftype-autosuggest__link {
padding: 1rem;
display: block;
font-size: 1.125rem;
text-decoration: none;
color: #000000;
}
.swiftype-autosuggest--active {
.swiftype-autosuggest__control {
border-radius: 0.25rem 0.25rem 0 0;
}
.swiftype-autosuggest__results {
display: initial;
}
}
.swiftype-autosuggest__item--active {
.swiftype-autosuggest__link {
background: #1abc9c;
color: #ffffff;
}
}
JavaScript
const inputDebounce = 500;
const minLength = 2;
const maxSuggestions = 10;
const engineKey = 'ZLUGCACvKay36iYNb5je';
const urlPrefix = '/search?q=';
const fields = ['sections'];
const selectors = {
container: '.swiftype-autosuggest',
input: '.swiftype-autosuggest__input',
list: '.swiftype-autosuggest__list',
item: '.swiftype-autosuggest__item',
itemActive: '.swiftype-autosuggest__item--active',
link: '.swiftype-autosuggest__link',
}
const classes = {
containerActive: 'swiftype-autosuggest--active',
item: 'swiftype-autosuggest__item',
itemActive: 'swiftype-autosuggest__item--active',
link: 'swiftype-autosuggest__link',
}
const $container = document.querySelector(selectors.container);
const $input = document.querySelector(selectors.input);
const $list = document.querySelector(selectors.list);
const cache = {}
const keys = {
up: 38,
down: 40,
}
let currentQuery = null;
let totalItems = null;
let currentItem = null;
const isString = (value) => {
return Object.prototype.toString.call(value) === '[object String]';
}
const debounce = (callback, delay) => {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
callback.apply(this, args);
}, delay);
}
}
const resetSuggestions = () => {
currentQuery = null;
totalItems = null;
currentItem = null;
hideSuggestions();
}
const decode = (value) => {
const decoder = document.createElement('textarea');
decoder.innerHTML = value;
if (decoder.childNodes.length === 0) {
return '';
}
return decoder.childNodes[0].nodeValue;
}
const getSuggestions = (query) => {
const params = new URLSearchParams({
q: query,
engine_key: engineKey,
spelling: 'always',
per_page: 50,
});
const url = 'https://api.swiftype.com/api/v1/public/engines/search.json?' + params.toString();
return axios.get(url).then((response) => {
let suggestions =...