overhauled autocomplete – should now work with mobile devices, too
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
const ignore = ['ArrowLeft','ArrowRight'];
|
||||
//let candidate = $state({ display : '' });
|
||||
let selected = $state([]);
|
||||
let selected = $state(null);
|
||||
let candidates = $state([]);
|
||||
let timer = null;
|
||||
|
||||
@@ -53,12 +53,13 @@
|
||||
const idx = select.value;
|
||||
candidate = candidates[idx];
|
||||
candidates = [];
|
||||
selected = [];
|
||||
selected = null;
|
||||
onSelect(candidate);
|
||||
}
|
||||
|
||||
async function fetchCandidates(){
|
||||
candidates = await getCandidates(candidate.display);
|
||||
selected = null;
|
||||
if (selected>candidates.length) selected = candidates.length;
|
||||
}
|
||||
|
||||
@@ -66,28 +67,28 @@
|
||||
if (ignore.includes(ev.key)) return;
|
||||
if (ev.key == 'ArrowDown'){
|
||||
ev.preventDefault();
|
||||
selected = selected.length < 1 ? [0] : [selected[0]+1]
|
||||
if (selected[0] >= candidates.length) selected = [0];
|
||||
selected = selected == null ? 0: selected +1;
|
||||
if (selected >= candidates.length) selected = 0;
|
||||
return false;
|
||||
}
|
||||
if (ev.key == 'ArrowUp'){
|
||||
ev.preventDefault();
|
||||
selected = selected.length < 1 ? [-1] : [selected[0]-1]
|
||||
if (selected[0] < 0) selected = [candidates.length-1];
|
||||
selected = selected == null ? candidates.length -1 : selected -1;
|
||||
if (selected < 0) selected = candidates.length -1;
|
||||
return false;
|
||||
}
|
||||
if (ev.key == 'Enter'|| ev.key == 'Tab'){
|
||||
ev.preventDefault();
|
||||
if (selected.length>0) {
|
||||
candidate = candidates[selected[0]];
|
||||
if (selected != null && selected < candidates.length) {
|
||||
candidate = candidates[selected];
|
||||
candidates = [];
|
||||
selected = [];
|
||||
selected = null;
|
||||
onSelect(candidate);
|
||||
return false;
|
||||
}
|
||||
if (ev.key == 'Enter') {
|
||||
candidates = [];
|
||||
selected = [];
|
||||
selected = null;
|
||||
if (onCommit(candidate)) candidate = { display : '' };
|
||||
}
|
||||
return false;
|
||||
@@ -95,7 +96,7 @@
|
||||
if (ev.key == 'Escape'){
|
||||
ev.preventDefault();
|
||||
candidates = [];
|
||||
selected = [];
|
||||
selected = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -104,23 +105,42 @@
|
||||
timer = setTimeout(fetchCandidates,400);
|
||||
return false;
|
||||
}
|
||||
|
||||
function select(index){
|
||||
candidate = candidates[index];
|
||||
selected = null;
|
||||
candidates = [];
|
||||
onSelect(candidate);
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
span { position : relative }
|
||||
select { position : absolute; top: 30px; left: 3px; }
|
||||
ul {
|
||||
position : absolute;
|
||||
top: 30px;
|
||||
left: 3px;
|
||||
background: black;
|
||||
color: orange;
|
||||
border: 1px solid orange;
|
||||
border-radius: 5px;
|
||||
z-index: 50;
|
||||
list-style: none;
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
}
|
||||
.highlight { background: orange; color: black; }
|
||||
|
||||
select { background: black; color: orange; border: 1px solid orange; border-radius: 5px; z-index: 50; }
|
||||
option:checked { background: orange; color: black; }
|
||||
</style>
|
||||
|
||||
<span>
|
||||
<input type="text" bind:value={candidate.display} {onkeyup} autofocus={autofocus} {id} />
|
||||
<input type="text" bind:value={candidate.display} {onkeyup} autofocus={autofocus} />
|
||||
{#if candidates && candidates.length > 0}
|
||||
<select bind:value={selected} {ondblclick} multiple tabindex="-1">
|
||||
<ul>
|
||||
{#each candidates as candidate,i}
|
||||
<option value={i}>{candidate.display}</option>
|
||||
<li class="option {selected==i?'highlight':''}" onclick={e => selected = i} ondblclick={e => select(i)}>{candidate.display}</li>
|
||||
{/each}
|
||||
</select>
|
||||
</ul>
|
||||
{/if}
|
||||
</span>
|
||||
Reference in New Issue
Block a user