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

Added: Wrap table cell in paragraph on enter.

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

+ 44 - 0
packages/ckeditor5-table/src/tableediting.js

@@ -10,6 +10,7 @@
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import { upcastElementToElement } from '@ckeditor/ckeditor5-engine/src/conversion/upcast-converters';
 import Range from '@ckeditor/ckeditor5-engine/src/model/range';
+import Position from '@ckeditor/ckeditor5-engine/src/model/position';
 import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 
 import upcastTable from './converters/upcasttable';
@@ -132,6 +133,8 @@ export default class TableEditing extends Plugin {
 		// Handle tab key navigation.
 		this.listenTo( editor.editing.view.document, 'keydown', ( ...args ) => this._handleTabOnSelectedTable( ...args ) );
 		this.listenTo( editor.editing.view.document, 'keydown', ( ...args ) => this._handleTabInsideTable( ...args ) );
+		// Add listener to 'enter' key pressed inside table cell.
+		this.listenTo( editor.editing.view.document, 'enter', ( ...args ) => this._handleEnterInsideTable( ...args ) );
 	}
 
 	/**
@@ -249,4 +252,45 @@ export default class TableEditing extends Plugin {
 			writer.setSelection( Range.createIn( cellToFocus ) );
 		} );
 	}
+
+	/**
+	 * Handles {@link module:engine/view/document~Document#event:enter keydown} events for the <kbd>Enter</kbd> key executed inside table
+	 * cell.
+	 *
+	 * @private
+	 * @param {module:utils/eventinfo~EventInfo} evt
+	 * @param {module:engine/view/observer/domeventdata~DomEventData} data
+	 */
+	_handleEnterInsideTable( evt, data ) {
+		// Do not act on SHIFT-ENTER.
+		if ( data.isSoft ) {
+			return;
+		}
+
+		const editor = this.editor;
+
+		const position = editor.model.document.selection.getFirstPosition();
+		const parent = position.parent;
+
+		// Either the selection is not inside a table or it is in a table cell that has already a block content.
+		if ( parent.name != 'tableCell' || ( !parent.getChild( 0 ) || !parent.getChild( 0 ).is( 'text' ) ) ) {
+			return;
+		}
+
+		data.preventDefault();
+		// Stop the event to prevent default enter event listener.
+		evt.stop();
+
+		editor.model.change( writer => {
+			// Wrap $text from table cell in paragraph.
+			writer.wrap( Range.createIn( parent ), 'paragraph' );
+
+			// Enforce selection to be inside newly created paragraph as consequent 'enter' keys would create nested paragraphs otherwise.
+			const positionInParagraph = Position.createFromParentAndOffset( parent.getChild( 0 ), position.offset );
+			writer.setSelection( positionInParagraph );
+
+			// Execute 'enter' command.
+			editor.execute( 'enter' );
+		} );
+	}
 }

+ 89 - 0
packages/ckeditor5-table/tests/tableediting.js

@@ -390,4 +390,93 @@ describe( 'TableEditing', () => {
 			} );
 		} );
 	} );
+
+	describe( 'enter key', () => {
+		let evtDataStub, viewDocument;
+
+		beforeEach( () => {
+			evtDataStub = {
+				preventDefault: sinon.spy(),
+				stopPropagation: sinon.spy(),
+				isSoft: false
+			};
+
+			return VirtualTestEditor
+				.create( {
+					plugins: [ TableEditing, Paragraph ]
+				} )
+				.then( newEditor => {
+					editor = newEditor;
+
+					sinon.stub( editor, 'execute' );
+
+					viewDocument = editor.editing.view.document;
+					model = editor.model;
+				} );
+		} );
+
+		it( 'should do nothing if not in table cell', () => {
+			setModelData( model, '<paragraph>[]foo</paragraph>' );
+
+			viewDocument.fire( 'enter', evtDataStub );
+
+			sinon.assert.notCalled( editor.execute );
+			expect( formatTable( getModelData( model ) ) ).to.equal( '<paragraph>[]foo</paragraph>' );
+		} );
+
+		it( 'should do nothing if table cell has already a block content', () => {
+			setModelData( model, modelTable( [
+				[ '<paragraph>[]11</paragraph>' ]
+			] ) );
+
+			viewDocument.fire( 'enter', evtDataStub );
+
+			sinon.assert.notCalled( editor.execute );
+			expect( formatTable( getModelData( model ) ) ).to.equal( formattedModelTable( [
+				[ '<paragraph>[]11</paragraph>' ]
+			] ) );
+		} );
+
+		it( 'should do nothing if table cell with a block content is selected as a whole', () => {
+			setModelData( model, modelTable( [
+				[ '<paragraph>[1</paragraph><paragraph>1]</paragraph>' ]
+			] ) );
+
+			viewDocument.fire( 'enter', evtDataStub );
+
+			sinon.assert.notCalled( editor.execute );
+			setModelData( model, modelTable( [
+				[ '<paragraph>[1</paragraph><paragraph>1]</paragraph>' ]
+			] ) );
+		} );
+
+		it( 'should allow default behavior of Shift+Enter pressed', () => {
+			setModelData( model, modelTable( [
+				[ '[]11' ]
+			] ) );
+
+			evtDataStub.isSoft = true;
+			viewDocument.fire( 'enter', evtDataStub );
+
+			sinon.assert.notCalled( editor.execute );
+			expect( formatTable( getModelData( model ) ) ).to.equal( formattedModelTable( [
+				[ '[]11' ]
+			] ) );
+		} );
+
+		it( 'should wrap table cell in paragraph and set selection', () => {
+			setModelData( model, modelTable( [
+				[ '[]11' ]
+			] ) );
+
+			viewDocument.fire( 'enter', evtDataStub );
+
+			sinon.assert.calledOnce( editor.execute );
+			sinon.assert.calledWithExactly( editor.execute, 'enter' );
+
+			expect( formatTable( getModelData( model ) ) ).to.equal( formattedModelTable( [
+				[ '<paragraph>[]11</paragraph>' ]
+			] ) );
+		} );
+	} );
 } );