Fix headline blur on click and improve editor focus

This commit is contained in:
Jonatan Kłosko 2021-11-18 17:34:04 +01:00
parent 551444ec76
commit bfe2036d34
2 changed files with 48 additions and 45 deletions

View file

@ -231,43 +231,47 @@ function handleElementFocused(hook, focusableId, scroll) {
} }
function handleInsertModeChanged(hook, insertMode) { function handleInsertModeChanged(hook, insertMode) {
if (hook.state.isFocused) { const input = getInput(hook);
if (hook.state.isFocused && !hook.state.insertMode && insertMode) {
hook.state.insertMode = insertMode; hook.state.insertMode = insertMode;
if (hook.state.liveEditor) { if (hook.state.liveEditor) {
if (hook.state.insertMode) { // For some reason, when clicking the editor for a brief moment it is
// already focused and the cursor is in the previous location, which
// makes the browser immediately scroll there. We blur the editor,
// then wait for the editor to update the cursor position, finally
// we focus the editor and scroll if the cursor is not in the view
// (when entering insert mode with "i").
hook.state.liveEditor.blur();
setTimeout(() => {
hook.state.liveEditor.focus(); hook.state.liveEditor.focus();
// The insert mode may be enabled as a result of clicking the editor, scrollIntoView(document.activeElement, {
// in which case we want to wait until editor handles the click scrollMode: "if-needed",
// and sets new cursor position. behavior: "smooth",
// To achieve this, we simply put this task at the end of event loop, block: "center",
// ensuring all click handlers are executed first. });
setTimeout(() => { }, 0);
scrollIntoView(document.activeElement, {
scrollMode: "if-needed",
behavior: "smooth",
block: "center",
});
}, 0);
broadcastSelection(hook); broadcastSelection(hook);
} else {
hook.state.liveEditor.blur();
}
} }
const input = getInput(hook); if (input) {
input.focus();
// selectionStart is only supported on text based input
if (input.selectionStart !== null) {
input.selectionStart = input.selectionEnd = input.value.length;
}
}
} else if (hook.state.insertMode && !insertMode) {
hook.state.insertMode = insertMode;
if (hook.state.liveEditor) {
hook.state.liveEditor.blur();
}
if (input) { if (input) {
if (hook.state.insertMode) { input.blur();
input.focus();
// selectionStart is only supported on text based input
if (input.selectionStart !== null) {
input.selectionStart = input.selectionEnd = input.value.length;
}
} else {
input.blur();
}
} }
} }
} }

View file

@ -95,25 +95,24 @@ function handleElementFocused(hook, cellId, scroll) {
} }
function handleInsertModeChanged(hook, insertMode) { function handleInsertModeChanged(hook, insertMode) {
if (hook.state.isFocused) { const heading = getHeading(hook);
if (hook.state.isFocused && !hook.state.insertMode && insertMode) {
hook.state.insertMode = insertMode; hook.state.insertMode = insertMode;
const heading = getHeading(hook); // While in insert mode, ignore the incoming changes
hook.el.setAttribute("phx-update", "ignore");
if (hook.state.insertMode) { heading.setAttribute("contenteditable", "true");
// While in insert mode, ignore the incoming changes heading.focus();
hook.el.setAttribute("phx-update", "ignore"); moveSelectionToEnd(heading);
heading.setAttribute("contenteditable", "true"); } else if (hook.state.insertMode && !insertMode) {
heading.focus(); hook.state.insertMode = insertMode;
moveSelectionToEnd(heading); heading.removeAttribute("contenteditable");
} else { hook.el.removeAttribute("phx-update");
heading.removeAttribute("contenteditable"); hook.pushEvent(hook.props.onValueChange, {
hook.el.removeAttribute("phx-update"); value: headingValue(heading),
hook.pushEvent(hook.props.onValueChange, { metadata: hook.props.metadata,
value: headingValue(heading), });
metadata: hook.props.metadata,
});
}
} }
} }