61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
|
import type { EditingArea } from ".";
|
||
|
|
||
|
import { bridgeCommand } from "./lib";
|
||
|
import { enableButtons, disableButtons } from "./toolbar";
|
||
|
import { saveField } from "./changeTimer";
|
||
|
|
||
|
function isElementInViewport(element: Element): boolean {
|
||
|
const rect = element.getBoundingClientRect();
|
||
|
|
||
|
return (
|
||
|
rect.top >= 0 &&
|
||
|
rect.left >= 0 &&
|
||
|
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
||
|
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function caretToEnd(currentField: EditingArea): void {
|
||
|
const range = document.createRange();
|
||
|
range.selectNodeContents(currentField.editable);
|
||
|
range.collapse(false);
|
||
|
const selection = currentField.getSelection();
|
||
|
selection.removeAllRanges();
|
||
|
selection.addRange(range);
|
||
|
}
|
||
|
|
||
|
// For distinguishing focus by refocusing window from deliberate focus
|
||
|
let previousActiveElement: EditingArea | null = null;
|
||
|
|
||
|
export function onFocus(evt: FocusEvent): void {
|
||
|
const currentField = evt.currentTarget as EditingArea;
|
||
|
|
||
|
if (currentField === previousActiveElement) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
currentField.focusEditable();
|
||
|
bridgeCommand(`focus:${currentField.ord}`);
|
||
|
enableButtons();
|
||
|
// do this twice so that there's no flicker on newer versions
|
||
|
caretToEnd(currentField);
|
||
|
// scroll if bottom of element off the screen
|
||
|
if (!isElementInViewport(currentField)) {
|
||
|
currentField.scrollIntoView(false /* alignToBottom */);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function onBlur(evt: FocusEvent): void {
|
||
|
const currentField = evt.currentTarget as EditingArea;
|
||
|
|
||
|
if (currentField === previousActiveElement) {
|
||
|
// other widget or window focused; current field unchanged
|
||
|
saveField(currentField, "key");
|
||
|
previousActiveElement = currentField;
|
||
|
} else {
|
||
|
saveField(currentField, "blur");
|
||
|
disableButtons();
|
||
|
previousActiveElement = null;
|
||
|
}
|
||
|
}
|