8
0
Pārlūkot izejas kodu

Added: Handle Shift+Tab keystroke handling in table.

Maciej Gołaszewski 7 gadi atpakaļ
vecāks
revīzija
e10c03a238

+ 29 - 18
packages/ckeditor5-table/src/tableediting.js

@@ -81,12 +81,12 @@ export default class TablesEditing extends Plugin {
 		this.listenTo( editor.editing.view.document, 'keydown', ( evt, data ) => {
 			const tabPressed = data.keyCode == keyCodes.tab;
 
-			if ( !tabPressed ) {
+			// Act only on TAB & SHIFT-TAB - Do not override native CTRL+TAB handler.
+			if ( !tabPressed || data.ctrlKey ) {
 				return;
 			}
 
-			const doc = editor.model.document;
-			const selection = doc.selection;
+			const selection = editor.model.document.selection;
 
 			const table = getParentTable( selection.getFirstPosition() );
 
@@ -94,37 +94,48 @@ export default class TablesEditing extends Plugin {
 				return;
 			}
 
+			data.preventDefault();
+			data.stopPropagation();
+
 			const tableCell = selection.focus.parent;
 			const tableRow = tableCell.parent;
+
 			const rowIndex = table.getChildIndex( tableRow );
+			const cellIndex = tableRow.getChildIndex( tableCell );
 
-			data.preventDefault();
-			data.stopPropagation();
+			const isForward = !data.shiftKey;
 
-			const rowChildrenCount = tableRow.childCount;
+			if ( !isForward && cellIndex === 0 && rowIndex === 0 ) {
+				// It's the first cell of a table - don't do anything (stay in current position).
+				return;
+			}
 
-			const isLastTableCell = tableCell === tableRow.getChild( rowChildrenCount - 1 );
+			const indexOfLastCellInRow = tableRow.childCount - 1;
 
-			if ( rowIndex === table.childCount - 1 && isLastTableCell ) {
-				// It's a last table cell in a table - create row
-				editor.execute( 'insertRow', { at: rowChildrenCount - 1 } );
+			if ( isForward && rowIndex === table.childCount - 1 && cellIndex === indexOfLastCellInRow ) {
+				// It's a last table cell in a table - so create a new row at table's end.
+				editor.execute( 'insertRow', { at: table.childCount } );
 			}
 
-			// go to next cell
-			const cellIndex = tableRow.getChildIndex( tableCell );
-
-			let moveTo;
+			let moveToCell;
 
-			if ( cellIndex === rowChildrenCount - 1 ) {
+			if ( isForward && cellIndex === indexOfLastCellInRow ) {
+				// Move to first cell in next row.
 				const nextRow = table.getChild( rowIndex + 1 );
 
-				moveTo = Position.createAt( nextRow.getChild( 0 ) );
+				moveToCell = nextRow.getChild( 0 );
+			} else if ( !isForward && cellIndex === 0 ) {
+				// Move to last cell in a previous row.
+				const prevRow = table.getChild( rowIndex - 1 );
+
+				moveToCell = prevRow.getChild( prevRow.childCount - 1 );
 			} else {
-				moveTo = Position.createAt( tableRow.getChild( cellIndex + 1 ) );
+				// Move to next/previous cell otherwise.
+				moveToCell = tableRow.getChild( cellIndex + ( isForward ? 1 : -1 ) );
 			}
 
 			editor.model.change( writer => {
-				writer.setSelection( moveTo );
+				writer.setSelection( Position.createAt( moveToCell ) );
 			} );
 		} );
 	}

+ 79 - 2
packages/ckeditor5-table/tests/tableediting.js

@@ -112,14 +112,28 @@ describe( 'TableEditing', () => {
 			] ) );
 		} );
 
+		it( 'should do nothing if Ctrl+Tab is pressed', () => {
+			setModelData( model, modelTable( [
+				[ '11', '12[]' ]
+			] ) );
+
+			domEvtDataStub.ctrlKey = true;
+
+			editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+			sinon.assert.notCalled( domEvtDataStub.preventDefault );
+			sinon.assert.notCalled( domEvtDataStub.stopPropagation );
+			expect( formatModelTable( getModelData( model ) ) ).to.equal( formattedModelTable( [
+				[ '11', '12[]' ]
+			] ) );
+		} );
+
 		describe( 'on TAB', () => {
 			it( 'should do nothing if selection is not in a table', () => {
 				setModelData( model, '[]' + modelTable( [
 					[ '11', '12' ]
 				] ) );
 
-				domEvtDataStub.keyCode = getCode( 'Tab' );
-
 				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
 
 				sinon.assert.notCalled( domEvtDataStub.preventDefault );
@@ -170,5 +184,68 @@ describe( 'TableEditing', () => {
 				] ) );
 			} );
 		} );
+
+		describe( 'on SHIFT+TAB', () => {
+			beforeEach( () => {
+				domEvtDataStub.shiftKey = true;
+			} );
+
+			it( 'should do nothing if selection is not in a table', () => {
+				setModelData( model, '[]' + modelTable( [
+					[ '11', '12' ]
+				] ) );
+
+				domEvtDataStub.keyCode = getCode( 'Tab' );
+				domEvtDataStub.shiftKey = true;
+
+				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+				sinon.assert.notCalled( domEvtDataStub.preventDefault );
+				sinon.assert.notCalled( domEvtDataStub.stopPropagation );
+				expect( formatModelTable( getModelData( model ) ) ).to.equal( '[]' + formattedModelTable( [
+					[ '11', '12' ]
+				] ) );
+			} );
+
+			it( 'should move to previous cell', () => {
+				setModelData( model, modelTable( [
+					[ '11', '12[]' ]
+				] ) );
+
+				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+				sinon.assert.calledOnce( domEvtDataStub.preventDefault );
+				sinon.assert.calledOnce( domEvtDataStub.stopPropagation );
+				expect( formatModelTable( getModelData( model ) ) ).to.equal( formattedModelTable( [
+					[ '[]11', '12' ]
+				] ) );
+			} );
+
+			it( 'should not move if caret is in first table cell', () => {
+				setModelData( model, '<paragraph>foo</paragraph>' + modelTable( [
+					[ '[]11', '12' ]
+				] ) );
+
+				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+				expect( formatModelTable( getModelData( model ) ) ).to.equal(
+					'<paragraph>foo</paragraph>' + formattedModelTable( [ [ '[]11', '12' ] ] )
+				);
+			} );
+
+			it( 'should move to the last cell of previous row if on beginning of a row', () => {
+				setModelData( model, modelTable( [
+					[ '11', '12' ],
+					[ '[]21', '22' ]
+				] ) );
+
+				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+				expect( formatModelTable( getModelData( model ) ) ).to.equal( formattedModelTable( [
+					[ '11', '[]12' ],
+					[ '21', '22' ]
+				] ) );
+			} );
+		} );
 	} );
 } );