Last active
February 21, 2020 08:16
-
-
Save marionebl/bf86cb48e2bf399569165e89c0949289 to your computer and use it in GitHub Desktop.
Typeahead
This file contains hidden or 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
Typeahead | |
Inactive* | |
Initial* | |
type trigger -> Empty | |
Completed | |
tick -> Initial | |
Active | |
Empty* | |
type Esc -> Initial | |
type Return -> Initial | |
type char -> List Options | |
type whitespace -> Initial | |
delete -> Initial | |
select -> Initial | |
List Options | |
type Esc -> Initial | |
type Return -> Has Matches? | |
type char -> List Options | |
type whitespace -> Has Matches? | |
delete -> Is Empty? | |
select -> Inactive | |
pick -> Completed | |
Queries | |
Has Matches? | |
has match -> Completed | |
no match -> Initial | |
Is Empty? | |
is empty -> Empty | |
is not empty -> List Options |
This file contains hidden or 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
window.picked = false; | |
window.query = ''; | |
window.results = []; | |
const haystack = 'aabbbbcccccddeeffgggghhhhhhhhiiiijjkkkklllllllmmmmnopqrstuvwxyz'.split(''); | |
function getType(trigger) { | |
switch(trigger.trim()) { | |
case ':': | |
return 'Emoji'; | |
case '/': | |
return 'QuickInsert'; | |
case '@': | |
return 'Mention'; | |
default: | |
return trigger; | |
} | |
} | |
function isTrigger(charCode) { | |
// [':', '@', '/'] | |
return [59, 50, 191].includes(charCode); | |
} | |
function renderResults(model) { | |
return $('ul', ...window.results.map(item=> $('li', [item.type, item.result].join(': ')))) | |
} | |
function renderInput(model) { | |
const name = model.active_states[0].name; | |
return $("div", | |
$("input", { | |
'data-id': 'input', | |
onBlur: () => { | |
setTimeout(() => !window.picked ? model.emit('select') : undefined); | |
}, | |
onKeyDown: e => { | |
if (e.keyCode === 8) { | |
return model.emit('delete'); | |
} | |
if (isTrigger(e.keyCode)) { | |
return model.emit('type trigger') | |
} | |
if (e.keyCode === 32) { | |
return model.emit('type whitespace'); | |
} | |
if (e.keyCode === 27) { | |
e.preventDefault(); | |
return model.emit('type Esc'); | |
} | |
if (e.keyCode === 13) { | |
e.preventDefault(); | |
return model.emit('type Return'); | |
} | |
return model.emit('type char'); | |
}, | |
onChange(e) { | |
window.query = e.target.value.length > 0 ? e.target.value.slice(1) : ''; | |
window.trigger = e.target.value.length > 0 ? e.target.value[0] : ''; | |
} | |
}) | |
); | |
} | |
function renderOptions(model) { | |
const name = model.active_states[0].name; | |
if (name !== 'List Options' && name !== 'Has Matches?') { | |
return null; | |
} | |
const matches = haystack.filter(item => item === window.query); | |
return $('ul', ...matches.map(item=> $('li', { onClick() { | |
window.picked = true; | |
model.emit('pick') | |
} }, item))) | |
} | |
function render(model){ | |
const name = model.active_states[0].name; | |
if (name === 'Has Matches?') { | |
const matchedItems = haystack.filter(item => item === window.query.trim()); | |
setTimeout(() => { | |
model.emit(matchedItems.length > 0 ? 'has match' : 'no match'); | |
}, 1000); | |
} | |
if (name === 'Is Empty?') { | |
setTimeout(() => { | |
model.emit(window.query.length > 1 ? 'is not empty' : 'is empty'); | |
}, 1000); | |
} | |
if (name === 'Completed') { | |
const matchedItems = haystack.filter(item => item === window.query.trim()); | |
const result = matchedItems[0]; | |
setTimeout(() => { | |
if (result) { | |
results.push({ type: getType(window.trigger), result }); | |
} | |
model.emit('tick'); | |
}, 1000) | |
} | |
if (name === 'Initial') { | |
const input = document.querySelector('[data-id=input]'); | |
input ? input.value = '' : undefined; | |
window.query = ''; | |
window.trigger = ''; | |
window.picked = false; | |
} | |
return $("div", { | |
style: { | |
fontFamily: 'sans-serif', | |
padding: '12px' | |
} | |
}, | |
$("h4", "Input"), renderInput(model), | |
$("h4", "Options"), renderOptions(model), | |
$("h4", "Results"), renderResults(model)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment