Don't allow Enter/Tab/Arrows for Autocomplete, if not active

Don't show Autocomplete, if there are no items available
This commit is contained in:
Henrik Giesel 2021-06-28 23:39:46 +02:00
parent bbef2ab6b4
commit a515a9899b
3 changed files with 59 additions and 55 deletions

View File

@ -25,6 +25,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
}
}
function isVisible(): boolean {
return (dropdown as any)._menu.classList.contains("show");
}
/* Normally dropdown and trigger are associated with a
/* common ancestor with .dropdown class */
function createDropdown(element: HTMLElement): Dropdown {
@ -43,6 +47,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/* Set custom menu without using common element with .dropdown */
(dropdown as any)._menu = menu;
Object.defineProperty(dropdown, "isVisible", { value: isVisible });
}
return dropdown as Dropdown;

View File

@ -16,9 +16,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { attachId, getName } from "./tags";
export let size = isApplePlatform() ? 1.6 : 2.0;
export let tags: TagType[] = [];
export let suggestions = ["en::idioms", "anki::functionality", "math"];
export let tags: TagType[] = [];
export function resetTags(names: string[]): void {
tags = names.map(attachId);
@ -35,31 +34,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function onAutocomplete({ detail }) {
const activeTag = tags[active!];
const autocompletionChoice = detail.choice;
const selected = detail.selected;
console.log(autocompletionChoice, activeTag);
if (autocompletionChoice) {
activeName = autocompletionChoice;
} else {
activeName = activeTag.name;
}
activeName = selected ?? activeTag.name;
}
let addOrPop = true;
function updateSuggestions(): void {
if (suggestions.length === 0) {
addOrPop = false;
} else if (suggestions.length > 3) {
addOrPop = true;
}
let suggestions: string[] = [];
if (addOrPop) {
suggestions.pop();
suggestions = suggestions;
} else {
suggestions = suggestions.concat(["another"]);
}
}
function updateSuggestions(): void {}
function updateWithTagName(tag: TagType): void {
tag.name = activeName;
@ -225,7 +207,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
activeAfterBlur = null;
}
function update(event: KeyboardEvent, autocomplete): void {
function update(event: KeyboardEvent, autocomplete: any): void {
const visible = autocomplete.isVisible();
if (
!visible &&
(event.location === KeyboardEvent.DOM_KEY_LOCATION_STANDARD ||
event.location === KeyboardEvent.DOM_KEY_LOCATION_NUMPAD)
) {
autocomplete.show();
}
switch (event.code) {
case "ArrowUp":
autocomplete.selectNext();
@ -277,6 +269,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
id={tag.id}
bind:name={activeName}
bind:input={activeInput}
on:click={(event) => event.stopPropagation()}
on:focus={() => {
activeName = tag.name;
createAutocomplete(activeInput);

View File

@ -16,7 +16,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let suggestions: string[];
let dropdown: Dropdown | undefined;
let target: HTMLElement;
let dropdown: Dropdown;
let autocomplete: any;
let selected: number | null = null;
// blue highlight
@ -24,25 +26,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const dispatch = createEventDispatcher();
const createAutocomplete =
(createDropdown: (target: HTMLElement) => Dropdown) =>
(target: HTMLElement): void => {
dropdown = createDropdown(target);
};
function selectPrevious() {
if (selected === null) {
selected = suggestions.length - 1;
} else if (selected === 0) {
selected = null;
} else {
selected--;
}
const choice = suggestions[selected ?? -1];
dispatch("dropdown", { choice });
}
function selectNext() {
if (selected === null) {
selected = 0;
@ -52,8 +35,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
selected++;
}
const choice = suggestions[selected ?? -1];
dispatch("autocomplete", { choice });
dispatch("autocomplete", { selected: suggestions[selected ?? -1] });
}
function selectPrevious() {
if (selected === null) {
selected = suggestions.length - 1;
} else if (selected === 0) {
selected = null;
} else {
selected--;
}
dispatch("autocomplete", { selected: suggestions[selected ?? -1] });
}
function chooseSelected() {
@ -69,20 +63,32 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
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");
}
}
const autocomplete = {
hide: () => dropdown!.hide(),
show: () => dropdown!.show(),
toggle: () => dropdown!.toggle(),
selectPrevious,
selectNext,
chooseSelected,
update,
};
const createAutocomplete =
(createDropdown: (element: HTMLElement) => Dropdown) =>
(element: HTMLElement): any => {
target = element;
dropdown = createDropdown(element);
autocomplete = {
hide: dropdown.hide.bind(dropdown),
show: dropdown.show.bind(dropdown),
toggle: dropdown.toggle.bind(dropdown),
isVisible: (dropdown as any).isVisible,
selectPrevious,
selectNext,
chooseSelected,
update,
};
return autocomplete;
};
onDestroy(() => dropdown?.dispose());
</script>