mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
Rewrite paste behavior
This commit is contained in:
parent
d705d049ce
commit
6e25a3d424
4 changed files with 58 additions and 40 deletions
|
@ -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}
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue