🐛 table cell 三击/ctrl+k

This commit is contained in:
Vanessa 2022-09-19 16:47:38 +08:00
parent 1fedca6929
commit c0c795c214
8 changed files with 51 additions and 57 deletions

View file

@ -1,5 +1,6 @@
import {ToolbarItem} from "./ToolbarItem"; import {ToolbarItem} from "./ToolbarItem";
import {hintRef} from "../hint/extend"; import {hintRef} from "../hint/extend";
import {fixTableRange} from "../util/selection";
export class BlockRef extends ToolbarItem { export class BlockRef extends ToolbarItem {
public element: HTMLElement; public element: HTMLElement;
@ -8,6 +9,7 @@ export class BlockRef extends ToolbarItem {
super(protyle, menuItem); super(protyle, menuItem);
// 不能用 getEventName否则会导致光标位置变动到点击的文档中 // 不能用 getEventName否则会导致光标位置变动到点击的文档中
this.element.addEventListener("click", (event: MouseEvent & { changedTouches: MouseEvent[] }) => { this.element.addEventListener("click", (event: MouseEvent & { changedTouches: MouseEvent[] }) => {
fixTableRange(protyle.toolbar.range);
hintRef(protyle.toolbar.range.toString(), protyle, true); hintRef(protyle.toolbar.range.toString(), protyle, true);
protyle.toolbar.element.classList.add("fn__none"); protyle.toolbar.element.classList.add("fn__none");
event.stopPropagation(); event.stopPropagation();

View file

@ -4,6 +4,7 @@ import {updateTransaction} from "../wysiwyg/transaction";
import {hasClosestBlock} from "../util/hasClosest"; import {hasClosestBlock} from "../util/hasClosest";
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock"; import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
import {mathRender} from "../markdown/mathRender"; import {mathRender} from "../markdown/mathRender";
import {fixTableRange} from "../util/selection";
export class InlineMath extends ToolbarItem { export class InlineMath extends ToolbarItem {
public element: HTMLElement; public element: HTMLElement;
@ -19,10 +20,11 @@ export class InlineMath extends ToolbarItem {
if (!nodeElement) { if (!nodeElement) {
return; return;
} }
if (!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) { fixTableRange(range);
if (!["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) {
range.setStartBefore(range.startContainer.parentElement); range.setStartBefore(range.startContainer.parentElement);
} }
if (!["DIV", "TD", "TH"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) { if (!["DIV", "TD", "TH", "TR"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) {
range.setEndAfter(range.endContainer.parentElement); range.setEndAfter(range.endContainer.parentElement);
} }
const wbrElement = document.createElement("wbr"); const wbrElement = document.createElement("wbr");

View file

@ -3,6 +3,7 @@ import * as dayjs from "dayjs";
import {updateTransaction} from "../wysiwyg/transaction"; import {updateTransaction} from "../wysiwyg/transaction";
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest"; import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock"; import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
import {fixTableRange} from "../util/selection";
export class InlineMemo extends ToolbarItem { export class InlineMemo extends ToolbarItem {
public element: HTMLElement; public element: HTMLElement;
@ -28,10 +29,12 @@ export class InlineMemo extends ToolbarItem {
return; return;
} }
if (!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) { fixTableRange(range);
if (!["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) {
range.setStartBefore(range.startContainer.parentElement); range.setStartBefore(range.startContainer.parentElement);
} }
if (!["DIV", "TD", "TH"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) { if (!["DIV", "TD", "TH", "TR"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) {
range.setEndAfter(range.endContainer.parentElement); range.setEndAfter(range.endContainer.parentElement);
} }
const wbrElement = document.createElement("wbr"); const wbrElement = document.createElement("wbr");

View file

@ -5,7 +5,7 @@ import * as dayjs from "dayjs";
import {updateTransaction} from "../wysiwyg/transaction"; import {updateTransaction} from "../wysiwyg/transaction";
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest"; import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock"; import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
import {focusByRange, focusByWbr} from "../util/selection"; import {fixTableRange, focusByRange, focusByWbr} from "../util/selection";
export class Link extends ToolbarItem { export class Link extends ToolbarItem {
public element: HTMLElement; public element: HTMLElement;
@ -28,10 +28,12 @@ export class Link extends ToolbarItem {
return; return;
} }
if (!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) { fixTableRange(range);
if (!["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName) && range.startOffset === 0 && !hasPreviousSibling(range.startContainer)) {
range.setStartBefore(range.startContainer.parentElement); range.setStartBefore(range.startContainer.parentElement);
} }
if (!["DIV", "TD", "TH"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) { if (!["DIV", "TD", "TH", "TR"].includes(range.endContainer.parentElement.tagName) && range.endOffset === range.endContainer.textContent.length && !hasNextSibling(range.endContainer)) {
range.setEndAfter(range.endContainer.parentElement); range.setEndAfter(range.endContainer.parentElement);
} }
const wbrElement = document.createElement("wbr"); const wbrElement = document.createElement("wbr");
@ -40,6 +42,7 @@ export class Link extends ToolbarItem {
const newElement = document.createElement("span"); const newElement = document.createElement("span");
newElement.setAttribute("data-type", "a"); newElement.setAttribute("data-type", "a");
newElement.setAttribute("data-href", "");
const rangeString = range.toString(); const rangeString = range.toString();
newElement.textContent = rangeString; newElement.textContent = rangeString;
range.extractContents(); range.extractContents();

View file

@ -2,6 +2,7 @@ import {Divider} from "./Divider";
import {Font, hasSameTextStyle, setFontStyle} from "./Font"; import {Font, hasSameTextStyle, setFontStyle} from "./Font";
import {ToolbarItem} from "./ToolbarItem"; import {ToolbarItem} from "./ToolbarItem";
import { import {
fixTableRange,
focusByRange, focusByRange,
focusByWbr, focusByWbr,
focusSideBlock, focusSideBlock,
@ -244,34 +245,7 @@ export class Toolbar {
} }
const rangeTypes = this.getCurrentType(this.range); const rangeTypes = this.getCurrentType(this.range);
const selectText = this.range.toString(); const selectText = this.range.toString();
fixTableRange(this.range);
// table 选中处理
const tableElement = hasClosestByAttribute(this.range.startContainer, "data-type", "NodeTable");
if (selectText !== "" && tableElement && this.range.commonAncestorContainer.nodeType !== 3) {
const parentTag = (this.range.commonAncestorContainer as Element).tagName;
if (parentTag !== "TH" && parentTag !== "TD") {
const startCellElement = hasClosestByMatchTag(this.range.startContainer, "TD") || hasClosestByMatchTag(this.range.startContainer, "TH");
const endCellElement = hasClosestByMatchTag(this.range.endContainer, "TD") || hasClosestByMatchTag(this.range.endContainer, "TH");
if (!startCellElement && !endCellElement) {
const cellElement = tableElement.querySelector("th") || tableElement.querySelector("td");
this.range.setStartBefore(cellElement.firstChild);
this.range.setEndAfter(cellElement.lastChild);
} else if (startCellElement &&
// 不能包含自身元素,否则对 cell 中的部分文字两次高亮后就会选中整个 cell。 https://github.com/siyuan-note/siyuan/issues/3649 第二点
!startCellElement.contains(this.range.endContainer)) {
const cloneRange = this.range.cloneRange();
this.range.setEndAfter(startCellElement.lastChild);
if (this.range.toString() === "" && endCellElement) {
this.range.setEnd(cloneRange.endContainer, cloneRange.endOffset);
this.range.setStartBefore(endCellElement.lastChild);
}
if (this.range.toString() === "") {
return;
}
}
}
}
let previousElement: HTMLElement; let previousElement: HTMLElement;
let nextElement: HTMLElement; let nextElement: HTMLElement;
let previousIndex: number; let previousIndex: number;

View file

@ -3,7 +3,7 @@ import * as dayjs from "dayjs";
import {removeEmbed} from "../wysiwyg/removeEmbed"; import {removeEmbed} from "../wysiwyg/removeEmbed";
import {transaction, updateTransaction} from "../wysiwyg/transaction"; import {transaction, updateTransaction} from "../wysiwyg/transaction";
import {getContenteditableElement} from "../wysiwyg/getBlock"; import {getContenteditableElement} from "../wysiwyg/getBlock";
import {focusBlock, getEditorRange, focusByWbr} from "./selection"; import {focusBlock, getEditorRange, focusByWbr, fixTableRange} from "./selection";
import {mathRender} from "../markdown/mathRender"; import {mathRender} from "../markdown/mathRender";
import {Constants} from "../../constants"; import {Constants} from "../../constants";
@ -12,24 +12,8 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false, spl
return; return;
} }
const range = getEditorRange(protyle.wysiwyg.element); const range = getEditorRange(protyle.wysiwyg.element);
// table 选中处理 https://ld246.com/article/1624269001599 fixTableRange(range);
const tableElement = hasClosestByAttribute(range.startContainer, "data-type", "NodeTable"); if (hasClosestByAttribute(range.startContainer, "data-type", "NodeTable") && !isBlock) {
if (range.toString() !== "" && tableElement && range.commonAncestorContainer.nodeType !== 3) {
const parentTag = (range.commonAncestorContainer as Element).tagName;
if (parentTag !== "TH" && parentTag !== "TD") {
let cellElement = hasClosestByMatchTag(range.startContainer, "TD") || hasClosestByMatchTag(range.startContainer, "TH");
if (!cellElement) {
cellElement = tableElement.querySelector("th") || tableElement.querySelector("td");
range.setStartBefore(cellElement.firstChild);
}
if (cellElement.lastChild) {
range.setEndAfter(cellElement.lastChild);
} else {
range.collapse(true);
}
}
}
if (tableElement && !isBlock) {
html = protyle.lute.BlockDOM2InlineBlockDOM(html); html = protyle.lute.BlockDOM2InlineBlockDOM(html);
} }
let blockElement = hasClosestBlock(range.startContainer) as Element; let blockElement = hasClosestBlock(range.startContainer) as Element;

View file

@ -5,7 +5,7 @@ import {
hasPreviousSibling, hasPreviousSibling,
isNotEditBlock isNotEditBlock
} from "../wysiwyg/getBlock"; } from "../wysiwyg/getBlock";
import {hasClosestByMatchTag} from "./hasClosest"; import {hasClosestByAttribute, hasClosestByMatchTag} from "./hasClosest";
import {countBlockWord, countSelectWord} from "../../layout/status"; import {countBlockWord, countSelectWord} from "../../layout/status";
const selectIsEditor = (editor: Element, range?: Range) => { const selectIsEditor = (editor: Element, range?: Range) => {
@ -21,6 +21,32 @@ const selectIsEditor = (editor: Element, range?: Range) => {
return editor.isEqualNode(container) || editor.contains(container); return editor.isEqualNode(container) || editor.contains(container);
}; };
// table 选中处理
export const fixTableRange = (range:Range) => {
const tableElement = hasClosestByAttribute(range.startContainer, "data-type", "NodeTable");
if (range.toString() !== "" && tableElement && range.commonAncestorContainer.nodeType !== 3) {
const parentTag = (range.commonAncestorContainer as Element).tagName;
if (parentTag !== "TH" && parentTag !== "TD") {
const startCellElement = hasClosestByMatchTag(range.startContainer, "TD") || hasClosestByMatchTag(range.startContainer, "TH");
const endCellElement = hasClosestByMatchTag(range.endContainer, "TD") || hasClosestByMatchTag(range.endContainer, "TH");
if (!startCellElement && !endCellElement) {
const cellElement = tableElement.querySelector("th") || tableElement.querySelector("td");
range.setStart(cellElement.firstChild, 0);
range.setEnd(cellElement.lastChild, cellElement.lastChild.textContent.length);
} else if (startCellElement &&
// 不能包含自身元素,否则对 cell 中的部分文字两次高亮后就会选中整个 cell。 https://github.com/siyuan-note/siyuan/issues/3649 第二点
!startCellElement.contains(range.endContainer)) {
const cloneRange = range.cloneRange();
range.setEnd(startCellElement.lastChild, startCellElement.lastChild.textContent.length);
if (range.toString() === "" && endCellElement) {
range.setStart(endCellElement.firstChild, 0);
range.setEnd(cloneRange.endContainer, cloneRange.endOffset);
}
}
}
}
}
export const selectAll = (protyle: IProtyle, nodeElement: Element, range: Range) => { export const selectAll = (protyle: IProtyle, nodeElement: Element, range: Range) => {
const editElement = getContenteditableElement(nodeElement); const editElement = getContenteditableElement(nodeElement);
if (editElement) { if (editElement) {

View file

@ -225,7 +225,7 @@ export class WYSIWYG {
if (range.startContainer.parentElement.parentElement.getAttribute("data-type") === "NodeHeading") { if (range.startContainer.parentElement.parentElement.getAttribute("data-type") === "NodeHeading") {
// 复制标题 https://github.com/siyuan-note/insider/issues/297 // 复制标题 https://github.com/siyuan-note/insider/issues/297
tempElement.append(range.startContainer.parentElement.parentElement.cloneNode(true)); tempElement.append(range.startContainer.parentElement.parentElement.cloneNode(true));
} else if (!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName)) { } else if (!["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName)) {
// 复制行内元素 https://github.com/siyuan-note/insider/issues/191 // 复制行内元素 https://github.com/siyuan-note/insider/issues/191
tempElement.append(range.startContainer.parentElement.cloneNode(true)); tempElement.append(range.startContainer.parentElement.cloneNode(true));
} else { } else {
@ -986,7 +986,7 @@ export class WYSIWYG {
transaction(protyle, doOperations, undoOperations); transaction(protyle, doOperations, undoOperations);
} else if (range.toString() !== "" && startContainer.isSameNode(range.endContainer) && range.startContainer.nodeType === 3 } else if (range.toString() !== "" && startContainer.isSameNode(range.endContainer) && range.startContainer.nodeType === 3
&& range.endOffset === range.endContainer.textContent.length && range.startOffset === 0 && && range.endOffset === range.endContainer.textContent.length && range.startOffset === 0 &&
!["DIV", "TD", "TH"].includes(range.startContainer.parentElement.tagName)) { !["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName)) {
// 选中整个内联元素 // 选中整个内联元素
tempElement.append(range.startContainer.parentElement); tempElement.append(range.startContainer.parentElement);
} else if (selectImgElement) { } else if (selectImgElement) {