Fix Mathjax sometimes being deleted even though it's not selected (#1696)

* Fix frame element being deleted, when a frame handle is deleted from while selected

* Fix mixing up preceding/following
This commit is contained in:
Henrik Giesel 2022-02-27 08:58:01 +01:00 committed by GitHub
parent 5963791d85
commit 55c64e5b54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 31 deletions

View file

@ -13,7 +13,7 @@ import {
import { on } from "../lib/events"; import { on } from "../lib/events";
import type { FrameHandle } from "./frame-handle"; import type { FrameHandle } from "./frame-handle";
import { import {
checkWhetherMovingIntoHandle, checkHandles,
frameElementTagName, frameElementTagName,
FrameEnd, FrameEnd,
FrameStart, FrameStart,
@ -32,43 +32,39 @@ function restoreFrameHandles(mutations: MutationRecord[]): void {
continue; continue;
} }
/** // In some rare cases, nodes might be inserted into the frame itself.
* In some rare cases, nodes might be inserted into the frame itself. // For example after using execCommand.
* For example after using execCommand. const placement = framed.compareDocumentPosition(node);
*/
const placement = node.compareDocumentPosition(framed);
if (placement & Node.DOCUMENT_POSITION_FOLLOWING) { if (placement & Node.DOCUMENT_POSITION_PRECEDING) {
referenceNode = moveChildOutOfElement(frameElement, node, "afterend");
continue;
} else if (placement & Node.DOCUMENT_POSITION_PRECEDING) {
referenceNode = moveChildOutOfElement( referenceNode = moveChildOutOfElement(
frameElement, frameElement,
node, node,
"beforebegin", "beforebegin",
); );
continue; } else if (placement & Node.DOCUMENT_POSITION_FOLLOWING) {
referenceNode = moveChildOutOfElement(frameElement, node, "afterend");
} }
} }
for (const node of mutation.removedNodes) { for (const node of mutation.removedNodes) {
if ( if (!isFrameHandle(node)) {
/* avoid triggering when (un)mounting whole frame */
mutations.length === 1 &&
nodeIsElement(node) &&
isFrameHandle(node)
) {
/* When deleting from _outer_ position in FrameHandle to _inner_ position */
frameElement.remove();
continue; continue;
} }
if ( if (
nodeIsElement(node) && /* avoid triggering when (un)mounting whole frame */
isFrameHandle(node) && mutations.length === 1 &&
frameElement.isConnected && !node.partiallySelected
!frameElement.block
) { ) {
// Similar to a "movein", this could be considered a
// "deletein" event and could get some special treatment, e.g.
// first highlight the entire frame-element.
frameElement.remove();
continue;
}
if (frameElement.isConnected && !frameElement.block) {
frameElement.refreshHandles(); frameElement.refreshHandles();
continue; continue;
} }
@ -248,7 +244,7 @@ function checkIfInsertingLineBreakAdjacentToBlockFrame() {
} }
function onSelectionChange() { function onSelectionChange() {
checkWhetherMovingIntoHandle(); checkHandles();
checkIfInsertingLineBreakAdjacentToBlockFrame(); checkIfInsertingLineBreakAdjacentToBlockFrame();
} }
@ -259,7 +255,7 @@ document.addEventListener("selectionchange", onSelectionChange);
* <anki-frame> * <anki-frame>
* <frame-handle-start> </frame-handle-start> * <frame-handle-start> </frame-handle-start>
* <your-element ... /> * <your-element ... />
* <frame-handle-end> </frame-handle-start> * <frame-handle-end> </frame-handle-end>
* </anki-frame> * </anki-frame>
*/ */
export function frameElement(element: HTMLElement, block: boolean): FrameElement { export function frameElement(element: HTMLElement, block: boolean): FrameElement {

View file

@ -120,6 +120,14 @@ export abstract class FrameHandle extends HTMLElement {
return ["data-frames"]; return ["data-frames"];
} }
/**
* When a deletion is trigger with a FrameHandle selected, it will be treated
* differently depending on whether it is selected:
* - If partially selected, it should be restored (unless the frame element
* is also selected).
* - Otherwise, it should be deleted along with the frame element.
*/
partiallySelected = false;
frames?: string; frames?: string;
constructor() { constructor() {
@ -273,15 +281,28 @@ export class FrameEnd extends FrameHandle {
} }
} }
export function checkWhetherMovingIntoHandle(): void { function checkWhetherMovingIntoHandle(selection: Selection, handle: FrameHandle): void {
for (const handle of handles) { if (selection.anchorNode === handle.firstChild && isSelectionCollapsed(selection)) {
const selection = getSelection(handle)!;
if (
selection.anchorNode === handle.firstChild &&
isSelectionCollapsed(selection)
) {
handle.notifyMoveIn(selection.anchorOffset); handle.notifyMoveIn(selection.anchorOffset);
} }
} }
function checkWhetherSelectingHandle(selection: Selection, handle: FrameHandle): void {
handle.partiallySelected =
handle.firstChild && !isSelectionCollapsed(selection)
? selection.containsNode(handle.firstChild)
: false;
}
export function checkHandles(): void {
for (const handle of handles) {
const selection = getSelection(handle)!;
if (selection.rangeCount === 0) {
return;
}
checkWhetherMovingIntoHandle(selection, handle);
checkWhetherSelectingHandle(selection, handle);
}
} }