Przeglądaj źródła

Update documentation of cropTableToDimensions() util.

Maciej Gołaszewski 5 lat temu
rodzic
commit
85290c7169

+ 60 - 35
packages/ckeditor5-table/src/tableselection/croptable.js

@@ -7,16 +7,31 @@
  * @module table/tableselection/croptable
  */
 
-import { findAncestor, updateNumericAttribute } from '../commands/utils';
+import { createEmptyTableCell, findAncestor, updateNumericAttribute } from '../commands/utils';
 import TableWalker from '../tablewalker';
 
 /**
  * Returns a cropped table according to given dimensions.
- *
- * This function is to be used with the table selection.
+
+ * To return a cropped table that starts at first row and first column and end in third row and column:
  *
  *		const croppedTable = cropTable( table, 1, 1, 3, 3, tableUtils, writer );
  *
+ * Calling the code above for the table below:
+ *
+ *		      0   1   2   3   4                      0   1   2
+ *		    ┌───┬───┬───┬───┬───┐
+ *		 0  │ a │ b │ c │ d │ e │
+ *		    ├───┴───┤   ├───┴───┤                  ┌───┬───┬───┐
+ *		 1  │ f     │   │ g     │                  │   │   │ g │  0
+ *		    ├───┬───┴───┼───┬───┤   will return:   ├───┴───┼───┤
+ *		 2  │ h │ i     │ j │ k │                  │ i     │ j │  1
+ *		    ├───┤       ├───┤   │                  │       ├───┤
+ *		 3  │ l │       │ m │   │                  │       │ m │  2
+ *		    ├───┼───┬───┤   ├───┤                  └───────┴───┘
+ *		 4  │ n │ o │ p │   │ q │
+ *		    └───┴───┴───┴───┴───┘
+ *
  * @param {Number} sourceTable
  * @param {Number} startRow
  * @param {Number} startColumn
@@ -27,46 +42,58 @@ import TableWalker from '../tablewalker';
  * @returns {module:engine/model/element~Element}
  */
 export function cropTableToDimensions( sourceTable, startRow, startColumn, endRow, endColumn, tableUtils, writer ) {
+	// Create empty table with empty rows equal to crop height.
 	const croppedTable = writer.createElement( 'table' );
+	const cropHeight = endRow - startRow + 1;
 
-	// Create needed rows.
-	for ( let i = 0; i < endRow - startRow + 1; i++ ) {
+	for ( let i = 0; i < cropHeight; i++ ) {
 		writer.insertElement( 'tableRow', croppedTable, 'end' );
 	}
 
 	const tableMap = [ ...new TableWalker( sourceTable, { startRow, endRow, includeSpanned: true } ) ];
 
+	// Iterate over source table slots (including empty - spanned - ones).
 	for ( const { row: sourceRow, column: sourceColumn, cell: tableCell, isSpanned } of tableMap ) {
+		// Skip slots outside the cropped area.
 		if ( sourceColumn < startColumn || sourceColumn > endColumn ) {
 			continue;
 		}
 
-		const insertRow = sourceRow - startRow;
-		const insertColumn = sourceColumn - startColumn;
-
-		const row = croppedTable.getChild( insertRow );
+		// Row index in cropped table.
+		const cropRow = sourceRow - startRow;
+		const row = croppedTable.getChild( cropRow );
 
+		// For empty slots: fill the gap with empty table cell.
 		if ( isSpanned ) {
 			const { row: anchorRow, column: anchorColumn } = tableUtils.getCellLocation( tableCell );
 
+			// But fill the gap only if the spanning cell is anchored outside cropped area.
+			// In the table from method jsdoc those cells are: "c" & "f".
 			if ( anchorRow < startRow || anchorColumn < startColumn ) {
-				const tableCell = writer.createElement( 'tableCell' );
-				const paragraph = writer.createElement( 'paragraph' );
-
-				writer.insert( paragraph, tableCell, 0 );
-				writer.insertText( '', paragraph, 0 );
-
-				writer.append( tableCell, row );
+				createEmptyTableCell( writer, writer.createPositionAt( row, 'end' ) );
 			}
-		} else {
+		}
+		// Otherwise clone the cell with all children and trim if it exceeds cropped area.
+		else {
 			const tableCellCopy = tableCell._clone( true );
 
 			writer.append( tableCellCopy, row );
 
-			trimTableCell( tableCellCopy, tableUtils, writer, insertRow, insertColumn, startRow, startColumn, endRow, endColumn );
+			// Crop end column/row is equal to crop width/height.
+			const cropEndRow = endColumn - startColumn + 1;
+			const cropEndColumn = cropHeight;
+
+			// Column index in cropped table.
+			const cropColumn = sourceColumn - startColumn;
+
+			// Trim table if it exceeds cropped area.
+			// In the table from method jsdoc those cells are: "g" & "m".
+			trimTableCellIfNeeded( tableCellCopy, cropRow, cropColumn, cropEndRow, cropEndColumn, tableUtils, writer );
 		}
 	}
-	addHeadingsToTableCopy( croppedTable, sourceTable, startRow, startColumn, writer );
+
+	// Adjust heading rows & columns in cropped table if crop selection includes headings parts.
+	addHeadingsToCroppedTable( croppedTable, sourceTable, startRow, startColumn, writer );
 
 	return croppedTable;
 }
@@ -101,39 +128,37 @@ export function cropTableToSelection( selectedTableCellsIterator, tableUtils, wr
 	return cropTableToDimensions( sourceTable, startRow, startColumn, endRow, endColumn, tableUtils, writer );
 }
 
-function trimTableCell( tableCell, tableUtils, writer, row, column, startRow, startColumn, endRow, endColumn ) {
+// Adjusts table cell dimensions to not exceed last row and last column.
+function trimTableCellIfNeeded( tableCell, cellRow, cellColumn, lastRow, lastColumn, tableUtils, writer ) {
 	const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 );
 	const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );
 
-	const width = endColumn - startColumn + 1;
-	const height = endRow - startRow + 1;
-
-	if ( column + colspan > width ) {
-		const newSpan = width - column;
+	if ( cellColumn + colspan > lastRow ) {
+		const trimmedSpan = lastRow - cellColumn;
 
-		updateNumericAttribute( 'colspan', newSpan, tableCell, writer, 1 );
+		updateNumericAttribute( 'colspan', trimmedSpan, tableCell, writer, 1 );
 	}
 
-	if ( row + rowspan > height ) {
-		const newSpan = height - row;
+	if ( cellRow + rowspan > lastColumn ) {
+		const trimmedSpan = lastColumn - cellRow;
 
-		updateNumericAttribute( 'rowspan', newSpan, tableCell, writer, 1 );
+		updateNumericAttribute( 'rowspan', trimmedSpan, tableCell, writer, 1 );
 	}
 }
 
-// Sets proper heading attributes to copied table.
-function addHeadingsToTableCopy( tableCopy, sourceTable, startRow, startColumn, writer ) {
+// Sets proper heading attributes to a cropped table.
+function addHeadingsToCroppedTable( croppedTable, sourceTable, startRow, startColumn, writer ) {
 	const headingRows = parseInt( sourceTable.getAttribute( 'headingRows' ) || 0 );
 
 	if ( headingRows > 0 ) {
-		const copiedRows = headingRows - startRow;
-		writer.setAttribute( 'headingRows', copiedRows, tableCopy );
+		const headingRowsInCrop = headingRows - startRow;
+		updateNumericAttribute( 'headingRows', headingRowsInCrop, croppedTable, writer, 0 );
 	}
 
 	const headingColumns = parseInt( sourceTable.getAttribute( 'headingColumns' ) || 0 );
 
 	if ( headingColumns > 0 ) {
-		const copiedColumns = headingColumns - startColumn;
-		writer.setAttribute( 'headingColumns', copiedColumns, tableCopy );
+		const headingColumnsInCrop = headingColumns - startColumn;
+		updateNumericAttribute( 'headingColumns', headingColumnsInCrop, croppedTable, writer, 0 );
 	}
 }