934a9bd24b
This is to provide minimal closures for the mutable file-local variables: - changeTimer - previousActiveElement - currentNoteId This makes it clear, that they should not be used, but rather the functions which wrap them in an API
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { EditingArea } from ".";
|
|
import { nodeIsElement } from "./helpers";
|
|
import { triggerChangeTimer } from "./changeTimer";
|
|
|
|
function inListItem(currentField: EditingArea): boolean {
|
|
const anchor = currentField.getSelection()!.anchorNode!;
|
|
|
|
let inList = false;
|
|
let n = nodeIsElement(anchor) ? anchor : anchor.parentElement;
|
|
while (n) {
|
|
inList = inList || window.getComputedStyle(n).display == "list-item";
|
|
n = n.parentElement;
|
|
}
|
|
|
|
return inList;
|
|
}
|
|
|
|
export function onInput(event: Event): void {
|
|
// make sure IME changes get saved
|
|
triggerChangeTimer(event.currentTarget as EditingArea);
|
|
}
|
|
|
|
export function onKey(evt: KeyboardEvent): void {
|
|
const currentField = evt.currentTarget as EditingArea;
|
|
|
|
// esc clears focus, allowing dialog to close
|
|
if (evt.code === "Escape") {
|
|
currentField.blurEditable();
|
|
return;
|
|
}
|
|
|
|
// prefer <br> instead of <div></div>
|
|
if (evt.code === "Enter" && !inListItem(currentField)) {
|
|
evt.preventDefault();
|
|
document.execCommand("insertLineBreak");
|
|
}
|
|
|
|
// // fix Ctrl+right/left handling in RTL fields
|
|
if (currentField.isRightToLeft()) {
|
|
const selection = currentField.getSelection();
|
|
const granularity = evt.ctrlKey ? "word" : "character";
|
|
const alter = evt.shiftKey ? "extend" : "move";
|
|
|
|
switch (evt.code) {
|
|
case "ArrowRight":
|
|
selection.modify(alter, "right", granularity);
|
|
evt.preventDefault();
|
|
return;
|
|
case "ArrowLeft":
|
|
selection.modify(alter, "left", granularity);
|
|
evt.preventDefault();
|
|
return;
|
|
}
|
|
}
|
|
|
|
triggerChangeTimer(currentField);
|
|
}
|
|
|
|
export function onKeyUp(evt: KeyboardEvent): void {
|
|
const currentField = evt.currentTarget as EditingArea;
|
|
|
|
// Avoid div element on remove
|
|
if (evt.code === "Enter" || evt.code === "Backspace") {
|
|
const anchor = currentField.getSelection().anchorNode as Node;
|
|
|
|
if (
|
|
nodeIsElement(anchor) &&
|
|
anchor.tagName === "DIV" &&
|
|
!(anchor instanceof EditingArea) &&
|
|
anchor.childElementCount === 1 &&
|
|
anchor.children[0].tagName === "BR"
|
|
) {
|
|
anchor.replaceWith(anchor.children[0]);
|
|
}
|
|
}
|
|
}
|