瀏覽代碼

Added: Initial Tab key support.

Maciej Gołaszewski 7 年之前
父節點
當前提交
733e4b4b5b
共有 2 個文件被更改,包括 143 次插入0 次删除
  1. 53 0
      packages/ckeditor5-table/src/tableediting.js
  2. 90 0
      packages/ckeditor5-table/tests/tableediting.js

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

@@ -14,6 +14,9 @@ import { downcastInsertCell, downcastInsertRow, downcastInsertTable, downcastRem
 import InsertTableCommand from './commands/inserttablecommand';
 import InsertRowCommand from './commands/insertrowcommand';
 import InsertColumnCommand from './commands/insertcolumncommand';
+import { keyCodes } from '../../ckeditor5-utils/src/keyboard';
+import { getParentTable } from './commands/utils';
+import Position from '../../ckeditor5-engine/src/model/position';
 
 /**
  * The table editing feature.
@@ -73,5 +76,55 @@ export default class TablesEditing extends Plugin {
 		editor.commands.add( 'insertTable', new InsertTableCommand( editor ) );
 		editor.commands.add( 'insertRow', new InsertRowCommand( editor ) );
 		editor.commands.add( 'insertColumn', new InsertColumnCommand( editor ) );
+
+		this.listenTo( editor.editing.view.document, 'keydown', ( evt, data ) => {
+			const tabPressed = data.keyCode == keyCodes.tab;
+
+			if ( !tabPressed ) {
+				return;
+			}
+
+			const doc = editor.model.document;
+			const selection = doc.selection;
+
+			const table = getParentTable( selection.getFirstPosition() );
+
+			if ( !table ) {
+				return;
+			}
+
+			const tableCell = selection.focus.parent;
+			const tableRow = tableCell.parent;
+			const rowIndex = table.getChildIndex( tableRow );
+
+			data.preventDefault();
+			data.stopPropagation();
+
+			const rowChildrenCount = tableRow.childCount;
+
+			const isLastTableCell = tableCell === tableRow.getChild( rowChildrenCount - 1 );
+
+			if ( rowIndex === table.childCount - 1 && isLastTableCell ) {
+				// It's a last table cell in a table - create row
+				editor.execute( 'insertRow', { at: rowChildrenCount - 1 } );
+			}
+
+			// go to next cell
+			const cellIndex = tableRow.getChildIndex( tableCell );
+
+			let moveTo;
+
+			if ( cellIndex === rowChildrenCount - 1 ) {
+				const nextRow = table.getChild( rowIndex + 1 );
+
+				moveTo = Position.createAt( nextRow.getChild( 0 ) );
+			} else {
+				moveTo = Position.createAt( tableRow.getChild( cellIndex + 1 ) );
+			}
+
+			editor.model.change( writer => {
+				writer.setSelection( moveTo );
+			} );
+		} );
 	}
 }

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

@@ -8,6 +8,9 @@ import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtest
 import { getData as getModelData, setData as setModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 
 import TableEditing from '../src/tableediting';
+import { formatModelTable, formattedModelTable, modelTable } from './_utils/utils';
+import { getCode } from '../../ckeditor5-utils/src/keyboard';
+import { getData } from '../../ckeditor5-engine/src/dev-utils/model';
 
 describe( 'TableEditing', () => {
 	let editor, model;
@@ -82,4 +85,91 @@ describe( 'TableEditing', () => {
 			} );
 		} );
 	} );
+
+	describe( 'caret movement', () => {
+		let domEvtDataStub;
+
+		beforeEach( () => {
+			domEvtDataStub = {
+				keyCode: getCode( 'Tab' ),
+				preventDefault: sinon.spy(),
+				stopPropagation: sinon.spy()
+			};
+		} );
+
+		it( 'should do nothing if not tab pressed', () => {
+			setModelData( model, modelTable( [
+				[ '11', '12[]' ]
+			] ) );
+
+			domEvtDataStub.keyCode = getCode( 'a' );
+
+			editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+			sinon.assert.notCalled( domEvtDataStub.preventDefault );
+			sinon.assert.notCalled( domEvtDataStub.stopPropagation );
+			expect( formatModelTable( getData( 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 );
+				sinon.assert.notCalled( domEvtDataStub.stopPropagation );
+				expect( formatModelTable( getData( model ) ) ).to.equal( '[]' + formattedModelTable( [
+					[ '11', '12' ]
+				] ) );
+			} );
+
+			it( 'should move to next 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( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '11', '[]12' ]
+				] ) );
+			} );
+
+			it( 'should create another row and move to first cell in new row', () => {
+				setModelData( model, modelTable( [
+					[ '11', '12[]' ]
+				] ) );
+
+				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+				expect( formatModelTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '11', '12' ],
+					[ '[]', '' ]
+				] ) );
+			} );
+
+			it( 'should move to the first cell of next row if on end of a row', () => {
+				setModelData( model, modelTable( [
+					[ '11', '12[]' ],
+					[ '21', '22' ]
+				] ) );
+
+				editor.editing.view.document.fire( 'keydown', domEvtDataStub );
+
+				expect( formatModelTable( getData( model ) ) ).to.equal( formattedModelTable( [
+					[ '11', '12' ],
+					[ '[]21', '22' ]
+				] ) );
+			} );
+		} );
+	} );
 } );