Răsfoiți Sursa

Changed: SplitCell command should split cell horizontally to given number of cells.

Maciej Gołaszewski 7 ani în urmă
părinte
comite
1875b918c2

+ 62 - 14
packages/ckeditor5-table/src/commands/splitcellcommand.js

@@ -9,7 +9,8 @@
 
 import Command from '@ckeditor/ckeditor5-core/src/command';
 import Position from '@ckeditor/ckeditor5-engine/src/model/position';
-import { unsplitVertically } from './utils';
+
+import TableWalker from '../tablewalker';
 
 /**
  * The split cell command.
@@ -26,7 +27,7 @@ export default class SplitCellCommand extends Command {
 
 		const element = doc.selection.getFirstPosition().parent;
 
-		this.isEnabled = element.is( 'tableCell' ) && ( element.hasAttribute( 'colspan' ) || element.hasAttribute( 'rowspan' ) );
+		this.isEnabled = element.is( 'tableCell' );
 	}
 
 	/**
@@ -34,7 +35,7 @@ export default class SplitCellCommand extends Command {
 	 *
 	 * @fires execute
 	 */
-	execute() {
+	execute( options ) {
 		const model = this.editor.model;
 		const document = model.document;
 		const selection = document.selection;
@@ -42,22 +43,69 @@ export default class SplitCellCommand extends Command {
 		const firstPosition = selection.getFirstPosition();
 		const tableCell = firstPosition.parent;
 
-		const colspan = parseInt( tableCell.getAttribute( 'colspan' ) || 1 );
-		const rowspan = parseInt( tableCell.getAttribute( 'rowspan' ) || 1 );
+		const horizontally = options && options.horizontally && parseInt( options.horizontally || 0 );
+
+		const tableRow = tableCell.parent;
+		const table = tableRow.parent;
 
 		model.change( writer => {
-			if ( rowspan > 1 ) {
-				unsplitVertically( tableCell, writer, { breakHorizontally: true } );
-			}
+			if ( horizontally && horizontally > 1 ) {
+				const tableMap = [ ...new TableWalker( table ) ];
+				const cellData = tableMap.find( value => value.cell === tableCell );
+
+				const cellColumn = cellData.column;
+				const cellColspan = cellData.colspan;
+				const cellRowspan = cellData.rowspan;
+
+				const splitOnly = cellColspan >= horizontally;
+
+				const cellsToInsert = horizontally - 1;
+
+				if ( !splitOnly ) {
+					const cellsToUpdate = tableMap.filter( value => {
+						const cell = value.cell;
+
+						if ( cell === tableCell ) {
+							return false;
+						}
+
+						const colspan = value.colspan;
+						const column = value.column;
 
-			if ( colspan > 1 ) {
-				for ( let i = colspan - 1; i > 0; i-- ) {
-					writer.insertElement( 'tableCell', Position.createAfter( tableCell ) );
+						return column === cellColumn || ( column < cellColumn && column + colspan - 1 >= cellColumn );
+					} );
+
+					for ( const tableWalkerValue of cellsToUpdate ) {
+						const colspan = tableWalkerValue.colspan;
+						const cell = tableWalkerValue.cell;
+
+						writer.setAttribute( 'colspan', colspan + horizontally - 1, cell );
+					}
+
+					for ( let i = 0; i < cellsToInsert; i++ ) {
+						writer.insertElement( 'tableCell', Position.createAfter( tableCell ) );
+					}
+				} else {
+					const colspanOfInsertedCells = Math.floor( cellColspan / horizontally );
+					const newColspan = ( cellColspan - colspanOfInsertedCells * horizontally ) + colspanOfInsertedCells;
+
+					if ( newColspan > 1 ) {
+						writer.setAttribute( 'colspan', newColspan, tableCell );
+					} else {
+						writer.removeAttribute( 'colspan', tableCell );
+					}
+
+					const attributes = colspanOfInsertedCells > 1 ? { colspan: colspanOfInsertedCells } : {};
+
+					if ( cellRowspan > 1 ) {
+						attributes.rowspan = cellRowspan;
+					}
+
+					for ( let i = 0; i < cellsToInsert; i++ ) {
+						writer.insertElement( 'tableCell', attributes, Position.createAfter( tableCell ) );
+					}
 				}
 			}
-
-			writer.removeAttribute( 'colspan', tableCell );
-			writer.removeAttribute( 'rowspan', tableCell );
 		} );
 	}
 }

+ 74 - 64
packages/ckeditor5-table/tests/commands/splitcellcommand.js

@@ -70,30 +70,14 @@ describe( 'SplitCellCommand', () => {
 	} );
 
 	describe( 'isEnabled', () => {
-		it( 'should be true if in cell with colspan attribute set', () => {
+		it( 'should be true if in a table cell', () => {
 			setData( model, modelTable( [
-				[ { colspan: 2, contents: '11[]' } ]
+				[ '00[]' ]
 			] ) );
 
 			expect( command.isEnabled ).to.be.true;
 		} );
 
-		it( 'should be true if in cell with rowspan attribute set', () => {
-			setData( model, modelTable( [
-				[ { rowspan: 2, contents: '11[]' } ]
-			] ) );
-
-			expect( command.isEnabled ).to.be.true;
-		} );
-
-		it( 'should be false in cell without rowspan or colspan attribute', () => {
-			setData( model, modelTable( [
-				[ '11[]' ]
-			] ) );
-
-			expect( command.isEnabled ).to.be.false;
-		} );
-
 		it( 'should be false if not in cell', () => {
 			setData( model, '<p>11[]</p>' );
 
@@ -102,62 +86,88 @@ describe( 'SplitCellCommand', () => {
 	} );
 
 	describe( 'execute()', () => {
-		it( 'should split table cell with colspan', () => {
-			setData( model, modelTable( [
-				[ { colspan: 2, contents: '[]11' } ]
-			] ) );
-
-			command.execute();
+		describe( 'options.horizontally', () => {
+			it( 'should split table cell for given table cells', () => {
+				setData( model, modelTable( [
+					[ '00', '01', '02' ],
+					[ '10', '[]11', '12' ],
+					[ '20', { colspan: 2, contents: '21' } ],
+					[ { colspan: 2, contents: '30' }, '32' ]
+				] ) );
+
+				command.execute( { horizontally: 3 } );
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '00', { colspan: 3, contents: '01' }, '02' ],
+					[ '10', '[]11', '', '', '12' ],
+					[ '20', { colspan: 4, contents: '21' } ],
+					[ { colspan: 4, contents: '30' }, '32' ]
+				] ) );
+			} );
 
-			expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
-				[ '[]11', '' ]
-			] ) );
-		} );
+			it( 'should unsplit table cell if split is equal to colspan', () => {
+				setData( model, modelTable( [
+					[ '00', '01', '02' ],
+					[ '10', '11', '12' ],
+					[ '20', { colspan: 2, contents: '21[]' } ],
+					[ { colspan: 2, contents: '30' }, '32' ]
+				] ) );
+
+				command.execute( { horizontally: 2 } );
+
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '00', '01', '02' ],
+					[ '10', '11', '12' ],
+					[ '20', '21[]', '' ],
+					[ { colspan: 2, contents: '30' }, '32' ]
+				] ) );
+			} );
 
-		it( 'should split table cell with rowspan', () => {
-			setData( model, modelTable( [
-				[ { rowspan: 2, contents: '[]11' }, '12' ],
-				[ '22' ]
-			] ) );
+			it( 'should properly unsplit table cell if split is uneven', () => {
+				setData( model, modelTable( [
+					[ '00', '01', '02' ],
+					[ { colspan: 3, contents: '10[]' } ]
+				] ) );
 
-			command.execute();
+				command.execute( { horizontally: 2 } );
 
-			expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
-				[ '[]11', '12' ],
-				[ '', '22' ]
-			] ) );
-		} );
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '00', '01', '02' ],
+					[ { colspan: 2, contents: '10[]' }, '' ]
+				] ) );
+			} );
 
-		it( 'should split table cell with rowspan in the middle of a table', () => {
-			setData( model, modelTable( [
-				[ '11', { rowspan: 3, contents: '[]12' }, '13' ],
-				[ { rowspan: 2, contents: '21' }, '23' ],
-				[ '33' ]
-			] ) );
+			it( 'should properly set colspan of inserted cells', () => {
+				setData( model, modelTable( [
+					[ '00', '01', '02', '03' ],
+					[ { colspan: 4, contents: '10[]' } ]
+				] ) );
 
-			command.execute();
+				command.execute( { horizontally: 2 } );
 
-			expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
-				[ '11', '[]12', '13' ],
-				[ { rowspan: 2, contents: '21' }, '', '23' ],
-				[ '', '33' ]
-			] ) );
-		} );
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '00', '01', '02', '03' ],
+					[ { colspan: 2, contents: '10[]' }, { colspan: 2, contents: '' } ]
+				] ) );
+			} );
 
-		it( 'should split table cell with rowspan and colspan in the middle of a table', () => {
-			setData( model, modelTable( [
-				[ '11', { rowspan: 3, colspan: 2, contents: '[]12' }, '14' ],
-				[ { rowspan: 2, contents: '21' }, '24' ],
-				[ '34' ]
-			] ) );
+			it( 'should keep rowspan attribute for newly inserted cells', () => {
+				setData( model, modelTable( [
+					[ '00', '01', '02', '03', '04', '05' ],
+					[ { colspan: 5, rowspan: 2, contents: '10[]' }, '15' ],
+					[ '25' ]
+				] ) );
 
-			command.execute();
+				command.execute( { horizontally: 2 } );
 
-			expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
-				[ '11', '[]12', '', '14' ],
-				[ { rowspan: 2, contents: '21' }, '', '', '24' ],
-				[ '', '', '34' ]
-			] ) );
+				expect( formatTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '00', '01', '02', '03', '04', '05' ],
+					[ { colspan: 3, rowspan: 2, contents: '10[]' }, { colspan: 2, rowspan: 2, contents: '' }, '15' ],
+					[ '25' ]
+				] ) );
+			} );
 		} );
+
+		describe( 'options.horizontally', () => {} );
 	} );
 } );