2022-05-26 15:18:53 +08:00
|
|
|
|
import {updateTransaction} from "../wysiwyg/transaction";
|
|
|
|
|
|
import {getSelectionOffset, focusByWbr, focusByRange, focusBlock} from "./selection";
|
|
|
|
|
|
import {hasClosestBlock, hasClosestByMatchTag} from "./hasClosest";
|
|
|
|
|
|
import {matchHotKey} from "./hotKey";
|
2023-11-12 12:28:20 +08:00
|
|
|
|
import {isNotCtrl} from "./compatibility";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
import {scrollCenter} from "../../util/highlightById";
|
2022-09-28 11:44:55 +08:00
|
|
|
|
import {insertEmptyBlock} from "../../block/util";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
2023-09-26 11:29:18 +08:00
|
|
|
|
const scrollToView = (nodeElement: Element, rowElement: HTMLElement, protyle: IProtyle) => {
|
|
|
|
|
|
if (nodeElement.getAttribute("custom-pinthead") === "true") {
|
|
|
|
|
|
const tableElement = nodeElement.querySelector("table");
|
|
|
|
|
|
if (tableElement.clientHeight + tableElement.scrollTop < rowElement.offsetTop + rowElement.clientHeight) {
|
|
|
|
|
|
tableElement.scrollTop = rowElement.offsetTop - tableElement.clientHeight + rowElement.clientHeight + 1;
|
|
|
|
|
|
} else if (tableElement.scrollTop > rowElement.offsetTop - rowElement.clientHeight) {
|
|
|
|
|
|
tableElement.scrollTop = rowElement.offsetTop - rowElement.clientHeight + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
scrollCenter(protyle, rowElement);
|
|
|
|
|
|
}
|
2023-09-26 12:43:26 +08:00
|
|
|
|
};
|
2023-09-26 11:29:18 +08:00
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
export const getColIndex = (cellElement: HTMLElement) => {
|
|
|
|
|
|
let previousElement = cellElement.previousElementSibling;
|
|
|
|
|
|
let index = 0;
|
|
|
|
|
|
while (previousElement) {
|
|
|
|
|
|
index++;
|
|
|
|
|
|
previousElement = previousElement.previousElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
return index;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 光标设置到前一个表格中
|
|
|
|
|
|
const goPreviousCell = (cellElement: HTMLElement, range: Range, isSelected = true) => {
|
|
|
|
|
|
let previousElement = cellElement.previousElementSibling;
|
|
|
|
|
|
if (!previousElement) {
|
|
|
|
|
|
if (cellElement.parentElement.previousElementSibling) {
|
|
|
|
|
|
previousElement = cellElement.parentElement.previousElementSibling.lastElementChild;
|
|
|
|
|
|
} else if (cellElement.parentElement.parentElement.tagName === "TBODY" &&
|
|
|
|
|
|
cellElement.parentElement.parentElement.previousElementSibling) {
|
|
|
|
|
|
previousElement = cellElement.parentElement
|
|
|
|
|
|
.parentElement.previousElementSibling.lastElementChild.lastElementChild;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
previousElement = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (previousElement) {
|
|
|
|
|
|
range.selectNodeContents(previousElement);
|
|
|
|
|
|
if (!isSelected) {
|
|
|
|
|
|
range.collapse(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
focusByRange(range);
|
|
|
|
|
|
}
|
|
|
|
|
|
return previousElement;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-06-12 22:06:19 +08:00
|
|
|
|
export const setTableAlign = (protyle: IProtyle, cellElements: HTMLElement[], nodeElement: Element, type: string, range: Range) => {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const html = nodeElement.outerHTML;
|
|
|
|
|
|
|
|
|
|
|
|
const tableElement = nodeElement.querySelector("table");
|
|
|
|
|
|
const columnCnt = tableElement.rows[0].cells.length;
|
|
|
|
|
|
const rowCnt = tableElement.rows.length;
|
2022-09-28 10:59:12 +08:00
|
|
|
|
const currentColumns: number[] = [];
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < rowCnt; i++) {
|
|
|
|
|
|
for (let j = 0; j < columnCnt; j++) {
|
2022-06-12 22:06:19 +08:00
|
|
|
|
if (tableElement.rows[i].cells[j].isSameNode(cellElements[currentColumns.length])) {
|
|
|
|
|
|
currentColumns.push(j);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-06-12 22:06:19 +08:00
|
|
|
|
if (currentColumns.length > 0) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
for (let k = 0; k < rowCnt; k++) {
|
2022-06-12 22:06:19 +08:00
|
|
|
|
currentColumns.forEach(item => {
|
|
|
|
|
|
tableElement.rows[k].cells[item].setAttribute("align", type);
|
2022-06-14 00:43:25 +08:00
|
|
|
|
});
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
2022-10-11 11:19:36 +08:00
|
|
|
|
focusByWbr(tableElement, range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const insertRow = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
2022-09-28 12:14:18 +08:00
|
|
|
|
const wbrElement = document.createElement("wbr");
|
2022-09-28 12:13:15 +08:00
|
|
|
|
range.insertNode(wbrElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const html = nodeElement.outerHTML;
|
2022-09-28 12:13:15 +08:00
|
|
|
|
wbrElement.remove();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
|
|
|
|
|
let rowHTML = "";
|
|
|
|
|
|
for (let m = 0; m < cellElement.parentElement.childElementCount; m++) {
|
2023-03-13 14:52:28 +08:00
|
|
|
|
rowHTML += `<td align="${cellElement.parentElement.children[m].getAttribute("align") || ""}"></td>`;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2022-09-28 12:13:15 +08:00
|
|
|
|
let newRowElememt: HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (cellElement.tagName === "TH") {
|
|
|
|
|
|
const tbodyElement = nodeElement.querySelector("tbody");
|
|
|
|
|
|
if (tbodyElement) {
|
|
|
|
|
|
tbodyElement.insertAdjacentHTML("afterbegin", `<tr>${rowHTML}</tr>`);
|
2022-09-28 12:13:15 +08:00
|
|
|
|
newRowElememt = tbodyElement.firstElementChild as HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
cellElement.parentElement.parentElement.insertAdjacentHTML("afterend", `<tbody><tr>${rowHTML}</tr></tbody>`);
|
2022-09-28 12:13:15 +08:00
|
|
|
|
newRowElememt = cellElement.parentElement.parentElement.nextElementSibling.firstElementChild as HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
cellElement.parentElement.insertAdjacentHTML("afterend", `<tr>${rowHTML}</tr>`);
|
2022-09-28 12:13:15 +08:00
|
|
|
|
newRowElememt = cellElement.parentElement.nextElementSibling as HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2022-09-28 12:13:15 +08:00
|
|
|
|
range.selectNodeContents(newRowElememt.cells[getColIndex(cellElement)]);
|
|
|
|
|
|
range.collapse(true);
|
2022-10-10 18:40:02 +08:00
|
|
|
|
focusByRange(range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
2023-09-26 11:29:18 +08:00
|
|
|
|
scrollToView(nodeElement, newRowElememt, protyle);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const insertRowAbove = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
2022-09-28 12:14:18 +08:00
|
|
|
|
const wbrElement = document.createElement("wbr");
|
2022-09-28 12:13:15 +08:00
|
|
|
|
range.insertNode(wbrElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const html = nodeElement.outerHTML;
|
2022-09-28 12:13:15 +08:00
|
|
|
|
wbrElement.remove();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let rowHTML = "";
|
|
|
|
|
|
let hasNone = false;
|
|
|
|
|
|
|
|
|
|
|
|
for (let m = 0; m < cellElement.parentElement.childElementCount; m++) {
|
|
|
|
|
|
const currentCellElement = cellElement.parentElement.children[m] as HTMLTableCellElement;
|
|
|
|
|
|
const className = currentCellElement.className;
|
|
|
|
|
|
if (className === "fn__none") {
|
|
|
|
|
|
hasNone = true;
|
|
|
|
|
|
}
|
2023-03-13 14:52:28 +08:00
|
|
|
|
// 不需要空格,否则列宽调整后在空格后插入图片会换行 https://github.com/siyuan-note/siyuan/issues/7631
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (cellElement.tagName === "TH") {
|
2023-03-13 14:52:28 +08:00
|
|
|
|
rowHTML += `<th class="${currentCellElement.className}" colspan="${currentCellElement.colSpan}" align="${currentCellElement.getAttribute("align")}"></th>`;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
2023-03-13 14:52:28 +08:00
|
|
|
|
rowHTML += `<td class="${currentCellElement.className}" colspan="${currentCellElement.colSpan}" align="${currentCellElement.getAttribute("align")}"></td>`;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (hasNone) {
|
|
|
|
|
|
let previousTrElement = cellElement.parentElement.previousElementSibling;
|
|
|
|
|
|
let rowCount = 1;
|
|
|
|
|
|
while (previousTrElement) {
|
|
|
|
|
|
rowCount++;
|
|
|
|
|
|
Array.from(previousTrElement.children).forEach((cell: HTMLTableCellElement) => {
|
|
|
|
|
|
if (cell.rowSpan >= rowCount && cell.rowSpan > 1) {
|
|
|
|
|
|
cell.rowSpan = cell.rowSpan + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
previousTrElement = previousTrElement.previousElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-09-28 12:14:18 +08:00
|
|
|
|
let newRowElememt: HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (cellElement.parentElement.parentElement.tagName === "THEAD" && !cellElement.parentElement.previousElementSibling) {
|
|
|
|
|
|
cellElement.parentElement.parentElement.insertAdjacentHTML("beforebegin", `<thead><tr>${rowHTML}</tr></thead>`);
|
2022-09-28 12:14:18 +08:00
|
|
|
|
newRowElememt = nodeElement.querySelector("thead tr");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
cellElement.parentElement.parentElement.nextElementSibling.insertAdjacentHTML("afterbegin", cellElement.parentElement.parentElement.innerHTML);
|
|
|
|
|
|
cellElement.parentElement.parentElement.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
cellElement.parentElement.insertAdjacentHTML("beforebegin", `<tr>${rowHTML}</tr>`);
|
2022-09-28 12:13:15 +08:00
|
|
|
|
newRowElememt = cellElement.parentElement.previousElementSibling as HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2022-09-28 12:13:15 +08:00
|
|
|
|
range.selectNodeContents(newRowElememt.cells[getColIndex(cellElement)]);
|
|
|
|
|
|
range.collapse(true);
|
2022-10-10 18:40:02 +08:00
|
|
|
|
focusByRange(range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
2023-09-26 11:29:18 +08:00
|
|
|
|
scrollToView(nodeElement, newRowElememt, protyle);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const insertColumn = (protyle: IProtyle, nodeElement: Element, cellElement: HTMLElement, type: InsertPosition, range: Range) => {
|
2022-09-28 12:14:18 +08:00
|
|
|
|
const wbrElement = document.createElement("wbr");
|
2022-09-28 12:13:15 +08:00
|
|
|
|
range.insertNode(wbrElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const html = nodeElement.outerHTML;
|
2022-09-28 12:13:15 +08:00
|
|
|
|
wbrElement.remove();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const index = getColIndex(cellElement);
|
|
|
|
|
|
const tableElement = nodeElement.querySelector("table");
|
|
|
|
|
|
for (let i = 0; i < tableElement.rows.length; i++) {
|
2022-10-10 18:40:02 +08:00
|
|
|
|
const colCellElement = tableElement.rows[i].cells[index];
|
2022-09-28 12:14:18 +08:00
|
|
|
|
const newCellElement = document.createElement(colCellElement.tagName);
|
2022-10-10 18:40:02 +08:00
|
|
|
|
colCellElement.insertAdjacentElement(type, newCellElement);
|
2022-09-28 12:13:15 +08:00
|
|
|
|
if (colCellElement.isSameNode(cellElement)) {
|
|
|
|
|
|
newCellElement.innerHTML = "<wbr> ";
|
2022-10-10 18:40:02 +08:00
|
|
|
|
// 滚动条横向定位
|
|
|
|
|
|
if (newCellElement.offsetLeft + newCellElement.clientWidth > nodeElement.firstElementChild.scrollLeft + nodeElement.firstElementChild.clientWidth) {
|
|
|
|
|
|
nodeElement.firstElementChild.scrollLeft = newCellElement.offsetLeft + newCellElement.clientWidth - nodeElement.firstElementChild.clientWidth;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
2022-09-28 12:13:15 +08:00
|
|
|
|
newCellElement.textContent = " ";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
tableElement.querySelectorAll("col")[index].insertAdjacentHTML(type, "<col>");
|
2022-09-28 12:13:15 +08:00
|
|
|
|
focusByWbr(nodeElement, range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const deleteRow = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
2022-06-10 16:35:08 +08:00
|
|
|
|
if (cellElement.parentElement.parentElement.tagName !== "THEAD") {
|
2022-10-10 18:40:02 +08:00
|
|
|
|
const wbrElement = document.createElement("wbr");
|
|
|
|
|
|
range.insertNode(wbrElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const html = nodeElement.outerHTML;
|
2022-10-10 18:40:02 +08:00
|
|
|
|
wbrElement.remove();
|
|
|
|
|
|
const index = getColIndex(cellElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const tbodyElement = cellElement.parentElement.parentElement;
|
2022-10-10 18:40:02 +08:00
|
|
|
|
let previousTrElement = tbodyElement.previousElementSibling.lastElementChild as HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (cellElement.parentElement.previousElementSibling) {
|
2022-10-11 11:19:36 +08:00
|
|
|
|
previousTrElement = cellElement.parentElement.previousElementSibling as HTMLTableRowElement;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tbodyElement.childElementCount === 1) {
|
|
|
|
|
|
tbodyElement.remove();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
cellElement.parentElement.remove();
|
|
|
|
|
|
}
|
2022-10-10 18:40:02 +08:00
|
|
|
|
range.selectNodeContents(previousTrElement.cells[index]);
|
|
|
|
|
|
range.collapse(true);
|
|
|
|
|
|
focusByRange(range);
|
2023-09-26 11:29:18 +08:00
|
|
|
|
scrollToView(nodeElement, previousTrElement, protyle);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const deleteColumn = (protyle: IProtyle, range: Range, nodeElement: Element, cellElement: HTMLElement) => {
|
2022-10-10 19:12:24 +08:00
|
|
|
|
const wbrElement = document.createElement("wbr");
|
|
|
|
|
|
range.insertNode(wbrElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const html = nodeElement.outerHTML;
|
2022-10-10 19:12:24 +08:00
|
|
|
|
wbrElement.remove();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const index = getColIndex(cellElement);
|
2022-10-11 11:19:36 +08:00
|
|
|
|
const sideCellElement = (cellElement.previousElementSibling || cellElement.nextElementSibling) as HTMLElement;
|
2022-10-10 19:12:24 +08:00
|
|
|
|
if (sideCellElement) {
|
|
|
|
|
|
range.selectNodeContents(sideCellElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
range.collapse(true);
|
2022-10-10 19:12:24 +08:00
|
|
|
|
// 滚动条横向定位
|
|
|
|
|
|
if (sideCellElement.offsetLeft + sideCellElement.clientWidth > nodeElement.firstElementChild.scrollLeft + nodeElement.firstElementChild.clientWidth) {
|
|
|
|
|
|
nodeElement.firstElementChild.scrollLeft = sideCellElement.offsetLeft + sideCellElement.clientWidth - nodeElement.firstElementChild.clientWidth;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
const tableElement = nodeElement.querySelector("table");
|
|
|
|
|
|
for (let i = 0; i < tableElement.rows.length; i++) {
|
|
|
|
|
|
const cells = tableElement.rows[i].cells;
|
|
|
|
|
|
if (cells.length === 1) {
|
|
|
|
|
|
tableElement.remove();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
cells[index].remove();
|
|
|
|
|
|
}
|
|
|
|
|
|
nodeElement.querySelectorAll("col")[index]?.remove();
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
2022-10-10 19:12:24 +08:00
|
|
|
|
focusByRange(range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const moveRowToUp = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
|
|
|
|
|
const rowElement = cellElement.parentElement;
|
|
|
|
|
|
if (rowElement.parentElement.tagName === "THEAD") {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const html = nodeElement.outerHTML;
|
|
|
|
|
|
if (rowElement.previousElementSibling) {
|
|
|
|
|
|
rowElement.after(rowElement.previousElementSibling);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const headElement = rowElement.parentElement.previousElementSibling.firstElementChild;
|
|
|
|
|
|
headElement.querySelectorAll("th").forEach(item => {
|
|
|
|
|
|
const tdElement = document.createElement("td");
|
|
|
|
|
|
tdElement.innerHTML = item.innerHTML;
|
|
|
|
|
|
item.parentNode.replaceChild(tdElement, item);
|
|
|
|
|
|
});
|
|
|
|
|
|
rowElement.querySelectorAll("td").forEach(item => {
|
|
|
|
|
|
const thElement = document.createElement("th");
|
|
|
|
|
|
thElement.innerHTML = item.innerHTML;
|
|
|
|
|
|
item.parentNode.replaceChild(thElement, item);
|
|
|
|
|
|
});
|
|
|
|
|
|
rowElement.after(headElement);
|
|
|
|
|
|
rowElement.parentElement.previousElementSibling.append(rowElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
|
|
|
|
|
focusByWbr(nodeElement, range);
|
2022-10-10 19:12:24 +08:00
|
|
|
|
scrollCenter(protyle, rowElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const moveRowToDown = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
|
|
|
|
|
const rowElement = cellElement.parentElement;
|
|
|
|
|
|
if ((rowElement.parentElement.tagName === "TBODY" && !rowElement.nextElementSibling) ||
|
|
|
|
|
|
(rowElement.parentElement.tagName === "THEAD" && !rowElement.parentElement.nextElementSibling)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const html = nodeElement.outerHTML;
|
|
|
|
|
|
if (rowElement.nextElementSibling) {
|
|
|
|
|
|
rowElement.before(rowElement.nextElementSibling);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const firstRowElement = rowElement.parentElement.nextElementSibling.firstElementChild;
|
|
|
|
|
|
firstRowElement.querySelectorAll("td").forEach(item => {
|
|
|
|
|
|
const thElement = document.createElement("th");
|
|
|
|
|
|
thElement.innerHTML = item.innerHTML;
|
|
|
|
|
|
item.parentNode.replaceChild(thElement, item);
|
|
|
|
|
|
});
|
|
|
|
|
|
rowElement.querySelectorAll("th").forEach(item => {
|
|
|
|
|
|
const tdElement = document.createElement("td");
|
|
|
|
|
|
tdElement.innerHTML = item.innerHTML;
|
|
|
|
|
|
item.parentNode.replaceChild(tdElement, item);
|
|
|
|
|
|
});
|
|
|
|
|
|
rowElement.after(firstRowElement);
|
|
|
|
|
|
rowElement.parentElement.nextElementSibling.insertAdjacentElement("afterbegin", rowElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
|
|
|
|
|
focusByWbr(nodeElement, range);
|
2022-10-10 19:12:24 +08:00
|
|
|
|
scrollCenter(protyle, rowElement);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const moveColumnToLeft = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
|
|
|
|
|
if (!cellElement.previousElementSibling) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const html = nodeElement.outerHTML;
|
|
|
|
|
|
let cellIndex = 0;
|
|
|
|
|
|
Array.from(cellElement.parentElement.children).find((item, index) => {
|
|
|
|
|
|
if (cellElement.isSameNode(item)) {
|
|
|
|
|
|
cellIndex = index;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2022-10-10 19:12:24 +08:00
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
nodeElement.querySelectorAll("tr").forEach((trElement) => {
|
|
|
|
|
|
trElement.cells[cellIndex].after(trElement.cells[cellIndex - 1]);
|
|
|
|
|
|
});
|
2022-10-10 19:12:24 +08:00
|
|
|
|
// 滚动条横向定位
|
|
|
|
|
|
if (cellElement.offsetLeft < nodeElement.firstElementChild.scrollLeft) {
|
|
|
|
|
|
nodeElement.firstElementChild.scrollLeft = cellElement.offsetLeft;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const colElements = nodeElement.querySelectorAll("col");
|
|
|
|
|
|
colElements[cellIndex].after(colElements[cellIndex - 1]);
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
|
|
|
|
|
focusByWbr(nodeElement, range);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const moveColumnToRight = (protyle: IProtyle, range: Range, cellElement: HTMLElement, nodeElement: Element) => {
|
|
|
|
|
|
if (!cellElement.nextElementSibling) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.insertNode(document.createElement("wbr"));
|
|
|
|
|
|
const html = nodeElement.outerHTML;
|
|
|
|
|
|
let cellIndex = 0;
|
|
|
|
|
|
Array.from(cellElement.parentElement.children).find((item, index) => {
|
|
|
|
|
|
if (cellElement.isSameNode(item)) {
|
|
|
|
|
|
cellIndex = index;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
nodeElement.querySelectorAll("tr").forEach((trElement) => {
|
|
|
|
|
|
trElement.cells[cellIndex].before(trElement.cells[cellIndex + 1]);
|
|
|
|
|
|
});
|
2022-10-10 19:12:24 +08:00
|
|
|
|
// 滚动条横向定位
|
|
|
|
|
|
if (cellElement.offsetLeft + cellElement.clientWidth > nodeElement.firstElementChild.scrollLeft + nodeElement.firstElementChild.clientWidth) {
|
|
|
|
|
|
nodeElement.firstElementChild.scrollLeft = cellElement.offsetLeft + cellElement.clientWidth - nodeElement.firstElementChild.clientWidth;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const colElements = nodeElement.querySelectorAll("col");
|
|
|
|
|
|
colElements[cellIndex].before(colElements[cellIndex + 1]);
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
|
|
|
|
|
|
focusByWbr(nodeElement, range);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) => {
|
|
|
|
|
|
const cellElement = hasClosestByMatchTag(range.startContainer, "TD") || hasClosestByMatchTag(range.startContainer, "TH");
|
|
|
|
|
|
const nodeElement = hasClosestBlock(range.startContainer) as HTMLTableElement;
|
|
|
|
|
|
if (!cellElement || !nodeElement) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (nodeElement.classList.contains("protyle-wysiwyg--select")) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-09-28 10:59:12 +08:00
|
|
|
|
// shift+enter 软换行
|
2023-11-12 12:28:20 +08:00
|
|
|
|
if (event.key === "Enter" && event.shiftKey && isNotCtrl(event) && !event.altKey) {
|
2022-09-28 10:59:12 +08:00
|
|
|
|
const wbrElement = document.createElement("wbr");
|
|
|
|
|
|
range.insertNode(wbrElement);
|
|
|
|
|
|
const oldHTML = nodeElement.outerHTML;
|
|
|
|
|
|
wbrElement.remove();
|
|
|
|
|
|
if (cellElement && !cellElement.innerHTML.endsWith("<br>")) {
|
|
|
|
|
|
cellElement.insertAdjacentHTML("beforeend", "<br>");
|
|
|
|
|
|
}
|
|
|
|
|
|
range.extractContents();
|
|
|
|
|
|
const types = protyle.toolbar.getCurrentType(range);
|
|
|
|
|
|
if (types.includes("code") && range.startContainer.nodeType !== 3) {
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/4169
|
|
|
|
|
|
const brElement = document.createElement("br");
|
|
|
|
|
|
(range.startContainer as HTMLElement).after(brElement);
|
|
|
|
|
|
range.setStartAfter(brElement);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
range.insertNode(document.createElement("br"));
|
|
|
|
|
|
}
|
|
|
|
|
|
range.collapse(false);
|
|
|
|
|
|
scrollCenter(protyle);
|
|
|
|
|
|
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, oldHTML);
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
// enter 光标跳转到下一行同列
|
2023-11-12 12:28:20 +08:00
|
|
|
|
if (isNotCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Enter") {
|
2022-09-28 10:59:12 +08:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
const trElement = cellElement.parentElement as HTMLTableRowElement;
|
|
|
|
|
|
if ((!trElement.nextElementSibling && trElement.parentElement.tagName === "TBODY") ||
|
|
|
|
|
|
(trElement.parentElement.tagName === "THEAD" && !trElement.parentElement.nextElementSibling)) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
let nextElement = trElement.nextElementSibling as HTMLTableRowElement;
|
|
|
|
|
|
if (!nextElement) {
|
|
|
|
|
|
nextElement = trElement.parentElement.nextElementSibling.firstChild as HTMLTableRowElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!nextElement) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.selectNodeContents(nextElement.cells[getColIndex(cellElement)]);
|
|
|
|
|
|
range.collapse(true);
|
|
|
|
|
|
scrollCenter(protyle);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2022-09-28 11:44:55 +08:00
|
|
|
|
// 表格后无内容时,按右键需新建空块
|
|
|
|
|
|
if (event.key === "ArrowRight" && range.toString() === "" &&
|
|
|
|
|
|
!nodeElement.nextElementSibling &&
|
|
|
|
|
|
cellElement.isSameNode(nodeElement.querySelector("table").lastElementChild.lastElementChild.lastElementChild) &&
|
2022-09-28 12:13:15 +08:00
|
|
|
|
getSelectionOffset(cellElement, protyle.wysiwyg.element, range).start === cellElement.textContent.length) {
|
2022-09-28 11:44:55 +08:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
insertEmptyBlock(protyle, "afterend", nodeElement.getAttribute("data-node-id"));
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// tab:光标移向下一个 cell
|
2023-11-12 12:28:20 +08:00
|
|
|
|
if (event.key === "Tab" && isNotCtrl(event)) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (event.shiftKey) {
|
|
|
|
|
|
// shift + tab 光标移动到前一个 cell
|
|
|
|
|
|
goPreviousCell(cellElement, range);
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let nextElement = cellElement.nextElementSibling;
|
|
|
|
|
|
if (!nextElement) {
|
|
|
|
|
|
if (cellElement.parentElement.nextElementSibling) {
|
|
|
|
|
|
nextElement = cellElement.parentElement.nextElementSibling.firstElementChild;
|
|
|
|
|
|
} else if (cellElement.parentElement.parentElement.tagName === "THEAD" &&
|
|
|
|
|
|
cellElement.parentElement.parentElement.nextElementSibling) {
|
|
|
|
|
|
nextElement =
|
|
|
|
|
|
cellElement.parentElement.parentElement.nextElementSibling.firstElementChild.firstElementChild;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
nextElement = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nextElement) {
|
|
|
|
|
|
range.selectNodeContents(nextElement);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
insertRow(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
range.selectNodeContents(nodeElement.querySelector("tbody").lastElementChild.firstElementChild);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-12 12:28:20 +08:00
|
|
|
|
if (event.key === "ArrowUp" && isNotCtrl(event) && !event.shiftKey && !event.altKey) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const startContainer = range.startContainer as HTMLElement;
|
|
|
|
|
|
let previousBrElement;
|
|
|
|
|
|
if (startContainer.nodeType !== 3 && (startContainer.tagName === "TH" || startContainer.tagName === "TD")) {
|
|
|
|
|
|
previousBrElement = (startContainer.childNodes[Math.max(0, range.startOffset - 1)] as HTMLElement)?.previousElementSibling;
|
2022-09-28 11:44:55 +08:00
|
|
|
|
} else if (startContainer.parentElement.tagName === "SPAN") {
|
2022-09-28 11:25:43 +08:00
|
|
|
|
previousBrElement = startContainer.parentElement.previousElementSibling;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
previousBrElement = startContainer.previousElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (previousBrElement) {
|
|
|
|
|
|
if (previousBrElement.tagName === "BR") {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
previousBrElement = previousBrElement.previousElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
const trElement = cellElement.parentElement as HTMLTableRowElement;
|
|
|
|
|
|
let previousElement = trElement.previousElementSibling as HTMLTableRowElement;
|
|
|
|
|
|
if (!previousElement) {
|
|
|
|
|
|
previousElement = trElement.parentElement.previousElementSibling.lastElementChild as HTMLTableRowElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!previousElement || previousElement?.tagName === "COL") {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.selectNodeContents(previousElement.cells[getColIndex(cellElement)]);
|
|
|
|
|
|
range.collapse(false);
|
|
|
|
|
|
scrollCenter(protyle);
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-12 12:28:20 +08:00
|
|
|
|
if (event.key === "ArrowDown" && isNotCtrl(event) && !event.shiftKey && !event.altKey) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const endContainer = range.endContainer as HTMLElement;
|
|
|
|
|
|
let nextBrElement;
|
|
|
|
|
|
if (endContainer.nodeType !== 3 && (endContainer.tagName === "TH" || endContainer.tagName === "TD")) {
|
|
|
|
|
|
nextBrElement = (endContainer.childNodes[Math.max(0, range.endOffset - 1)] as HTMLElement)?.nextElementSibling;
|
2022-09-28 11:44:55 +08:00
|
|
|
|
} else if (endContainer.parentElement.tagName === "SPAN") {
|
2022-09-28 11:25:43 +08:00
|
|
|
|
nextBrElement = endContainer.parentElement.nextElementSibling;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
nextBrElement = endContainer.nextElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
while (nextBrElement) {
|
2022-09-28 11:25:43 +08:00
|
|
|
|
if (nextBrElement.tagName === "BR" && nextBrElement.nextSibling) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
nextBrElement = nextBrElement.nextElementSibling;
|
|
|
|
|
|
}
|
|
|
|
|
|
const trElement = cellElement.parentElement as HTMLTableRowElement;
|
|
|
|
|
|
if ((!trElement.nextElementSibling && trElement.parentElement.tagName === "TBODY") ||
|
|
|
|
|
|
(trElement.parentElement.tagName === "THEAD" && !trElement.parentElement.nextElementSibling)) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
let nextElement = trElement.nextElementSibling as HTMLTableRowElement;
|
|
|
|
|
|
if (!nextElement) {
|
|
|
|
|
|
nextElement = trElement.parentElement.nextElementSibling.firstChild as HTMLTableRowElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!nextElement) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
range.selectNodeContents(nextElement.cells[getColIndex(cellElement)]);
|
|
|
|
|
|
range.collapse(true);
|
|
|
|
|
|
scrollCenter(protyle);
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Backspace:光标移动到前一个 cell
|
2023-11-12 12:28:20 +08:00
|
|
|
|
if (isNotCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace"
|
2022-05-26 15:18:53 +08:00
|
|
|
|
&& getSelectionOffset(cellElement, protyle.wysiwyg.element, range).start === 0 && range.toString() === "" &&
|
|
|
|
|
|
// 空换行无法删除 https://github.com/siyuan-note/siyuan/issues/2732
|
|
|
|
|
|
(range.startOffset === 0 || (range.startOffset === 1 && cellElement.querySelectorAll("br").length === 1))) {
|
|
|
|
|
|
const previousCellElement = goPreviousCell(cellElement, range, false);
|
|
|
|
|
|
if (!previousCellElement && nodeElement.previousElementSibling) {
|
|
|
|
|
|
focusBlock(nodeElement.previousElementSibling, undefined, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
scrollCenter(protyle);
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-12 22:06:19 +08:00
|
|
|
|
// 居左
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.general.alignLeft.custom, event)) {
|
2022-06-12 22:06:19 +08:00
|
|
|
|
setTableAlign(protyle, [cellElement], nodeElement, "left", range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2022-06-12 22:06:19 +08:00
|
|
|
|
// 居中
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.general.alignCenter.custom, event)) {
|
2022-06-12 22:06:19 +08:00
|
|
|
|
setTableAlign(protyle, [cellElement], nodeElement, "center", range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2022-06-12 22:06:19 +08:00
|
|
|
|
// 居右
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.general.alignRight.custom, event)) {
|
2022-06-12 22:06:19 +08:00
|
|
|
|
setTableAlign(protyle, [cellElement], nodeElement, "right", range);
|
2022-05-26 15:18:53 +08:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const tableElement = nodeElement.querySelector("table");
|
|
|
|
|
|
const hasNone = cellElement.parentElement.querySelector(".fn__none");
|
|
|
|
|
|
let hasColSpan = false;
|
|
|
|
|
|
let hasRowSpan = false;
|
|
|
|
|
|
Array.from(cellElement.parentElement.children).forEach((item: HTMLTableCellElement) => {
|
|
|
|
|
|
if (item.colSpan > 1) {
|
|
|
|
|
|
hasColSpan = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.rowSpan > 1) {
|
|
|
|
|
|
hasRowSpan = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
let previousHasNone: false | Element = false;
|
|
|
|
|
|
let previousHasColSpan = false;
|
|
|
|
|
|
let previousHasRowSpan = false;
|
|
|
|
|
|
let previousRowElement = cellElement.parentElement.previousElementSibling;
|
|
|
|
|
|
if (!previousRowElement && cellElement.parentElement.parentElement.tagName === "TBODY") {
|
|
|
|
|
|
previousRowElement = tableElement.querySelector("thead").lastElementChild;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (previousRowElement) {
|
|
|
|
|
|
previousHasNone = previousRowElement.querySelector(".fn__none");
|
|
|
|
|
|
Array.from(previousRowElement.children).forEach((item: HTMLTableCellElement) => {
|
|
|
|
|
|
if (item.colSpan > 1) {
|
|
|
|
|
|
previousHasColSpan = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.rowSpan > 1) {
|
|
|
|
|
|
previousHasRowSpan = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
let nextHasNone: false | Element = false;
|
|
|
|
|
|
let nextHasColSpan = false;
|
|
|
|
|
|
let nextHasRowSpan = false;
|
|
|
|
|
|
let nextRowElement = cellElement.parentElement.nextElementSibling;
|
|
|
|
|
|
if (!nextRowElement && cellElement.parentElement.parentElement.tagName === "THEAD") {
|
|
|
|
|
|
nextRowElement = tableElement.querySelector("tbody")?.firstElementChild;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (nextRowElement) {
|
|
|
|
|
|
nextHasNone = nextRowElement.querySelector(".fn__none");
|
|
|
|
|
|
Array.from(nextRowElement.children).forEach((item: HTMLTableCellElement) => {
|
|
|
|
|
|
if (item.colSpan > 1) {
|
|
|
|
|
|
nextHasColSpan = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.rowSpan > 1) {
|
|
|
|
|
|
nextHasRowSpan = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
const colIndex = getColIndex(cellElement);
|
|
|
|
|
|
let colIsPure = true;
|
|
|
|
|
|
Array.from(tableElement.rows).find(item => {
|
|
|
|
|
|
const cellElement = item.cells[colIndex];
|
|
|
|
|
|
if (cellElement.classList.contains("fn__none") || cellElement.colSpan > 1 || cellElement.rowSpan > 1) {
|
|
|
|
|
|
colIsPure = false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
let nextColIsPure = true;
|
|
|
|
|
|
Array.from(tableElement.rows).find(item => {
|
|
|
|
|
|
const cellElement = item.cells[colIndex + 1];
|
|
|
|
|
|
if (cellElement && (cellElement.classList.contains("fn__none") || cellElement.colSpan > 1 || cellElement.rowSpan > 1)) {
|
|
|
|
|
|
nextColIsPure = false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
let previousColIsPure = true;
|
|
|
|
|
|
Array.from(tableElement.rows).find(item => {
|
|
|
|
|
|
const cellElement = item.cells[colIndex - 1];
|
|
|
|
|
|
if (cellElement && (cellElement.classList.contains("fn__none") || cellElement.colSpan > 1 || cellElement.rowSpan > 1)) {
|
|
|
|
|
|
previousColIsPure = false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.moveToUp.custom, event)) {
|
|
|
|
|
|
if ((!hasNone || (hasNone && !hasRowSpan && hasColSpan)) &&
|
|
|
|
|
|
(!previousHasNone || (previousHasNone && !previousHasRowSpan && previousHasColSpan))) {
|
|
|
|
|
|
moveRowToUp(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.moveToDown.custom, event)) {
|
|
|
|
|
|
if ((!hasNone || (hasNone && !hasRowSpan && hasColSpan)) &&
|
|
|
|
|
|
(!nextHasNone || (nextHasNone && !nextHasRowSpan && nextHasColSpan))) {
|
|
|
|
|
|
moveRowToDown(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.moveToLeft.custom, event)) {
|
|
|
|
|
|
if (colIsPure && previousColIsPure) {
|
|
|
|
|
|
moveColumnToLeft(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.moveToRight.custom, event)) {
|
|
|
|
|
|
if (colIsPure && nextColIsPure) {
|
|
|
|
|
|
moveColumnToRight(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 上方新添加一行
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.insertRowAbove.custom, event)) {
|
|
|
|
|
|
insertRowAbove(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
event.preventDefault();
|
2022-08-29 00:03:45 +08:00
|
|
|
|
event.stopPropagation();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 下方新添加一行 https://github.com/Vanessa219/vditor/issues/46
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.insertRowBelow.custom, event)) {
|
|
|
|
|
|
if (!nextHasNone || (nextHasNone && !nextHasRowSpan && nextHasColSpan)) {
|
|
|
|
|
|
insertRow(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 左方新添加一列
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.insertColumnLeft.custom, event)) {
|
|
|
|
|
|
if (colIsPure || previousColIsPure) {
|
|
|
|
|
|
insertColumn(protyle, nodeElement, cellElement, "beforebegin", range);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 后方新添加一列
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table.insertColumnRight.custom, event)) {
|
|
|
|
|
|
if (colIsPure || nextColIsPure) {
|
|
|
|
|
|
insertColumn(protyle, nodeElement, cellElement, "afterend", range);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 删除当前行
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table["delete-row"].custom, event)) {
|
2022-05-30 11:18:51 +08:00
|
|
|
|
if ((!hasNone && !hasRowSpan) || //https://github.com/siyuan-note/siyuan/issues/5045
|
|
|
|
|
|
(hasNone && !hasRowSpan && hasColSpan)) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
deleteRow(protyle, range, cellElement, nodeElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
2023-02-02 15:48:24 +08:00
|
|
|
|
event.stopPropagation();
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 删除当前列
|
|
|
|
|
|
if (matchHotKey(window.siyuan.config.keymap.editor.table["delete-column"].custom, event)) {
|
|
|
|
|
|
if (colIsPure) {
|
|
|
|
|
|
deleteColumn(protyle, range, nodeElement, cellElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|