Last active
October 19, 2016 15:35
-
-
Save thomhos/540ff12ebf81426f87b7088a387aab65 to your computer and use it in GitHub Desktop.
Autocomplete with RxJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Require libs | |
var Rx = require('rxjs/Rx'); | |
var yo = require('yo-yo'); | |
// Select dom elements | |
var inputField = document.querySelector('.input'); | |
var suggestionsEl = document.querySelector('.suggestions'); | |
// Create streams | |
var response$ = new Rx.BehaviorSubject({ query: '', results: []}); | |
var selected$ = new Rx.BehaviorSubject(-1); | |
var input$ = Rx.Observable.fromEvent(inputField, 'keyup') | |
.share(); | |
var query$ = input$ | |
.throttleTime(200) | |
.filter(e => e.keyCode !== 38 && e.keyCode !== 40) | |
.map(e => e.target.value) | |
.distinctUntilChanged() | |
var request$ = query$ | |
.filter(e => e.length > 3) | |
.map(e => ( /* do ajaxRequest => */ { query: e, results: [e, e+e, e+e+e] })) | |
.subscribe(response$); | |
var inputUpDown$ = input$ | |
.filter(e => e.keyCode === 38 || e.keyCode === 40) | |
.map(e => (e.keyCode === 38 ? -1 : 1)).scan((acc, currentValue) => { | |
var nextValue = acc + currentValue; // acc is the state (selected$) and the input modifier is added to this | |
var response = response$.getValue().results; // this is the current state of the responses | |
nextValue = (nextValue < response.length ? nextValue : -1); | |
nextValue = (nextValue > -2 ? nextValue : response.length - 1); | |
return nextValue; | |
}, selected$.getValue()) | |
.subscribe(selected$) | |
var inputClose$ = input$ | |
.filter(e => e.keyCode === 27 || e.target.value.length == 0) | |
// Constuctor to create list element | |
listFunc = (res, selected) => yo` | |
<ul> | |
${ res.results.map((item, index) => yo` | |
<li> | |
<a href="#" class="${index == selected ? 'selected' : ''}"> | |
<strong>${item.substring(0, res.query.length)}</strong>${item.substring(res.query.length)} | |
</a> | |
</li>` | |
)} | |
</ul> | |
`; | |
// Variables for list element | |
var list = listFunc(response$.getValue(), selected$.getValue()); | |
// connect list to DOM | |
suggestionsEl.appendChild(list); | |
// Update list upon response | |
response$.subscribe(res => { | |
yo.update(list, listFunc(res, selected$.getValue())); | |
}) | |
// Set index upon arrow keys | |
selected$.subscribe(e => { | |
yo.update(list, listFunc(response$.getValue(), e)); | |
if(response$.getValue()[e]) { | |
inputField.value = response$.getValue()[e]; | |
} | |
}); | |
// Set index upon arrow keys | |
inputClose$.subscribe(closeDropdown); | |
function closeDropdown() { | |
response$.next({ query: '', results: []}) | |
selected$.next(-1) | |
yo.update(list, listFunc(response$.getValue(), selected$.getValue())); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment