mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 23:12:21 -04:00
Rework focusing code to fix two issues:
1. Clicking away from the editor window, and back on it should not focus old field 2. Clicking on a field, which is not fully visible, should scroll it into view
This commit is contained in:
parent
b56b3fd74a
commit
ee194e951c
2 changed files with 30 additions and 14 deletions
|
@ -1,18 +1,26 @@
|
||||||
import type { EditingArea } from ".";
|
import type { EditingArea, EditorField } from ".";
|
||||||
|
|
||||||
import { bridgeCommand } from "./lib";
|
import { bridgeCommand } from "./lib";
|
||||||
import { enableButtons, disableButtons } from "./toolbar";
|
import { enableButtons, disableButtons } from "./toolbar";
|
||||||
import { saveField } from "./changeTimer";
|
import { saveField } from "./changeTimer";
|
||||||
|
|
||||||
function isElementInViewport(element: Element): boolean {
|
enum ViewportRelativePosition {
|
||||||
|
Contained,
|
||||||
|
ExceedTop,
|
||||||
|
ExceedBottom,
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFieldInViewport(
|
||||||
|
element: Element,
|
||||||
|
toolbarHeight: number
|
||||||
|
): ViewportRelativePosition {
|
||||||
const rect = element.getBoundingClientRect();
|
const rect = element.getBoundingClientRect();
|
||||||
|
|
||||||
return (
|
return rect.top <= toolbarHeight
|
||||||
rect.top >= 0 &&
|
? ViewportRelativePosition.ExceedTop
|
||||||
rect.left >= 0 &&
|
: rect.bottom >= (window.innerHeight || document.documentElement.clientHeight)
|
||||||
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
? ViewportRelativePosition.ExceedBottom
|
||||||
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
: ViewportRelativePosition.Contained;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function caretToEnd(currentField: EditingArea): void {
|
function caretToEnd(currentField: EditingArea): void {
|
||||||
|
@ -34,21 +42,29 @@ export function onFocus(evt: FocusEvent): void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editorField = currentField.parentElement! as EditorField;
|
||||||
|
const toolbarHeight = document.getElementById("topbutsOuter")!.clientHeight;
|
||||||
|
switch (isFieldInViewport(editorField, toolbarHeight)) {
|
||||||
|
case ViewportRelativePosition.ExceedBottom:
|
||||||
|
editorField.scrollIntoView(false);
|
||||||
|
break;
|
||||||
|
case ViewportRelativePosition.ExceedTop:
|
||||||
|
editorField.scrollIntoView(true);
|
||||||
|
window.scrollBy(0, -toolbarHeight);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
currentField.focusEditable();
|
currentField.focusEditable();
|
||||||
bridgeCommand(`focus:${currentField.ord}`);
|
bridgeCommand(`focus:${currentField.ord}`);
|
||||||
enableButtons();
|
enableButtons();
|
||||||
// do this twice so that there's no flicker on newer versions
|
// do this twice so that there's no flicker on newer versions
|
||||||
caretToEnd(currentField);
|
caretToEnd(currentField);
|
||||||
// scroll if bottom of element off the screen
|
|
||||||
if (!isElementInViewport(currentField)) {
|
|
||||||
currentField.scrollIntoView(false /* alignToBottom */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function onBlur(evt: FocusEvent): void {
|
export function onBlur(evt: FocusEvent): void {
|
||||||
const currentField = evt.currentTarget as EditingArea;
|
const currentField = evt.currentTarget as EditingArea;
|
||||||
|
|
||||||
if (currentField === previousActiveElement) {
|
if (currentField === document.activeElement) {
|
||||||
// other widget or window focused; current field unchanged
|
// other widget or window focused; current field unchanged
|
||||||
saveField(currentField, "key");
|
saveField(currentField, "key");
|
||||||
previousActiveElement = currentField;
|
previousActiveElement = currentField;
|
||||||
|
|
|
@ -207,7 +207,7 @@ export class EditingArea extends HTMLDivElement {
|
||||||
|
|
||||||
customElements.define("anki-editing-area", EditingArea, { extends: "div" });
|
customElements.define("anki-editing-area", EditingArea, { extends: "div" });
|
||||||
|
|
||||||
class EditorField extends HTMLDivElement {
|
export class EditorField extends HTMLDivElement {
|
||||||
labelContainer: HTMLDivElement;
|
labelContainer: HTMLDivElement;
|
||||||
label: HTMLSpanElement;
|
label: HTMLSpanElement;
|
||||||
editingArea: EditingArea;
|
editingArea: EditingArea;
|
||||||
|
|
Loading…
Reference in a new issue