diff --git a/Autocomplete.js b/Autocomplete.js index 540ea94..4c3ced6 100644 --- a/Autocomplete.js +++ b/Autocomplete.js @@ -1,6 +1,10 @@ +import 'regenerator-runtime/runtime' + export default class Autocomplete { - constructor(rootEl, options = {}) { + constructor(rootEl, url, id, options = {}) { this.rootEl = rootEl; + this.url = url; + this.id = id; this.options = { numOfResults: 10, data: [], @@ -22,12 +26,34 @@ export default class Autocomplete { }); } - onQueryChange(query) { + async onQueryChange(query) { + let results; + // Get data for the dropdown - let results = this.getResults(query, this.options.data); - results = results.slice(0, this.options.numOfResults); - - this.updateDropdown(results); + if (query.length > 0) { + await this.fetchData(query).then((data)=> { + this.results = data; + }); + } else { + this.results = []; + } + + this.updateDropdown(this.results); + } + + async fetchData (query) { + return fetch(this.url + query + "&per_page=" + this.options.numOfResults) + .then((resp) => resp.json()) + .then(function(data) { + let items = data.items + return items.map(item => ({ + text: item[Object.keys(item)[0]], + value: item[Object.keys(item)[1]], + })); + }) + .catch(function(error) { + console.log(error); + }); } updateDropdown(results) { @@ -37,31 +63,67 @@ export default class Autocomplete { createResultsEl(results) { const fragment = document.createDocumentFragment(); - results.forEach((result) => { + results.forEach((result, i) => { const el = document.createElement('li'); el.classList.add('result'); el.textContent = result.text; + el.setAttribute('tabindex', i); // Pass the value to the onSelect callback el.addEventListener('click', () => { const { onSelect } = this.options; if (typeof onSelect === 'function') onSelect(result.value); }); + + el.addEventListener('keypress', (e) => { + if(e.keyCode === 13) { + const { onSelect } = this.options; + if (typeof onSelect === 'function') onSelect(result.value); + } + }); + fragment.appendChild(el); }); return fragment; } + + scrollList() { + var list = document.getElementById(this.id + "list"); + var first = list.firstChild; + var input = document.getElementById(this.id); + document.onkeydown = function(e) { + switch (e.keyCode) { + case 38: //up + if (document.activeElement == first) { + break; + } + else { + document.activeElement.previousSibling.focus(); + } + break; + case 40: //down + if (document.activeElement == input) { + first.focus(); + } + else { + document.activeElement.nextSibling.focus(); + } + break; + } + } +} createQueryInputEl() { const inputEl = document.createElement('input'); inputEl.setAttribute('type', 'search'); inputEl.setAttribute('name', 'query'); + inputEl.setAttribute('id', this.id); inputEl.setAttribute('autocomplete', 'off'); inputEl.addEventListener('input', event => this.onQueryChange(event.target.value)); - + inputEl.addEventListener('keydown', this.scrollList); return inputEl; } @@ -73,6 +135,7 @@ export default class Autocomplete { // Build results dropdown this.listEl = document.createElement('ul'); this.listEl.classList.add('results'); + this.listEl.setAttribute('id', this.id + "list"); this.rootEl.appendChild(this.listEl); } } diff --git a/SOLUTION.md b/SOLUTION.md index 71e864e..611cf78 100644 --- a/SOLUTION.md +++ b/SOLUTION.md @@ -1,3 +1,7 @@ # Solution Docs +To esure multiple instances of the component can be used on the same page, I gave the component an option for a unique id. +I added an eventlistener to the input to allow for the movement with arrow keys. Added a tabindex to get the focus funtion to work. +To allow selection, I added an eventlistener to each list item to listen for the enter key and call the onselection function already provided. +Allowed the url to be a parameter for the component. \ No newline at end of file diff --git a/index.html b/index.html index 8a457ca..bcafa0b 100644 --- a/index.html +++ b/index.html @@ -6,17 +6,24 @@
-