浏览代码

Merge pull request #44 from ckeditor/t/43

t/43: Enable toolbar focus and blur using keyboard shortcuts.
Piotrek Koszuliński 8 年之前
父节点
当前提交
34bd793911

+ 23 - 0
packages/ckeditor5-editor-classic/src/classiceditorui.js

@@ -89,6 +89,29 @@ export default class ClassicEditorUI {
 				}
 
 				return Promise.all( promises );
+			} )
+			.then( () => {
+				const toolbarFocusTracker = this.view.toolbar.focusTracker;
+
+				// Because toolbar items can get focus, the overall state of
+				// the toolbar must also be tracked.
+				this.focusTracker.add( this.view.toolbar.element );
+
+				// Focus the toolbar on the keystroke, if not already focused.
+				editor.keystrokes.set( 'Alt+F10', ( data, cancel ) => {
+					if ( this.focusTracker.isFocused && !toolbarFocusTracker.isFocused ) {
+						this.view.toolbar.focus();
+						cancel();
+					}
+				} );
+
+				// Blur the toolbar and bring the focus back to editable on the keystroke.
+				this.view.toolbar.keystrokes.set( 'Esc', ( data, cancel ) => {
+					if ( toolbarFocusTracker.isFocused ) {
+						editor.editing.view.focus();
+						cancel();
+					}
+				} );
 			} );
 	}
 

+ 66 - 2
packages/ckeditor5-editor-classic/tests/classiceditorui.js

@@ -6,11 +6,14 @@
 /* globals document, Event */
 
 import ComponentFactory from '@ckeditor/ckeditor5-ui/src/componentfactory';
-import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
+import View from '@ckeditor/ckeditor5-ui/src/view';
+
 import ClassicEditorUI from '../src/classiceditorui';
 import ClassicEditorUIView from '../src/classiceditoruiview';
 import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
-import View from '@ckeditor/ckeditor5-ui/src/view';
+
+import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
+import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
 
 import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
 import utils from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
@@ -142,6 +145,66 @@ describe( 'ClassicEditorUI', () => {
 				expect( view.toolbar.items.get( 1 ).name ).to.equal( 'bar' );
 			} );
 		} );
+
+		describe( 'activates keyboard navigation for the toolbar', () => {
+			it( 'Alt+F10: focus the first focusable toolbar item', () => {
+				return ui.init().then( () => {
+					const spy = sinon.spy( view.toolbar, 'focus' );
+					const toolbarFocusTracker = view.toolbar.focusTracker;
+					const keyEvtData = {
+						keyCode: keyCodes.f10,
+						altKey: true,
+						preventDefault: sinon.spy(),
+						stopPropagation: sinon.spy()
+					};
+
+					toolbarFocusTracker.isFocused = false;
+					ui.focusTracker.isFocused = false;
+
+					editor.keystrokes.press( keyEvtData );
+					sinon.assert.notCalled( spy );
+
+					toolbarFocusTracker.isFocused = true;
+					ui.focusTracker.isFocused = true;
+
+					editor.keystrokes.press( keyEvtData );
+					sinon.assert.notCalled( spy );
+
+					toolbarFocusTracker.isFocused = false;
+					ui.focusTracker.isFocused = true;
+
+					editor.keystrokes.press( keyEvtData );
+					sinon.assert.calledOnce( spy );
+
+					sinon.assert.calledOnce( keyEvtData.preventDefault );
+					sinon.assert.calledOnce( keyEvtData.stopPropagation );
+				} );
+			} );
+
+			it( 'esc: re–foucus editable when toolbar is focused', () => {
+				return ui.init().then( () => {
+					const spy = sinon.spy( editor.editing.view, 'focus' );
+					const toolbarFocusTracker = view.toolbar.focusTracker;
+					const keyEvtData = { keyCode: keyCodes.esc,
+						preventDefault: sinon.spy(),
+						stopPropagation: sinon.spy()
+					};
+
+					toolbarFocusTracker.isFocused = false;
+
+					ui.view.toolbar.keystrokes.press( keyEvtData );
+					sinon.assert.notCalled( spy );
+
+					toolbarFocusTracker.isFocused = true;
+
+					ui.view.toolbar.keystrokes.press( keyEvtData );
+
+					sinon.assert.calledOnce( spy );
+					sinon.assert.calledOnce( keyEvtData.preventDefault );
+					sinon.assert.calledOnce( keyEvtData.stopPropagation );
+				} );
+			} );
+		} );
 	} );
 
 	describe( 'destroy()', () => {
@@ -176,6 +239,7 @@ function viewCreator( name ) {
 		const view = new View( locale );
 
 		view.name = name;
+		view.element = document.createElement( 'a' );
 
 		return view;
 	};