diff --git a/app/src/menus/protyle.ts b/app/src/menus/protyle.ts index 8731ae6bc..739389d81 100644 --- a/app/src/menus/protyle.ts +++ b/app/src/menus/protyle.ts @@ -847,7 +847,7 @@ export const tableMenu = (protyle: IProtyle, nodeElement: Element, cellElement: accelerator: window.siyuan.config.keymap.editor.general.alignLeft.custom, label: window.siyuan.languages.alignLeft, click: () => { - setTableAlign(protyle, cellElement, nodeElement, "left", range); + setTableAlign(protyle, [cellElement], nodeElement, "left", range); } }); menus.push({ @@ -855,7 +855,7 @@ export const tableMenu = (protyle: IProtyle, nodeElement: Element, cellElement: label: window.siyuan.languages.alignCenter, accelerator: window.siyuan.config.keymap.editor.general.alignCenter.custom, click: () => { - setTableAlign(protyle, cellElement, nodeElement, "center", range); + setTableAlign(protyle, [cellElement], nodeElement, "center", range); } }); menus.push({ @@ -863,7 +863,7 @@ export const tableMenu = (protyle: IProtyle, nodeElement: Element, cellElement: label: window.siyuan.languages.alignRight, accelerator: window.siyuan.config.keymap.editor.general.alignRight.custom, click: () => { - setTableAlign(protyle, cellElement, nodeElement, "right", range); + setTableAlign(protyle, [cellElement], nodeElement, "right", range); } }); menus.push({ diff --git a/app/src/protyle/util/table.ts b/app/src/protyle/util/table.ts index d71b1daca..08fbad660 100644 --- a/app/src/protyle/util/table.ts +++ b/app/src/protyle/util/table.ts @@ -39,25 +39,29 @@ const goPreviousCell = (cellElement: HTMLElement, range: Range, isSelected = tru return previousElement; }; -export const setTableAlign = (protyle: IProtyle, cellElement: HTMLElement, nodeElement: Element, type: string, range: Range) => { +export const setTableAlign = (protyle: IProtyle, cellElements: HTMLElement[], nodeElement: Element, type: string, range: Range) => { 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; - let currentColumn = 0; + const currentColumns:number[] = []; for (let i = 0; i < rowCnt; i++) { for (let j = 0; j < columnCnt; j++) { - if (tableElement.rows[i].cells[j].isSameNode(cellElement)) { - currentColumn = j; - break; + if (tableElement.rows[i].cells[j].isSameNode(cellElements[currentColumns.length])) { + currentColumns.push(j); } } + if (currentColumns.length > 0) { + break; + } } for (let k = 0; k < rowCnt; k++) { - tableElement.rows[k].cells[currentColumn].setAttribute("align", type); + currentColumns.forEach(item => { + tableElement.rows[k].cells[item].setAttribute("align", type); + }) } updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html); nodeElement.querySelector("wbr").remove(); @@ -414,21 +418,21 @@ export const fixTable = (protyle: IProtyle, event: KeyboardEvent, range: Range) return true; } - // 剧左 + // 居左 if (matchHotKey(window.siyuan.config.keymap.editor.general.alignLeft.custom, event)) { - setTableAlign(protyle, cellElement, nodeElement, "left", range); + setTableAlign(protyle, [cellElement], nodeElement, "left", range); event.preventDefault(); return true; } - // 剧中 + // 居中 if (matchHotKey(window.siyuan.config.keymap.editor.general.alignCenter.custom, event)) { - setTableAlign(protyle, cellElement, nodeElement, "center", range); + setTableAlign(protyle, [cellElement], nodeElement, "center", range); event.preventDefault(); return true; } - // 剧右 + // 居右 if (matchHotKey(window.siyuan.config.keymap.editor.general.alignRight.custom, event)) { - setTableAlign(protyle, cellElement, nodeElement, "right", range); + setTableAlign(protyle, [cellElement], nodeElement, "right", range); event.preventDefault(); return true; } diff --git a/app/src/protyle/wysiwyg/index.ts b/app/src/protyle/wysiwyg/index.ts index 99b7c1e1c..debdfbfc7 100644 --- a/app/src/protyle/wysiwyg/index.ts +++ b/app/src/protyle/wysiwyg/index.ts @@ -53,6 +53,7 @@ import {isCtrl} from "../util/compatibility"; import {MenuItem} from "../../menus/Menu"; import {fetchPost} from "../../util/fetch"; import {onGet} from "../util/onGet"; +import {setTableAlign} from "../util/table"; export class WYSIWYG { public lastHTMLs: { [key: string]: string } = {}; @@ -429,7 +430,7 @@ export class WYSIWYG { const type = target.getAttribute("data-type"); if (type === "block-ref") { refMenu(protyle, target); - const rect =target.getBoundingClientRect(); + const rect = target.getBoundingClientRect(); setPosition(window.siyuan.menus.menu.element, rect.left, rect.top + 13, 26); // 阻止 popover target.removeAttribute("data-type"); @@ -444,7 +445,7 @@ export class WYSIWYG { } if (type === "a") { linkMenu(protyle, target); - const rect =target.getBoundingClientRect(); + const rect = target.getBoundingClientRect(); setPosition(window.siyuan.menus.menu.element, rect.left, rect.top + 13, 26); if (target.getAttribute("data-href")?.startsWith("siyuan://blocks")) { // 阻止 popover @@ -1044,6 +1045,72 @@ export class WYSIWYG { } } }).element); + window.siyuan.menus.menu.append(new MenuItem({ + icon: "iconAlignLeft", + accelerator: window.siyuan.config.keymap.editor.general.alignLeft.custom, + label: window.siyuan.languages.alignLeft, + click: () => { + if (tableBlockElement) { + const selectCellElements: HTMLTableCellElement[] = []; + const scrollLeft = tableBlockElement.firstElementChild.scrollLeft; + tableBlockElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement) => { + if (!item.classList.contains("fn__none") && + item.offsetLeft + 6 > tableSelectElement.offsetLeft + scrollLeft && item.offsetLeft + item.clientWidth - 6 < tableSelectElement.offsetLeft + scrollLeft + tableSelectElement.clientWidth && + item.offsetTop + 6 > tableSelectElement.offsetTop && item.offsetTop + item.clientHeight - 6 < tableSelectElement.offsetTop + tableSelectElement.clientHeight && + (selectCellElements.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) { + selectCellElements.push(item); + } + }); + tableBlockElement.querySelector("table").classList.remove("select"); + tableSelectElement.removeAttribute("style"); + setTableAlign(protyle, selectCellElements, tableBlockElement, "left", getEditorRange(tableBlockElement)); + } + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + icon: "iconAlignCenter", + accelerator: window.siyuan.config.keymap.editor.general.alignCenter.custom, + label: window.siyuan.languages.alignCenter, + click: () => { + if (tableBlockElement) { + const selectCellElements: HTMLTableCellElement[] = []; + const scrollLeft = tableBlockElement.firstElementChild.scrollLeft; + tableBlockElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement) => { + if (!item.classList.contains("fn__none") && + item.offsetLeft + 6 > tableSelectElement.offsetLeft + scrollLeft && item.offsetLeft + item.clientWidth - 6 < tableSelectElement.offsetLeft + scrollLeft + tableSelectElement.clientWidth && + item.offsetTop + 6 > tableSelectElement.offsetTop && item.offsetTop + item.clientHeight - 6 < tableSelectElement.offsetTop + tableSelectElement.clientHeight && + (selectCellElements.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) { + selectCellElements.push(item); + } + }); + tableBlockElement.querySelector("table").classList.remove("select"); + tableSelectElement.removeAttribute("style"); + setTableAlign(protyle, selectCellElements, tableBlockElement, "center", getEditorRange(tableBlockElement)); + } + } + }).element); + window.siyuan.menus.menu.append(new MenuItem({ + icon: "iconAlignRight", + accelerator: window.siyuan.config.keymap.editor.general.alignRight.custom, + label: window.siyuan.languages.alignRight, + click: () => { + if (tableBlockElement) { + const selectCellElements: HTMLTableCellElement[] = []; + const scrollLeft = tableBlockElement.firstElementChild.scrollLeft; + tableBlockElement.querySelectorAll("th, td").forEach((item: HTMLTableCellElement) => { + if (!item.classList.contains("fn__none") && + item.offsetLeft + 6 > tableSelectElement.offsetLeft + scrollLeft && item.offsetLeft + item.clientWidth - 6 < tableSelectElement.offsetLeft + scrollLeft + tableSelectElement.clientWidth && + item.offsetTop + 6 > tableSelectElement.offsetTop && item.offsetTop + item.clientHeight - 6 < tableSelectElement.offsetTop + tableSelectElement.clientHeight && + (selectCellElements.length === 0 || (selectCellElements.length > 0 && item.offsetTop === selectCellElements[0].offsetTop))) { + selectCellElements.push(item); + } + }); + tableBlockElement.querySelector("table").classList.remove("select"); + tableSelectElement.removeAttribute("style"); + setTableAlign(protyle, selectCellElements, tableBlockElement, "right", getEditorRange(tableBlockElement)); + } + } + }).element); window.siyuan.menus.menu.element.classList.remove("fn__none"); setPosition(window.siyuan.menus.menu.element, mouseUpEvent.clientX - 16, mouseUpEvent.clientY - 46); }