Przeglądaj źródła

Table cell properties command #value handling for multi-cell selection

Maciej Gołaszewski 5 lat temu
rodzic
commit
9a52e114fe

+ 15 - 2
packages/ckeditor5-table/src/commands/utils.js

@@ -29,6 +29,12 @@ export function findAncestor( parentName, positionOrElement ) {
 	}
 }
 
+function getSelectedTableCell( firstPosition ) {
+	const isTableCellSelected = firstPosition.nodeAfter && firstPosition.nodeAfter.is( 'tableCell' );
+
+	return isTableCellSelected ? firstPosition.nodeAfter : findAncestor( 'tableCell', firstPosition );
+}
+
 /**
  * Returns a first selected table cell from a multi-cell or in-cell selection.
  *
@@ -39,9 +45,16 @@ export function findAncestor( parentName, positionOrElement ) {
  */
 export function getFirstSelectedTableCell( selection ) {
 	const firstPosition = selection.getFirstPosition();
-	const isTableCellSelected = firstPosition.nodeAfter && firstPosition.nodeAfter.is( 'tableCell' );
 
-	return isTableCellSelected ? firstPosition.nodeAfter : findAncestor( 'tableCell', firstPosition );
+	return getSelectedTableCell( firstPosition );
+}
+
+export function getSelectedTableCells( model ) {
+	const selection = model.document.selection;
+
+	return Array.from( selection.getSelectedBlocks() )
+		.map( element => findAncestor( 'tableCell', model.createPositionAt( element, 0 ) ) )
+		.filter( tableCell => !!tableCell );
 }
 
 /**

+ 21 - 7
packages/ckeditor5-table/src/tablecellproperties/commands/tablecellpropertycommand.js

@@ -9,7 +9,7 @@
 
 import Command from '@ckeditor/ckeditor5-core/src/command';
 
-import { findAncestor, getFirstSelectedTableCell } from '../../commands/utils';
+import { getSelectedTableCells } from '../../commands/utils';
 
 /**
  * The table cell attribute command.
@@ -36,10 +36,11 @@ export default class TableCellPropertyCommand extends Command {
 	 */
 	refresh() {
 		const editor = this.editor;
-		const tableCell = getFirstSelectedTableCell( editor.model.document.selection );
 
-		this.isEnabled = !!tableCell;
-		this.value = this._getAttribute( tableCell );
+		const selectedTableCells = getSelectedTableCells( editor.model );
+
+		this.isEnabled = !!selectedTableCells.length;
+		this.value = this._getSingleValue( selectedTableCells );
 	}
 
 	/**
@@ -54,12 +55,10 @@ export default class TableCellPropertyCommand extends Command {
 	 */
 	execute( options = {} ) {
 		const model = this.editor.model;
-		const selection = model.document.selection;
 
 		const { value, batch } = options;
 
-		const tableCells = Array.from( selection.getSelectedBlocks() )
-			.map( element => findAncestor( 'tableCell', model.createPositionAt( element, 0 ) ) );
+		const tableCells = getSelectedTableCells( model );
 		const valueToSet = this._getValueToSet( value );
 
 		model.enqueueChange( batch || 'default', writer => {
@@ -96,4 +95,19 @@ export default class TableCellPropertyCommand extends Command {
 	_getValueToSet( value ) {
 		return value;
 	}
+
+	/**
+	 * Returns a single value for selected table cells. If all cells have the same value set it returns that value or undefined otherwise.
+	 *
+	 * @param {Array.<module:engine/model/element~Element>} tableCell
+	 * @returns {*}
+	 * @private
+	 */
+	_getSingleValue( tableCell ) {
+		const firstCellValue = this._getAttribute( tableCell[ 0 ] );
+
+		const everyCellHasAttribute = tableCell.every( tableCell => this._getAttribute( tableCell ) === firstCellValue );
+
+		return everyCellHasAttribute ? firstCellValue : undefined;
+	}
 }

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbackgroundcolorcommand.js

@@ -96,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'blue' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a backgroundColor property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a backgroundColor property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, backgroundColor: '#f00' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, backgroundColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different backgroundColor property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, backgroundColor: '#f00' },
+								{ contents: '01', isSelected: true, backgroundColor: 'pink' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, backgroundColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same backgroundColor property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, backgroundColor: '#f00' },
+								{ contents: '01', isSelected: true, backgroundColor: '#f00' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, backgroundColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '#f00' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellbordercolorcommand.js

@@ -121,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'blue' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a borderColor property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a borderColor property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderColor: '#f00' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different borderColor property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderColor: '#f00' },
+								{ contents: '01', isSelected: true, borderColor: 'pink' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same borderColor property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderColor: '#f00' },
+								{ contents: '01', isSelected: true, borderColor: '#f00' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderColor: '#f00' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '#f00' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderstylecommand.js

@@ -121,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'ridge' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a borderStyle property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a borderStyle property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderStyle: 'solid' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderStyle: 'solid' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different borderStyle property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderStyle: 'solid' },
+								{ contents: '01', isSelected: true, borderStyle: 'ridge' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderStyle: 'solid' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same borderStyle property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderStyle: 'solid' },
+								{ contents: '01', isSelected: true, borderStyle: 'solid' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderStyle: 'solid' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( 'solid' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellborderwidthcommand.js

@@ -121,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '2em' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a borderWidth property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a borderWidth property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderWidth: '1px' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderWidth: '1px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different borderWidth property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderWidth: '1px' },
+								{ contents: '01', isSelected: true, borderWidth: '20px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderWidth: '1px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same borderWidth property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, borderWidth: '1px' },
+								{ contents: '01', isSelected: true, borderWidth: '1px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, borderWidth: '1px' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '1px' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellheightcommand.js

@@ -96,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '100px' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a height property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a height property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, height: '100px' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, height: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different height property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, height: '100px' },
+								{ contents: '01', isSelected: true, height: '23px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, height: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same height property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, height: '100px' },
+								{ contents: '01', isSelected: true, height: '100px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, height: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '100px' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellhorizontalalignmentcommand.js

@@ -96,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'center' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a horizontalAlignment property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a horizontalAlignment property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, horizontalAlignment: 'center' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, horizontalAlignment: 'center' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different horizontalAlignment property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, horizontalAlignment: 'center' },
+								{ contents: '01', isSelected: true, horizontalAlignment: 'right' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, horizontalAlignment: 'center' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same horizontalAlignment property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, horizontalAlignment: 'center' },
+								{ contents: '01', isSelected: true, horizontalAlignment: 'center' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, horizontalAlignment: 'center' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( 'center' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellpaddingcommand.js

@@ -121,6 +121,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '2em' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a padding property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a padding property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, padding: '2em' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, padding: '2em' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different padding property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, padding: '2em' },
+								{ contents: '01', isSelected: true, padding: '3em' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, padding: '2em' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same padding property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, padding: '2em' },
+								{ contents: '01', isSelected: true, padding: '2em' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, padding: '2em' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '2em' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellverticalalignmentcommand.js

@@ -96,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( 'bottom' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a verticalAlignment property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a verticalAlignment property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, verticalAlignment: 'bottom' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, verticalAlignment: 'bottom' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different verticalAlignment property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, verticalAlignment: 'bottom' },
+								{ contents: '01', isSelected: true, verticalAlignment: 'top' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, verticalAlignment: 'bottom' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same verticalAlignment property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, verticalAlignment: 'bottom' },
+								{ contents: '01', isSelected: true, verticalAlignment: 'bottom' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, verticalAlignment: 'bottom' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( 'bottom' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {

+ 62 - 0
packages/ckeditor5-table/tests/tablecellproperties/commands/tablecellwidthcommand.js

@@ -96,6 +96,68 @@ describe( 'table cell properties', () => {
 						expect( command.value ).to.equal( '100px' );
 					} );
 				} );
+
+				describe( 'multi-cell selection', () => {
+					it( 'should be undefined if no table cell has a width property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if only some table cell has a width property', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, width: '100px' },
+								{ contents: '01', isSelected: true }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, width: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be undefined if one of selected table cells has different width property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, width: '100px' },
+								{ contents: '01', isSelected: true, width: '25px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, width: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.be.undefined;
+					} );
+
+					it( 'should be set if all table cell has the same width property value', () => {
+						setData( model, modelTable( [
+							[
+								{ contents: '00', isSelected: true, width: '100px' },
+								{ contents: '01', isSelected: true, width: '100px' }
+							],
+							[
+								'10',
+								{ contents: '11', isSelected: true, width: '100px' }
+							]
+						] ) );
+
+						expect( command.value ).to.equal( '100px' );
+					} );
+				} );
 			} );
 
 			describe( 'execute()', () => {