mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
Take most recent input as basis for suggestions
This commit is contained in:
parent
4da1c77220
commit
9e1f2aa262
2 changed files with 47 additions and 55 deletions
|
@ -62,8 +62,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSuggestions(): void {
|
function updateSuggestions(): void {
|
||||||
const currentInput = tags[tags.length - 1].name;
|
suggestionsPromise = fetchSuggestions(activeName).then(
|
||||||
suggestionsPromise = fetchSuggestions(currentInput).then(
|
|
||||||
(names: string[]): string[] => names.map(replaceWithUnicodeSeparator)
|
(names: string[]): string[] => names.map(replaceWithUnicodeSeparator)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -78,6 +77,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
function updateTagName(tag: TagType): void {
|
function updateTagName(tag: TagType): void {
|
||||||
tag.name = activeName;
|
tag.name = activeName;
|
||||||
tags = tags;
|
tags = tags;
|
||||||
|
|
||||||
|
autocomplete.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setActiveAfterBlur(value: number): void {
|
function setActiveAfterBlur(value: number): void {
|
||||||
|
@ -287,13 +288,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
autocomplete.chooseSelected();
|
autocomplete.chooseSelected();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
|
||||||
if (printable || deletion) {
|
|
||||||
autocomplete.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,67 +15,71 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export { className as class };
|
export { className as class };
|
||||||
|
|
||||||
export let drop: "down" | "up" | "left" | "right" = "down";
|
export let drop: "down" | "up" | "left" | "right" = "down";
|
||||||
|
|
||||||
export let suggestionsPromise: Promise<string[]>;
|
export let suggestionsPromise: Promise<string[]>;
|
||||||
|
|
||||||
let target: HTMLElement;
|
let target: HTMLElement;
|
||||||
let dropdown: Dropdown;
|
let dropdown: Dropdown;
|
||||||
|
|
||||||
|
let suggestionsItems: string[] = [];
|
||||||
|
$: suggestionsPromise.then((items) => {
|
||||||
|
if (items.length > 0) {
|
||||||
|
// disabled class will tell Bootstrap not to show menu on clicking
|
||||||
|
target.classList.remove("disabled");
|
||||||
|
dropdown.show();
|
||||||
|
} else {
|
||||||
|
dropdown.hide();
|
||||||
|
target.classList.add("disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
suggestionsItems = items;
|
||||||
|
});
|
||||||
|
|
||||||
let selected: number | null = null;
|
let selected: number | null = null;
|
||||||
let active: boolean = false;
|
let active: boolean = false;
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* select as currently highlighted item
|
||||||
|
*/
|
||||||
async function selectNext() {
|
async function selectNext() {
|
||||||
const suggestions = await suggestionsPromise;
|
|
||||||
|
|
||||||
if (selected === null) {
|
if (selected === null) {
|
||||||
selected = 0;
|
selected = 0;
|
||||||
} else if (selected >= suggestions.length - 1) {
|
} else if (selected >= suggestionsItems.length - 1) {
|
||||||
selected = null;
|
selected = null;
|
||||||
} else {
|
} else {
|
||||||
selected++;
|
selected++;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch("select", { selected: suggestions[selected ?? -1] });
|
dispatch("select", { selected: suggestionsItems[selected ?? -1] });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function selectPrevious() {
|
async function selectPrevious() {
|
||||||
const suggestions = await suggestionsPromise;
|
|
||||||
|
|
||||||
if (selected === null) {
|
if (selected === null) {
|
||||||
selected = suggestions.length - 1;
|
selected = suggestionsItems.length - 1;
|
||||||
} else if (selected === 0) {
|
} else if (selected === 0) {
|
||||||
selected = null;
|
selected = null;
|
||||||
} else {
|
} else {
|
||||||
selected--;
|
selected--;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch("select", { selected: suggestions[selected ?? -1] });
|
dispatch("select", { selected: suggestionsItems[selected ?? -1] });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* choose as accepted suggestion
|
||||||
|
*/
|
||||||
async function chooseSelected() {
|
async function chooseSelected() {
|
||||||
const suggestions = await suggestionsPromise;
|
|
||||||
|
|
||||||
active = true;
|
active = true;
|
||||||
dispatch("choose", { chosen: suggestions[selected ?? -1] });
|
dispatch("choose", { chosen: suggestionsItems[selected ?? -1] });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function update() {
|
async function update() {
|
||||||
dropdown = dropdown as Dropdown;
|
dropdown = dropdown as Dropdown;
|
||||||
dropdown.update();
|
dropdown.update();
|
||||||
|
await tick();
|
||||||
|
|
||||||
dispatch("update");
|
dispatch("update");
|
||||||
|
|
||||||
const [, suggestions] = await Promise.all([tick(), suggestionsPromise]);
|
|
||||||
|
|
||||||
if (suggestions.length > 0) {
|
|
||||||
dropdown.show();
|
|
||||||
// disabled class will tell Bootstrap not to show menu on clicking
|
|
||||||
target.classList.remove("disabled");
|
|
||||||
} else {
|
|
||||||
dropdown.hide();
|
|
||||||
target.classList.add("disabled");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasSelected(): boolean {
|
function hasSelected(): boolean {
|
||||||
|
@ -85,8 +89,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const createAutocomplete =
|
const createAutocomplete =
|
||||||
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
(createDropdown: (element: HTMLElement) => Dropdown) =>
|
||||||
(element: HTMLElement): any => {
|
(element: HTMLElement): any => {
|
||||||
target = element;
|
|
||||||
dropdown = createDropdown(element);
|
dropdown = createDropdown(element);
|
||||||
|
target = element;
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
hide: dropdown.hide,
|
hide: dropdown.hide,
|
||||||
|
@ -103,8 +107,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
return api;
|
return api;
|
||||||
};
|
};
|
||||||
|
|
||||||
onDestroy(() => dropdown?.dispose());
|
|
||||||
|
|
||||||
function setSelected(index: number): void {
|
function setSelected(index: number): void {
|
||||||
selected = index;
|
selected = index;
|
||||||
active = true;
|
active = true;
|
||||||
|
@ -115,9 +117,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
|
|
||||||
async function selectIndex(index: number): Promise<void> {
|
async function selectIndex(index: number): Promise<void> {
|
||||||
const suggestions = await suggestionsPromise;
|
|
||||||
active = false;
|
active = false;
|
||||||
dispatch("select", { selected: suggestions[index] });
|
dispatch("select", { selected: suggestionsItems[index] });
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectIfMousedown(event: MouseEvent, index: number): void {
|
function selectIfMousedown(event: MouseEvent, index: number): void {
|
||||||
|
@ -125,16 +126,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
setSelected(index);
|
setSelected(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDestroy(() => dropdown?.dispose());
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<WithDropdown {drop} toggleOpen={false} let:createDropdown>
|
<WithDropdown {drop} toggleOpen={false} let:createDropdown>
|
||||||
<slot createAutocomplete={createAutocomplete(createDropdown)} />
|
<slot createAutocomplete={createAutocomplete(createDropdown)} />
|
||||||
|
|
||||||
<DropdownMenu class={className}>
|
<DropdownMenu class={className}>
|
||||||
{#await suggestionsPromise}
|
{#each suggestionsItems as suggestion, index}
|
||||||
<AutocompleteItem>...</AutocompleteItem>
|
|
||||||
{:then suggestions}
|
|
||||||
{#each suggestions as suggestion, index}
|
|
||||||
<AutocompleteItem
|
<AutocompleteItem
|
||||||
selected={index === selected}
|
selected={index === selected}
|
||||||
active={index === selected && active}
|
active={index === selected && active}
|
||||||
|
@ -144,10 +144,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
chooseSelected();
|
chooseSelected();
|
||||||
}}
|
}}
|
||||||
on:mouseenter={(event) => selectIfMousedown(event, index)}
|
on:mouseenter={(event) => selectIfMousedown(event, index)}
|
||||||
on:mouseleave={() => (active = false)}
|
on:mouseleave={() => (active = false)}>{suggestion}</AutocompleteItem
|
||||||
>{suggestion}</AutocompleteItem
|
|
||||||
>
|
>
|
||||||
{/each}
|
{/each}
|
||||||
{/await}
|
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</WithDropdown>
|
</WithDropdown>
|
||||||
|
|
Loading…
Reference in a new issue