8
0
Просмотр исходного кода

Added: Initial row & column dropdowns.

Maciej Gołaszewski 7 лет назад
Родитель
Сommit
8efde98db8

+ 78 - 31
packages/ckeditor5-table/src/tableui.js

@@ -9,10 +9,11 @@
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
+import { addListToDropdown, createDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
+import Model from '@ckeditor/ckeditor5-ui/src/model';
+import Collection from '@ckeditor/ckeditor5-utils/src/collection';
 
 import icon from '@ckeditor/ckeditor5-core/theme/icons/object-center.svg';
-import insertRowIcon from '@ckeditor/ckeditor5-core/theme/icons/object-left.svg';
-import insertColumnIcon from '@ckeditor/ckeditor5-core/theme/icons/object-right.svg';
 
 /**
  * The table UI plugin.
@@ -46,44 +47,90 @@ export default class TableUI extends Plugin {
 			return buttonView;
 		} );
 
-		editor.ui.componentFactory.add( 'insertRowBelow', locale => {
-			const command = editor.commands.get( 'insertRowBelow' );
-			const buttonView = new ButtonView( locale );
-
-			buttonView.bind( 'isEnabled' ).to( command );
+		editor.ui.componentFactory.add( 'tableColumn', locale => {
+			const options = [
+				{ command: 'insertColumnBefore', label: 'Insert column before' },
+				{ command: 'insertColumnAfter', label: 'Insert column after' },
+				{ command: 'removeColumn', label: 'Delete column' }
+			];
 
-			buttonView.set( {
-				icon: insertRowIcon,
-				label: 'Insert row',
-				tooltip: true
-			} );
+			return this._prepareDropdown( 'Column', icon, options, locale );
+		} );
 
-			buttonView.on( 'execute', () => {
-				editor.execute( 'insertRowBelow' );
-				editor.editing.view.focus();
-			} );
+		editor.ui.componentFactory.add( 'tableRow', locale => {
+			const options = [
+				{ command: 'insertRowBelow', label: 'Insert row below' },
+				{ command: 'insertRowAbove', label: 'Insert row above' },
+				{ command: 'removeRow', label: 'Delete row' }
+			];
 
-			return buttonView;
+			return this._prepareDropdown( 'Row', icon, options, locale );
 		} );
+	}
 
-		editor.ui.componentFactory.add( 'insertColumnAfter', locale => {
-			const command = editor.commands.get( 'insertColumnAfter' );
-			const buttonView = new ButtonView( locale );
+	/**
+	 * Common method that prepares dropdown.
+	 *
+	 * @private
+	 * @param {String} buttonName
+	 * @param {String} icon
+	 * @param {Array.<Object>} options
+	 * @param locale
+	 * @returns {module:ui/dropdown/dropdownview~DropdownView}
+	 */
+	_prepareDropdown( buttonName, icon, options, locale ) {
+		const editor = this.editor;
 
-			buttonView.bind( 'isEnabled' ).to( command );
+		const dropdownView = createDropdown( locale );
+		const commands = [];
 
-			buttonView.set( {
-				icon: insertColumnIcon,
-				label: 'Insert column',
-				tooltip: true
-			} );
+		const dropdownItems = new Collection();
 
-			buttonView.on( 'execute', () => {
-				editor.execute( 'insertColumnAfter' );
-				editor.editing.view.focus();
-			} );
+		for ( const { command, label } of options ) {
+			addListOption( command, label, editor, commands, dropdownItems );
+		}
 
-			return buttonView;
+		addListToDropdown( dropdownView, dropdownItems );
+
+		dropdownView.buttonView.set( {
+			label: buttonName,
+			icon,
+			tooltip: true
 		} );
+
+		dropdownView.bind( 'isEnabled' ).toMany( commands, 'isEnabled', ( ...areEnabled ) => {
+			return areEnabled.some( isEnabled => isEnabled );
+		} );
+
+		this.listenTo( dropdownView, 'execute', evt => {
+			editor.execute( evt.source.commandName );
+			editor.editing.view.focus();
+		} );
+
+		return dropdownView;
 	}
 }
+
+/**
+ * Adds an option to a list view.
+ *
+ * @param {String} commandName
+ * @param {String} label
+ * @param {module:core/editor/editor~Editor} editor
+ * @param {Array.<module:core/command~Command>} commands
+ * @param {module:utils/collection~Collection} dropdownItems
+ */
+function addListOption( commandName, label, editor, commands, dropdownItems ) {
+	const command = editor.commands.get( commandName );
+
+	commands.push( command );
+
+	const itemModel = new Model( {
+		commandName,
+		label
+	} );
+
+	itemModel.bind( 'isEnabled' ).to( command );
+
+	dropdownItems.add( itemModel );
+}

+ 1 - 1
packages/ckeditor5-table/tests/manual/table.js

@@ -13,7 +13,7 @@ ClassicEditor
 	.create( document.querySelector( '#editor' ), {
 		plugins: [ ArticlePluginSet, Table ],
 		toolbar: [
-			'heading', '|', 'insertTable', 'insertRowBelow', 'insertColumnAfter',
+			'heading', '|', 'insertTable', '|', 'tableColumn', 'tableRow',
 			'|', 'bold', 'italic', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo'
 		]
 	} )

+ 87 - 40
packages/ckeditor5-table/tests/tableui.js

@@ -12,6 +12,7 @@ import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 
 import TableEditing from '../src/tableediting';
 import TableUI from '../src/tableui';
+import DropdownView from '@ckeditor/ckeditor5-ui/src/dropdown/dropdownview';
 
 testUtils.createSinonSandbox();
 
@@ -81,73 +82,119 @@ describe( 'TableUI', () => {
 		} );
 	} );
 
-	describe( 'insertRowBelow button', () => {
-		let insertRow;
+	describe( 'tableRow dropdown', () => {
+		let dropdown;
 
 		beforeEach( () => {
-			insertRow = editor.ui.componentFactory.create( 'insertRowBelow' );
+			dropdown = editor.ui.componentFactory.create( 'tableRow' );
 		} );
 
-		it( 'should register insertRowBelow button', () => {
-			expect( insertRow ).to.be.instanceOf( ButtonView );
-			expect( insertRow.isOn ).to.be.false;
-			expect( insertRow.label ).to.equal( 'Insert row' );
-			expect( insertRow.icon ).to.match( /<svg / );
+		it( 'have button with proper properties set', () => {
+			expect( dropdown ).to.be.instanceOf( DropdownView );
+
+			const button = dropdown.buttonView;
+
+			expect( button.isOn ).to.be.false;
+			expect( button.tooltip ).to.be.true;
+			expect( button.label ).to.equal( 'Column' );
+			expect( button.icon ).to.match( /<svg / );
 		} );
 
-		it( 'should bind to insertRow command', () => {
-			const command = editor.commands.get( 'insertRowBelow' );
+		it( 'should have proper items in panel', () => {
+			const listView = dropdown.listView;
 
-			command.isEnabled = true;
-			expect( insertRow.isOn ).to.be.false;
-			expect( insertRow.isEnabled ).to.be.true;
+			const labels = listView.items.map( ( { label } ) => label );
 
-			command.isEnabled = false;
-			expect( insertRow.isEnabled ).to.be.false;
+			expect( labels ).to.deep.equal( [ 'Insert row below', 'Insert row above', 'Delete row' ] );
 		} );
 
-		it( 'should execute insertRow command on button execute event', () => {
-			const executeSpy = testUtils.sinon.spy( editor, 'execute' );
+		it( 'should bind items in panel to proper commands', () => {
+			const items = dropdown.listView.items;
 
-			insertRow.fire( 'execute' );
+			const insertRowBelowCommand = editor.commands.get( 'insertRowBelow' );
+			const insertRowAboveCommand = editor.commands.get( 'insertRowAbove' );
+			const removeRowCommand = editor.commands.get( 'removeRow' );
 
-			sinon.assert.calledOnce( executeSpy );
-			sinon.assert.calledWithExactly( executeSpy, 'insertRowBelow' );
+			insertRowBelowCommand.isEnabled = true;
+			insertRowAboveCommand.isEnabled = true;
+			removeRowCommand.isEnabled = true;
+
+			expect( items.get( 0 ).isEnabled ).to.be.true;
+			expect( items.get( 1 ).isEnabled ).to.be.true;
+			expect( items.get( 2 ).isEnabled ).to.be.true;
+			expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+			insertRowBelowCommand.isEnabled = false;
+
+			expect( items.get( 0 ).isEnabled ).to.be.false;
+			expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+			insertRowAboveCommand.isEnabled = false;
+
+			expect( items.get( 1 ).isEnabled ).to.be.false;
+			expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+			removeRowCommand.isEnabled = false;
+			expect( items.get( 2 ).isEnabled ).to.be.false;
+			expect( dropdown.buttonView.isEnabled ).to.be.false;
 		} );
 	} );
 
-	describe( 'insertColumnAfter button', () => {
-		let insertColumn;
+	describe.only( 'tableColumn button', () => {
+		let dropdown;
 
 		beforeEach( () => {
-			insertColumn = editor.ui.componentFactory.create( 'insertColumnAfter' );
+			dropdown = editor.ui.componentFactory.create( 'tableColumn' );
 		} );
 
-		it( 'should register insertColumn buton', () => {
-			expect( insertColumn ).to.be.instanceOf( ButtonView );
-			expect( insertColumn.isOn ).to.be.false;
-			expect( insertColumn.label ).to.equal( 'Insert column' );
-			expect( insertColumn.icon ).to.match( /<svg / );
+		it( 'have button with proper properties set', () => {
+			expect( dropdown ).to.be.instanceOf( DropdownView );
+
+			const button = dropdown.buttonView;
+
+			expect( button.isOn ).to.be.false;
+			expect( button.tooltip ).to.be.true;
+			expect( button.label ).to.equal( 'Row' );
+			expect( button.icon ).to.match( /<svg / );
 		} );
 
-		it( 'should bind to insertColumn command', () => {
-			const command = editor.commands.get( 'insertColumnAfter' );
+		it( 'should have proper items in panel', () => {
+			const listView = dropdown.listView;
 
-			command.isEnabled = true;
-			expect( insertColumn.isOn ).to.be.false;
-			expect( insertColumn.isEnabled ).to.be.true;
+			const labels = listView.items.map( ( { label } ) => label );
 
-			command.isEnabled = false;
-			expect( insertColumn.isEnabled ).to.be.false;
+			expect( labels ).to.deep.equal( [ 'Insert column before', 'Insert column after', 'Delete column' ] );
 		} );
 
-		it( 'should execute insertColumn command on button execute event', () => {
-			const executeSpy = testUtils.sinon.spy( editor, 'execute' );
+		it( 'should bind items in panel to proper commands', () => {
+			const items = dropdown.listView.items;
 
-			insertColumn.fire( 'execute' );
+			const insertColumnBeforeCommand = editor.commands.get( 'insertColumnBefore' );
+			const insertColumnAfterCommand = editor.commands.get( 'insertColumnAfter' );
+			const removeColumnCommand = editor.commands.get( 'removeColumn' );
 
-			sinon.assert.calledOnce( executeSpy );
-			sinon.assert.calledWithExactly( executeSpy, 'insertColumnAfter' );
+			insertColumnBeforeCommand.isEnabled = true;
+			insertColumnAfterCommand.isEnabled = true;
+			removeColumnCommand.isEnabled = true;
+
+			expect( items.get( 0 ).isEnabled ).to.be.true;
+			expect( items.get( 1 ).isEnabled ).to.be.true;
+			expect( items.get( 2 ).isEnabled ).to.be.true;
+			expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+			insertColumnBeforeCommand.isEnabled = false;
+
+			expect( items.get( 0 ).isEnabled ).to.be.false;
+			expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+			insertColumnAfterCommand.isEnabled = false;
+
+			expect( items.get( 1 ).isEnabled ).to.be.false;
+			expect( dropdown.buttonView.isEnabled ).to.be.true;
+
+			removeColumnCommand.isEnabled = false;
+			expect( items.get( 2 ).isEnabled ).to.be.false;
+			expect( dropdown.buttonView.isEnabled ).to.be.false;
 		} );
 	} );
 } );