mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-20 16:40:13 +01:00
🐛 table cell 三击/ctrl+k
This commit is contained in:
parent
1fedca6929
commit
c0c795c214
8 changed files with 51 additions and 57 deletions
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue