Skip to content

Commit

Permalink
🎨 Vanessa219#27 table
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanessa219 authored and stevapple committed Apr 8, 2020
1 parent 931d8c8 commit a8347b9
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 232 deletions.
8 changes: 1 addition & 7 deletions src/ts/hint/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,7 @@ export class Hint {
return;
}

let editorElement = vditor.sv.element;
if (vditor.currentMode === "wysiwyg") {
editorElement = vditor.wysiwyg.element;
} else if (vditor.currentMode === "ir") {
editorElement = vditor.ir.element;
}

const editorElement = vditor[vditor.currentMode].element;
const textareaPosition = getCursorPosition(editorElement);
const x = textareaPosition.left;
const y = textareaPosition.top;
Expand Down
4 changes: 4 additions & 0 deletions src/ts/ir/highlightToolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ export const highlightToolbar = (vditor: IVditor) => {
"list", "ordered-list", "check", "code", "inline-code", "upload", "link", "table", "record"]);
setCurrentToolbar(vditor.toolbar.elements, ["code"]);
}
const tableElement = hasClosestByMatchTag(typeElement, "TABLE") as HTMLTableElement;
if (tableElement) {
disableToolbar(vditor.toolbar.elements, ["table"]);
}

}, 200);
};
4 changes: 2 additions & 2 deletions src/ts/ir/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
getSelectPosition,
insertHTML,
setSelectionByPosition,
setSelectionFocus
setSelectionFocus,
} from "../util/selection";
import {expandMarker} from "./expandMarker";
import {highlightToolbar} from "./highlightToolbar";
Expand Down Expand Up @@ -256,7 +256,7 @@ class IR {
// 行内数学公式
if (previewRenderElement.tagName === "SPAN" &&
(event.key === "ArrowDown" || event.key === "ArrowRight")) {
range.selectNodeContents(previewRenderElement.parentElement.lastElementChild)
range.selectNodeContents(previewRenderElement.parentElement.lastElementChild);
range.collapse(false);
event.preventDefault();
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/ts/ir/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ export const processToolbar = (vditor: IVditor, actionBtn: Element, prefix: stri
}
document.execCommand("insertHTML", false, html);
} else if (commandName === "italic" || commandName === "bold" || commandName === "strike"
|| commandName === "inline-code" || commandName === "code") {
|| commandName === "inline-code" || commandName === "code" || commandName === "table") {
let html;
if (range.toString() === "") {
html = `${prefix}<wbr>${suffix}`;
Expand Down
13 changes: 10 additions & 3 deletions src/ts/ir/processKeydown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {Constants} from "../constants";
import {isCtrl} from "../util/compatibility";
import {scrollCenter} from "../util/editorCommenEvent";
import {hasClosestByAttribute, hasClosestByClassName, hasClosestByMatchTag} from "../util/hasClosest";
import {tableHotkey} from "../util/processTable";
import {getSelectPosition, setRangeByWbr} from "../util/selection";
import {processAfterRender} from "./process";

Expand Down Expand Up @@ -43,6 +44,7 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
}

const pElement = hasClosestByMatchTag(startContainer, "P");
// 代码块
const preRenderElement = hasClosestByClassName(startContainer, "vditor-ir__marker--pre");
if (preRenderElement && preRenderElement.tagName === "PRE") {
const codeRenderElement = preRenderElement.firstChild as HTMLElement;
Expand Down Expand Up @@ -78,7 +80,7 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
// Backspace: 光标位于第零个字符,仅删除代码块标签
preRenderElement.parentElement.outerHTML =
`<p data-block="0"><wbr>${codeRenderElement.innerHTML}</p>`;
setRangeByWbr(vditor.wysiwyg.element, range);
setRangeByWbr(vditor.ir.element, range);
processAfterRender(vditor);
event.preventDefault();
return true;
Expand All @@ -100,8 +102,8 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
// 代码块下无元素或者为代码块元素,添加空块
if ((event.key === "ArrowDown" && codeRenderElement.textContent.trimRight().substr(codePosition.start).indexOf("\n") === -1) ||
(event.key === "ArrowRight" && codePosition.start >= codeRenderElement.textContent.trimRight().length)) {
const nextElement = preRenderElement.parentElement.nextElementSibling
if (!nextElement || (nextElement && nextElement.getAttribute('data-type'))) {
const nextElement = preRenderElement.parentElement.nextElementSibling;
if (!nextElement || (nextElement && nextElement.getAttribute("data-type"))) {
preRenderElement.parentElement.insertAdjacentHTML("afterend",
`<p data-block="0">${Constants.ZWSP}<wbr></p>`);
setRangeByWbr(vditor.ir.element, range);
Expand Down Expand Up @@ -174,6 +176,11 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
}
}

// table
if (tableHotkey(vditor, event, range, processAfterRender)) {
return true;
}

// blockquote
const blockquoteElement = hasClosestByMatchTag(startContainer, "BLOCKQUOTE");
if (blockquoteElement && range.toString() === "") {
Expand Down
2 changes: 1 addition & 1 deletion src/ts/toolbar/EditMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const setEditMode = (vditor: IVditor, type: string, event?: Event) => {
enableToolbar(vditor.toolbar.elements, allToolbar);
removeCurrentToolbar(vditor.toolbar.elements, allToolbar);

const irUnUsedToolbar = ["list", "ordered-list", "check", "table"];
const irUnUsedToolbar = ["list", "ordered-list", "check"];
showToolbar(vditor.toolbar.elements, irUnUsedToolbar);
if (type === "ir") {
hideToolbar(vditor.toolbar.elements, ["format", "both", "preview"].concat(irUnUsedToolbar));
Expand Down
255 changes: 255 additions & 0 deletions src/ts/util/processTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import {isCtrl} from "./compatibility";
import {scrollCenter} from "./editorCommenEvent";
import {hasClosestByMatchTag} from "./hasClosest";
import {matchHotKey} from "./hotKey";
import {setRangeByWbr} from "./selection";

// 光标设置到前一个表格中
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);
}
}
};

export const setTableAlign = (tableElement: HTMLTableElement, type: string) => {
const cell = getSelection().getRangeAt(0).startContainer.parentElement;

const columnCnt = tableElement.rows[0].cells.length;
const rowCnt = tableElement.rows.length;
let currentColumn = 0;

for (let i = 0; i < rowCnt; i++) {
for (let j = 0; j < columnCnt; j++) {
if (tableElement.rows[i].cells[j].isEqualNode(cell)) {
currentColumn = j;
break;
}
}
}
for (let k = 0; k < rowCnt; k++) {
tableElement.rows[k].cells[currentColumn].setAttribute("align", type);
}
};

export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
afterRenderEvent: (vditor: IVditor) => void) => {
const startContainer = range.startContainer;
const cellElement = hasClosestByMatchTag(startContainer, "TD") ||
hasClosestByMatchTag(startContainer, "TH");
if (cellElement) {
// 换行或软换行:在 cell 中添加 br
if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
if (!cellElement.lastElementChild ||
(cellElement.lastElementChild && (!cellElement.lastElementChild.isEqualNode(cellElement.lastChild) ||
cellElement.lastElementChild.tagName !== "BR"))) {
cellElement.insertAdjacentHTML("beforeend", "<br>");
}
const brElement = document.createElement("br");
range.insertNode(brElement);
range.setStartAfter(brElement);
afterRenderEvent(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
}

// Backspace:光标移动到前一个 cell
if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace"
&& range.startOffset === 0 && range.toString() === "") {
goPreviousCell(cellElement, range, false);
event.preventDefault();
return true;
}

// tab:光标移向下一个 cell
if (event.key === "Tab") {
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);
}
event.preventDefault();
return true;
}

// 删除当前行
if (cellElement.tagName === "TD" && matchHotKey("⌘--", event)) {
const tbodyElement = cellElement.parentElement.parentElement;
if (cellElement.parentElement.previousElementSibling) {
range.selectNodeContents(cellElement.parentElement.previousElementSibling.lastElementChild);
} else {
range.selectNodeContents(tbodyElement.previousElementSibling.lastElementChild.lastElementChild);
}

if (tbodyElement.childElementCount === 1) {
tbodyElement.remove();
} else {
cellElement.parentElement.remove();
}

range.collapse(false);
event.preventDefault();
afterRenderEvent(vditor);
return true;
}

// 下方新添加一行 https://github.com/Vanessa219/vditor/issues/46
if (matchHotKey("⌘-=", event)) {
let rowHTML = "";
for (let m = 0; m < cellElement.parentElement.childElementCount; m++) {
rowHTML += `<td>${m === 0 ? " <wbr>" : " "}</td>`;
}
if (cellElement.tagName === "TH") {
cellElement.parentElement.parentElement.insertAdjacentHTML("afterend",
`<tbody><tr>${rowHTML}</tr></tbody>`);
} else {
cellElement.parentElement.insertAdjacentHTML("afterend", `<tr>${rowHTML}</tr>`);
}

setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
}

// 后方新添加一列
const tableElement = cellElement.parentElement.parentElement.parentElement as HTMLTableElement;
if (matchHotKey("⌘-⇧-=", event)) {
let index = 0;
let previousElement = cellElement.previousElementSibling;
while (previousElement) {
index++;
previousElement = previousElement.previousElementSibling;
}
for (let i = 0; i < tableElement.rows.length; i++) {
if (i === 0) {
tableElement.rows[i].cells[index].insertAdjacentHTML("afterend", "<th> </th>");
} else {
tableElement.rows[i].cells[index].insertAdjacentHTML("afterend", "<td> </td>");
}
}

afterRenderEvent(vditor);
event.preventDefault();
return true;
}

// 删除当前列
if (matchHotKey("⌘-⇧--", event)) {
let index = 0;
let previousElement = cellElement.previousElementSibling;
while (previousElement) {
index++;
previousElement = previousElement.previousElementSibling;
}
if (cellElement.previousElementSibling || cellElement.nextElementSibling) {
range.selectNodeContents(cellElement.previousElementSibling || cellElement.nextElementSibling);
range.collapse(true);
}
for (let i = 0; i < tableElement.rows.length; i++) {
if (tableElement.rows.length === 1) {
tableElement.remove();
} else {
tableElement.rows[i].cells[index].remove();
}
}
afterRenderEvent(vditor);
event.preventDefault();
return true;
}

// 剧左
if (matchHotKey("⌘-⇧-L", event)) {
if (vditor.currentMode === "ir") {
setTableAlign(tableElement, "left");
afterRenderEvent(vditor);
event.preventDefault();
return true;
} else {
const itemElement: HTMLElement = vditor.wysiwyg.popover.querySelector('[data-type="left"]');
if (itemElement) {
itemElement.click();
event.preventDefault();
return true;
}
}
}

// 剧中
if (matchHotKey("⌘-⇧-C", event)) {
if (vditor.currentMode === "ir") {
setTableAlign(tableElement, "center");
afterRenderEvent(vditor);
event.preventDefault();
return true;
} else {
const itemElement: HTMLElement = vditor.wysiwyg.popover.querySelector('[data-type="center"]');
if (itemElement) {
itemElement.click();
event.preventDefault();
return true;
}
}
}
// 剧右
if (matchHotKey("⌘-⇧-R", event)) {
if (vditor.currentMode === "ir") {
setTableAlign(tableElement, "right");
afterRenderEvent(vditor);
event.preventDefault();
return true;
} else {
const itemElement: HTMLElement = vditor.wysiwyg.popover.querySelector('[data-type="right"]');
if (itemElement) {
itemElement.click();
event.preventDefault();
return true;
}
}
}

// focus row input
if (vditor.currentMode === "wysiwyg" &&
!isCtrl(event) && event.key === "Enter" && !event.shiftKey && event.altKey) {
const inputElement = (vditor.wysiwyg.popover.querySelector(".vditor-input") as HTMLInputElement);
inputElement.focus();
inputElement.select();
event.preventDefault();
return true;
}
}
return false;
};
Loading

0 comments on commit a8347b9

Please sign in to comment.