Skip to content

Instantly share code, notes, and snippets.

@mishelen
Last active May 13, 2016 21:31
Show Gist options
  • Save mishelen/e8e4243a1d80ef415a373ea400c3de0f to your computer and use it in GitHub Desktop.
Save mishelen/e8e4243a1d80ef415a373ea400c3de0f to your computer and use it in GitHub Desktop.
class AutoComplete {
constructor(input, config) {
this.input = typeof input == "string" ? document.querySelector(input) : input;
this.wholeSuggestList = config.wholeSuggestList;
this.suggestListMathes = [];
this.options = Object.assign({
delay: 150,
suggestListClassName: 'suggestions list-unstyled',
maxSuggestions: 7,
minChars: 1
}, config.options);
this.init();
}
set newSuggestions(list) {
this.wholeSuggestList = list;
}
get value() {
return this.input.value;
}
createList() {
this.list = document.createElement('ul');
this.listActiveItem = 0;
this.list.className = this.options.suggestListClassName;
this.input.parentNode.appendChild(this.list);
}
showList(suggestions) {
const template = document.createDocumentFragment();
// вспомогательная фальш-строка в списке. Для кажущегося перескока на инпут
template.appendChild(document.createElement('li')).setAttribute('hidden', 'hidden');
suggestions.forEach(item => {
const li = document.createElement('li');
const text = document.createTextNode(item);
li.appendChild(text);
template.appendChild(li);
});
this.list.innerHTML = '';
this.list.appendChild(template);
this.list.style.opacity = 1;
}
closeList() {
this.list.style.opacity = 0;
this.listActiveItem = 0;
}
destroy() {
this.input.removeEventListener("input", this.onAutocompleteChange);
this.input.removeEventListener("keydown", this.keyDownHandler);
this.list.remove();
}
onAutocompleteChange(e) {
const val = e.target.value
if (val.length < this.options.minChars) {
this.closeList();
return;
}
this.suggestListMathes = this.wholeSuggestList.filter(item => (new RegExp(val, 'i')).test(item));
this.suggestListMathes.length > 0 ? this.showList(this.suggestListMathes) : this.closeList();
}
onChange() {
console.log('user choosed');
}
keyDownHandler(e) {
const keyCode = e.keyCode;
if (keyCode == 33) {// page up
return; // ничего
}
if (keyCode == 34) {// page down (do nothing);
return; // ничего
}
if (keyCode == 27) { //escape
// todo сбрасываем выбор на последнее введенное.
this.closeList();
}
if (keyCode == 39 || keyCode == 35 || keyCode == 9) { // right, end, tab -- сработал автокомплит
if (keyCode == 9) { // для таба перебиваем стандартное поведение, что бы не прыгало
e.preventDefault();
e.stopPropagation();
}
// todo заполнение пользовательского инпута подсказкой. Проверка существования подсказки.
this.onChange();
this.closeList();
}
if (keyCode == 13) { // enter -- сработал автокомплит
// todo заполнение пользовательского инпута подсказкой. Проверка существования подсказки.
this.onChange();
this.closeList();
}
if (keyCode == 38 || keyCode == 40) { // up & down
let listItems = this.list.childNodes;
Array.prototype.forEach.call(listItems, item => item.classList.remove('text-danger'));
this.listActiveItem += keyCode - 39;
if (this.listActiveItem < 0) {
this.listActiveItem = listItems.length - 1;
} else if (this.listActiveItem >= listItems.length) {
this.listActiveItem = 0;
}
listItems[this.listActiveItem].classList.add('text-danger');
// todo дополнение пользовательского инпута подсказкой. Проверка существования подсказки.
return;
}
}
init() {
this.input.addEventListener("input", e => this.onAutocompleteChange(e));
this.input.addEventListener("keydown", e => this.keyDownHandler(e));
this.createList();
}
}
let input = document.querySelector('#auto_complete-input');
suggestor = new AutoComplete(input, {
wholeSuggestList: ['one', 'two', 'three', 'four'],
options : {delay: 250}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment