in packages/roosterjs-editor-dom/lib/table/VTable.ts [145:340]
edit(operation: TableOperation) {
if (!this.table) {
return;
}
let currentRow = this.cells[this.row];
let currentCell = currentRow[this.col];
let { style } = currentCell.td;
switch (operation) {
case TableOperation.InsertAbove:
this.cells.splice(this.row, 0, currentRow.map(cloneCell));
break;
case TableOperation.InsertBelow:
let newRow = this.row + this.countSpanAbove(this.row, this.col);
this.cells.splice(
newRow,
0,
this.cells[newRow - 1].map((cell, colIndex) => {
let nextCell = this.getCell(newRow, colIndex);
if (nextCell.spanAbove) {
return cloneCell(nextCell);
} else if (cell.spanLeft) {
let newCell = cloneCell(cell);
newCell.spanAbove = false;
return newCell;
} else {
return {
td: cloneNode(this.getTd(this.row, colIndex)),
};
}
})
);
break;
case TableOperation.InsertLeft:
this.forEachCellOfCurrentColumn((cell, row) => {
row.splice(this.col, 0, cloneCell(cell));
});
break;
case TableOperation.InsertRight:
let newCol = this.col + this.countSpanLeft(this.row, this.col);
this.forEachCellOfColumn(newCol - 1, (cell, row, i) => {
let nextCell = this.getCell(i, newCol);
let newCell: VCell;
if (nextCell.spanLeft) {
newCell = cloneCell(nextCell);
} else if (cell.spanAbove) {
newCell = cloneCell(cell);
newCell.spanLeft = false;
} else {
newCell = {
td: cloneNode(this.getTd(i, this.col)),
};
}
row.splice(newCol, 0, newCell);
});
break;
case TableOperation.DeleteRow:
this.forEachCellOfCurrentRow((cell, i) => {
let nextCell = this.getCell(this.row + 1, i);
if (cell.td && cell.td.rowSpan > 1 && nextCell.spanAbove) {
nextCell.td = cell.td;
}
});
this.cells.splice(this.row, 1);
break;
case TableOperation.DeleteColumn:
this.forEachCellOfCurrentColumn((cell, row, i) => {
let nextCell = this.getCell(i, this.col + 1);
if (cell.td && cell.td.colSpan > 1 && nextCell.spanLeft) {
nextCell.td = cell.td;
}
row.splice(this.col, 1);
});
break;
case TableOperation.MergeAbove:
case TableOperation.MergeBelow:
let rowStep = operation == TableOperation.MergeAbove ? -1 : 1;
for (
let rowIndex = this.row + rowStep;
rowIndex >= 0 && rowIndex < this.cells.length;
rowIndex += rowStep
) {
let cell = this.getCell(rowIndex, this.col);
if (cell.td && !cell.spanAbove) {
let aboveCell = rowIndex < this.row ? cell : currentCell;
let belowCell = rowIndex < this.row ? currentCell : cell;
if (aboveCell.td.colSpan == belowCell.td.colSpan) {
moveChildNodes(
aboveCell.td,
belowCell.td,
true /*keepExistingChildren*/
);
belowCell.td = null;
belowCell.spanAbove = true;
}
break;
}
}
break;
case TableOperation.MergeLeft:
case TableOperation.MergeRight:
let colStep = operation == TableOperation.MergeLeft ? -1 : 1;
for (
let colIndex = this.col + colStep;
colIndex >= 0 && colIndex < this.cells[this.row].length;
colIndex += colStep
) {
let cell = this.getCell(this.row, colIndex);
if (cell.td && !cell.spanLeft) {
let leftCell = colIndex < this.col ? cell : currentCell;
let rightCell = colIndex < this.col ? currentCell : cell;
if (leftCell.td.rowSpan == rightCell.td.rowSpan) {
moveChildNodes(
leftCell.td,
rightCell.td,
true /*keepExistingChildren*/
);
rightCell.td = null;
rightCell.spanLeft = true;
}
break;
}
}
break;
case TableOperation.DeleteTable:
this.cells = null;
break;
case TableOperation.SplitVertically:
if (currentCell.td.rowSpan > 1) {
this.getCell(this.row + 1, this.col).td = cloneNode(currentCell.td);
} else {
let splitRow = currentRow.map(cell => {
return {
td: cell == currentCell ? cloneNode(cell.td) : null,
spanAbove: cell != currentCell,
spanLeft: cell.spanLeft,
};
});
this.cells.splice(this.row + 1, 0, splitRow);
}
break;
case TableOperation.SplitHorizontally:
if (currentCell.td.colSpan > 1) {
this.getCell(this.row, this.col + 1).td = cloneNode(currentCell.td);
} else {
this.forEachCellOfCurrentColumn((cell, row) => {
row.splice(this.col + 1, 0, {
td: row == currentRow ? cloneNode(cell.td) : null,
spanAbove: cell.spanAbove,
spanLeft: row != currentRow,
});
});
}
break;
case TableOperation.AlignCenter:
this.table.style.marginLeft = 'auto';
this.table.style.marginRight = 'auto';
break;
case TableOperation.AlignLeft:
this.table.style.marginLeft = '';
this.table.style.marginRight = 'auto';
break;
case TableOperation.AlignRight:
this.table.style.marginLeft = 'auto';
this.table.style.marginRight = '';
break;
case TableOperation.AlignCellCenter:
style.textAlign = 'center';
break;
case TableOperation.AlignCellLeft:
style.textAlign = 'left';
break;
case TableOperation.AlignCellRight:
style.textAlign = 'right';
break;
case TableOperation.AlignCellTop:
style.verticalAlign = 'top';
break;
case TableOperation.AlignCellMiddle:
style.verticalAlign = 'middle';
break;
case TableOperation.AlignCellBottom:
style.verticalAlign = 'bottom';
break;
}
}