mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 15:02:21 -04:00
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:
parent
5963791d85
commit
55c64e5b54
2 changed files with 48 additions and 31 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
if (selection.anchorNode === handle.firstChild && isSelectionCollapsed(selection)) {
|
||||||
|
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) {
|
for (const handle of handles) {
|
||||||
const selection = getSelection(handle)!;
|
const selection = getSelection(handle)!;
|
||||||
|
|
||||||
if (
|
if (selection.rangeCount === 0) {
|
||||||
selection.anchorNode === handle.firstChild &&
|
return;
|
||||||
isSelectionCollapsed(selection)
|
|
||||||
) {
|
|
||||||
handle.notifyMoveIn(selection.anchorOffset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkWhetherMovingIntoHandle(selection, handle);
|
||||||
|
checkWhetherSelectingHandle(selection, handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue