浏览代码

Introduce cutCellsVerticallyAt() and use it pasting scenario.

Maciej Gołaszewski 5 年之前
父节点
当前提交
1b41a3fd7c
共有 2 个文件被更改,包括 75 次插入1 次删除
  1. 8 1
      packages/ckeditor5-table/src/tableclipboard.js
  2. 67 0
      packages/ckeditor5-table/src/utils.js

+ 8 - 1
packages/ckeditor5-table/src/tableclipboard.js

@@ -11,7 +11,7 @@ import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 
 import TableSelection from './tableselection';
 import TableWalker from './tablewalker';
-import { cutCellsHorizontallyAt, getColumnIndexes, getRowIndexes, isSelectionRectangular } from './utils';
+import { cutCellsHorizontallyAt, cutCellsVerticallyAt, getColumnIndexes, getRowIndexes, isSelectionRectangular } from './utils';
 import { findAncestor } from './commands/utils';
 import { cropTableToDimensions } from './tableselection/croptable';
 import TableUtils from './tableutils';
@@ -306,10 +306,17 @@ function prepareLandingPlace( selectedTableCells, writer ) {
 	const table = findAncestor( 'table', selectedTableCells[ 0 ] );
 
 	const { first: firstRow, last: lastRow } = getRowIndexes( selectedTableCells );
+	const { first: firstColumn, last: lastColumn } = getColumnIndexes( selectedTableCells );
 
 	if ( firstRow > 0 ) {
 		cutCellsHorizontallyAt( table, firstRow, 0, writer );
 	}
 
 	cutCellsHorizontallyAt( table, lastRow + 1, firstRow, writer );
+
+	if ( firstColumn > 0 ) {
+		cutCellsVerticallyAt( table, firstColumn, 0, writer );
+	}
+
+	cutCellsVerticallyAt( table, lastColumn + 1, firstColumn, writer );
 }

+ 67 - 0
packages/ckeditor5-table/src/utils.js

@@ -256,6 +256,15 @@ export function cutCellsHorizontallyAt( table, headingRowsToSet, currentHeadingR
 	}
 }
 
+// TODO: refactor it to a better, general util.
+export function cutCellsVerticallyAt( table, headingColumnsToSet, currentHeadingColumns, writer ) {
+	const cellsToSplit = getVerticallyOverlappingCells( table, headingColumnsToSet, currentHeadingColumns );
+
+	for ( const { cell, column } of cellsToSplit ) {
+		splitVertically( cell, column, headingColumnsToSet, writer );
+	}
+}
+
 // Returns cells that span beyond the new heading section.
 //
 // @param {module:engine/model/element~Element} table The table to check.
@@ -330,6 +339,64 @@ function splitHorizontally( tableCell, headingRows, writer ) {
 	updateNumericAttribute( 'rowspan', newRowspan, tableCell, writer );
 }
 
+// Returns cells that span beyond the new heading section.
+//
+// @param {module:engine/model/element~Element} table The table to check.
+// @param {Number} headingColumnsToSet New heading columns attribute.
+// @param {Number} currentHeadingColumns Current heading columns attribute.
+// @returns {Array.<module:engine/model/element~Element>}
+function getVerticallyOverlappingCells( table, headingColumnsToSet, currentHeadingColumns ) {
+	const cellsToSplit = [];
+
+	const startAnalysisColumn = headingColumnsToSet > currentHeadingColumns ? currentHeadingColumns : 0;
+	// We're analyzing only when headingColumnsToSet > 0.
+	const endAnalysisColumn = headingColumnsToSet - 1;
+
+	// todo: end/start column
+	const tableWalker = new TableWalker( table );
+
+	for ( const { column, colspan, cell } of tableWalker ) {
+		// Skip slots outside the cropped area.
+		// Could use startColumn, endColumn. See: https://github.com/ckeditor/ckeditor5/issues/6785.
+		if ( startAnalysisColumn > column || column > endAnalysisColumn ) {
+			continue;
+		}
+		if ( colspan > 1 && column + colspan > headingColumnsToSet ) {
+			cellsToSplit.push( { cell, column } );
+		}
+	}
+
+	return cellsToSplit;
+}
+
+// Splits the table cell vertically.
+//
+// @param {module:engine/model/element~Element} tableCell
+// @param {Number} headingColumns
+// @param {module:engine/model/writer~Writer} writer
+function splitVertically( tableCell, columnIndex, headingColumns, writer ) {
+	const colspan = parseInt( tableCell.getAttribute( 'colspan' ) );
+	const newColspan = headingColumns - columnIndex;
+
+	const attributes = {};
+
+	const spanToSet = colspan - newColspan;
+
+	if ( spanToSet > 1 ) {
+		attributes.colspan = spanToSet;
+	}
+
+	const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );
+
+	if ( rowspan > 1 ) {
+		attributes.rowspan = rowspan;
+	}
+
+	createEmptyTableCell( writer, writer.createPositionAfter( tableCell ), attributes );
+	// Update the colspan attribute after updating table.
+	updateNumericAttribute( 'colspan', newColspan, tableCell, writer );
+}
+
 // Helper method to get an object with `first` and `last` indexes from an unsorted array of indexes.
 function getFirstLastIndexesObject( indexes ) {
 	const allIndexesSorted = indexes.sort( ( indexA, indexB ) => indexA - indexB );