Rewrite paste behavior

This commit is contained in:
Henrik Giesel 2021-06-25 02:22:10 +02:00
parent d705d049ce
commit 6e25a3d424
4 changed files with 58 additions and 40 deletions

View file

@ -40,6 +40,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
bind:input bind:input
on:focusout={() => (active = false)} on:focusout={() => (active = false)}
on:tagupdate={updateTag} on:tagupdate={updateTag}
on:tagadd
on:mount={(event) => event.detail.input.focus()} on:mount={(event) => event.detail.input.focus()}
/> />
{:else} {:else}

View file

@ -8,7 +8,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import DropdownMenu from "components/DropdownMenu.svelte"; import DropdownMenu from "components/DropdownMenu.svelte";
import DropdownItem from "components/DropdownItem.svelte"; import DropdownItem from "components/DropdownItem.svelte";
export let name: string;
export const suggestions = ["en::idioms", "anki::functionality", "math"]; export const suggestions = ["en::idioms", "anki::functionality", "math"];
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
@ -16,10 +15,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
const triggerClass = "dropdown-toggle"; const triggerClass = "dropdown-toggle";
let menu: HTMLDivElement; let menu: HTMLDivElement;
let dropdown;
let activeItem = -1;
$: tagValues = [...suggestions, name];
function onItemClick(event: Event) { function onItemClick(event: Event) {
dispatch("nameChosen", { name: event.currentTarget!.innerText }); dispatch("nameChosen", { name: event.currentTarget!.innerText });
@ -29,11 +24,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function switchUpDown(event: KeyboardEvent): void { function switchUpDown(event: KeyboardEvent): void {
const target = event.currentTarget as HTMLButtonElement; const target = event.currentTarget as HTMLButtonElement;
console.log(
event.code,
target.nextElementSibling,
target.previousElementSibling
);
if (event.code === "ArrowUp") { if (event.code === "ArrowUp") {
if (target.nextElementSibling) { if (target.nextElementSibling) {
(target.nextElementSibling as HTMLButtonElement).focus(); (target.nextElementSibling as HTMLButtonElement).focus();
@ -50,23 +40,10 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} }
function updateActiveItem(even: FocusEvent): void {} function updateActiveItem(even: FocusEvent): void {}
/* else if (event.code === "Enter") { */
/* const dropdownActive = dropdown._element.classList.contains("show"); */
/* if (dropdownActive) { */
/* if (typeof activeItem === "number") { */
/* name = tagValues[activeItem]; */
/* activeItem = null; */
/* } */
/* dropdown.hide(); */
/* } else { */
/* dispatch("accept"); */
/* } */
/* } */
</script> </script>
<div bind:this={menu} class="dropup dropdown-reverse"> <div bind:this={menu} class="dropup dropdown-reverse">
<slot {triggerId} {triggerClass} {dropdown} /> <slot {triggerId} {triggerClass} />
<DropdownMenu labelledby={triggerId}> <DropdownMenu labelledby={triggerId}>
{#each suggestions as tag} {#each suggestions as tag}

View file

@ -8,7 +8,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import Tag from "./Tag.svelte"; import Tag from "./Tag.svelte";
import TagInput from "./TagInput.svelte"; import TagInput from "./TagInput.svelte";
export let tags = ["en::foobar", "zh::あっちこっち", "test", "def"]; export let tags = ["en::foobar", "test", "def"];
let tagInputNew: HTMLInputElement; let tagInputNew: HTMLInputElement;
let newName: string = ""; let newName: string = "";
@ -17,12 +17,24 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
tagInputNew.focus(); tagInputNew.focus();
} }
function deleteTag(index: number): void { const insertTagAt = (index: number) => () => {
tags.splice(index, 1); const copy = tags.slice(0);
tags = tags; copy.splice(index, 1);
if (copy.includes(tags[index])) {
return;
} }
function addTag(): void { tags.splice(index - 1, 0, tags[index]);
tags = tags;
};
const deleteTagAt = (index: number) => () => {
tags.splice(index, 1);
tags = tags;
};
function appendTag(): void {
if (!tags.includes(newName) && newName.length > 0) { if (!tags.includes(newName) && newName.length > 0) {
tags.push(newName); tags.push(newName);
} }
@ -36,10 +48,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<AddTagBadge on:click={focusInputNew} /> <AddTagBadge on:click={focusInputNew} />
{#each tags as tag, index} {#each tags as tag, index}
<Tag bind:name={tag} on:tagdelete={() => deleteTag(index)} /> <Tag
bind:name={tag}
on:tagadd={insertTagAt(index)}
on:tagdelete={deleteTagAt(index)}
/>
{/each} {/each}
<TagInput bind:input={tagInputNew} bind:name={newName} on:tagupdate={addTag} /> <TagInput
bind:input={tagInputNew}
bind:name={newName}
on:tagupdate={appendTag}
on:tagadd={appendTag}
/>
</div> </div>
</StickyBottom> </StickyBottom>

View file

@ -40,17 +40,36 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} }
} }
function onPaste({ clipboardData }: ClipboardEvent): void { function onPaste(event: ClipboardEvent): void {
const pasted = name + clipboardData!.getData("text/plain"); event.preventDefault();
const splitted = pasted.split(" ");
const last = splitted.pop(); if (!event.clipboardData) {
for (const token of splitted) { return;
const name = normalizeTagname(token);
if (name) {
dispatch("tagadd", { name });
} }
const pasted = name + event.clipboardData.getData("text/plain");
const splitted = pasted
.split(/\s+/)
.map(normalizeTagname)
.filter((name: string) => name.length > 0);
if (splitted.length === 0) {
return;
} else if (splitted.length === 1) {
name = splitted.shift()!;
} else {
name = splitted.shift()!;
dispatch("tagadd");
const last = splitted.pop()!;
for (const pastedName of splitted) {
name = pastedName;
dispatch("tagadd");
}
name = last;
} }
name = last!;
} }
function setTagname({ detail }: CustomEvent): void { function setTagname({ detail }: CustomEvent): void {