Skip to content

Commit

Permalink
Add menu bar integration to multi root editor. (#16280)
Browse files Browse the repository at this point in the history
Feature (editor-multi-root): Added menu bar support for multi-root editor.
  • Loading branch information
mremiszewski authored May 7, 2024
1 parent 04a8c63 commit 627f842
Show file tree
Hide file tree
Showing 14 changed files with 275 additions and 324 deletions.
2 changes: 1 addition & 1 deletion packages/ckeditor5-core/tests/_utils/classictesteditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export default class ClassicTestEditor extends ElementApiMixin( Editor ) {
* @memberOf tests.core._utils
* @extends core.editor.EditorUI
*/
class ClassicTestEditorUI extends EditorUI {
export class ClassicTestEditorUI extends EditorUI {
/**
* @inheritDoc
*/
Expand Down
60 changes: 10 additions & 50 deletions packages/ckeditor5-editor-classic/src/classiceditorui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
import type { Editor, ElementApi } from 'ckeditor5/src/core.js';
import {
EditorUI,
normalizeToolbarConfig,
normalizeMenuBarConfig,
DialogView,
normalizeToolbarConfig,
_initMenuBar,
type DialogViewMoveToEvent,
type Dialog,
type EditorUIReadyEvent
type EditorUIReadyEvent,
type EditorUIView,
type MenuBarView
} from 'ckeditor5/src/ui.js';
import {
enablePlaceholder,
Expand All @@ -38,11 +40,6 @@ export default class ClassicEditorUI extends EditorUI {
*/
private readonly _toolbarConfig: ReturnType<typeof normalizeToolbarConfig>;

/**
* A normalized `config.menuBar` object.
*/
private readonly _menuBarConfig: ReturnType<typeof normalizeMenuBarConfig>;

/**
* The element replacer instance used to hide the editor's source element.
*/
Expand All @@ -60,9 +57,6 @@ export default class ClassicEditorUI extends EditorUI {
this.view = view;
this._toolbarConfig = normalizeToolbarConfig( editor.config.get( 'toolbar' ) );

// We use config.define in ClassicEditor, there will always be some configuration.
this._menuBarConfig = normalizeMenuBarConfig( editor.config.get( 'menuBar' ) || {} );

this._elementReplacer = new ElementReplacer();

this.listenTo<ViewScrollToTheSelectionEvent>(
Expand Down Expand Up @@ -124,7 +118,11 @@ export default class ClassicEditorUI extends EditorUI {

this._initPlaceholder();
this._initToolbar();
this._initMenuBar();

if ( view.menuBarView ) {
_initMenuBar( editor, view.menuBarView );
}

this._initDialogPluginIntegration();
this.fire<EditorUIReadyEvent>( 'ready' );
}
Expand Down Expand Up @@ -160,21 +158,6 @@ export default class ClassicEditorUI extends EditorUI {
this.addToolbar( view.toolbar );
}

/**
* Initializes the editor menu bar.
*/
private _initMenuBar(): void {
const view = this.view;

if ( !view.menuBarView ) {
return;
}

this._setupMenuBarBehaviors( view.menuBarView.element! );

view.menuBarView.fillFromConfig( this._menuBarConfig, this.componentFactory );
}

/**
* Enable the placeholder text on the editing root.
*/
Expand Down Expand Up @@ -275,28 +258,5 @@ export default class ClassicEditorUI extends EditorUI {
}, { priority: 'high' } );
}, { priority: 'low' } );
}

/**
* Handles focus and keystrokes for menu bar element.
*/
private _setupMenuBarBehaviors( menuBarViewElement: HTMLElement ) {
const editor = this.editor;
this.focusTracker.add( menuBarViewElement );
editor.keystrokes.listenTo( menuBarViewElement );

editor.keystrokes.set( 'Esc', ( data, cancel ) => {
if ( menuBarViewElement.contains( this.focusTracker.focusedElement ) ) {
editor.editing.view.focus();
cancel();
}
} );

editor.keystrokes.set( 'Alt+F9', ( data, cancel ) => {
if ( !menuBarViewElement.contains( this.focusTracker.focusedElement ) ) {
this.view.menuBarView!.focus();
cancel();
}
} );
}
}

113 changes: 0 additions & 113 deletions packages/ckeditor5-editor-classic/tests/classiceditorui.js
Original file line number Diff line number Diff line change
Expand Up @@ -765,119 +765,6 @@ describe( 'Focus handling and navigation between editing root and editor toolbar
} );
} );

describe( 'Focus handling and navigation between editing root and editor menu bar', () => {
let editorElement, editor, ui, menuBarView, domRoot;

testUtils.createSinonSandbox();

beforeEach( async () => {
editorElement = document.body.appendChild( document.createElement( 'div' ) );

editor = await ClassicEditor.create( editorElement, {
plugins: [ Paragraph, Image, ImageToolbar, ImageCaption ],
toolbar: [ 'imageTextAlternative' ],
image: {
toolbar: [ 'toggleImageCaption' ]
},
menuBar: {
isVisible: true
}
} );

domRoot = editor.editing.view.domRoots.get( 'main' );

ui = editor.ui;
menuBarView = ui.view.menuBarView;
} );

afterEach( () => {
editorElement.remove();

return editor.destroy();
} );

describe( 'Focusing menu bar on Alt+F9 key press', () => {
beforeEach( () => {
ui.focusTracker.isFocused = true;
ui.focusTracker.focusedElement = domRoot;
} );

it( 'should focus the menu bar when the focus is in the editing root', () => {
const spy = testUtils.sinon.spy( menuBarView, 'focus' );

setModelData( editor.model, '<paragraph>foo[]</paragraph>' );

ui.focusTracker.isFocused = true;
ui.focusTracker.focusedElement = domRoot;

// Focus the menu bar.
pressAltF9( editor );

sinon.assert.calledOnce( spy );
} );

it( 'should do nothing if the menu bar is already focused', () => {
const domRootFocusSpy = testUtils.sinon.spy( domRoot, 'focus' );
const menuBarFocusSpy = testUtils.sinon.spy( menuBarView, 'focus' );

setModelData( editor.model, '<paragraph>foo[]</paragraph>' );

// Focus the menu bar.
pressAltF9( editor );
ui.focusTracker.focusedElement = menuBarView.element;

// Try Alt+F9 again.
pressAltF9( editor );

sinon.assert.calledOnce( menuBarFocusSpy );
sinon.assert.notCalled( domRootFocusSpy );
} );
} );

describe( 'Restoring focus on Esc key press', () => {
beforeEach( () => {
ui.focusTracker.isFocused = true;
ui.focusTracker.focusedElement = domRoot;
} );

it( 'should move the focus back from the menu bar to the editing root', () => {
const domRootFocusSpy = testUtils.sinon.spy( domRoot, 'focus' );
const menuBarFocusSpy = testUtils.sinon.spy( menuBarView, 'focus' );

setModelData( editor.model, '<paragraph>foo[]</paragraph>' );

// Focus the menu bar.
pressAltF9( editor );
ui.focusTracker.focusedElement = menuBarView.element;

pressEsc( editor );

sinon.assert.callOrder( menuBarFocusSpy, domRootFocusSpy );
} );

it( 'should do nothing if it was pressed when menu bar was not focused', () => {
const domRootFocusSpy = testUtils.sinon.spy( domRoot, 'focus' );
const menuBarFocusSpy = testUtils.sinon.spy( menuBarView, 'focus' );

setModelData( editor.model, '<paragraph>foo[]</paragraph>' );

pressEsc( editor );

sinon.assert.notCalled( domRootFocusSpy );
sinon.assert.notCalled( menuBarFocusSpy );
} );
} );
} );

function pressAltF9( editor ) {
editor.keystrokes.press( {
keyCode: keyCodes.f9,
altKey: true,
preventDefault: sinon.spy(),
stopPropagation: sinon.spy()
} );
}

function pressAltF10( editor ) {
editor.keystrokes.press( {
keyCode: keyCodes.f10,
Expand Down
36 changes: 3 additions & 33 deletions packages/ckeditor5-editor-decoupled/src/decouplededitorui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {

import {
EditorUI,
normalizeMenuBarConfig,
type EditorUIReadyEvent
type EditorUIReadyEvent,
_initMenuBar
} from 'ckeditor5/src/ui.js';

import { enablePlaceholder } from 'ckeditor5/src/engine.js';
Expand Down Expand Up @@ -81,7 +81,7 @@ export default class DecoupledEditorUI extends EditorUI {

this._initPlaceholder();
this._initToolbar();
this._initMenuBar();
_initMenuBar( editor, this.view.menuBarView );
this.fire<EditorUIReadyEvent>( 'ready' );
}

Expand Down Expand Up @@ -112,36 +112,6 @@ export default class DecoupledEditorUI extends EditorUI {
this.addToolbar( view.toolbar );
}

/**
* Initializes the editor menu bar.
*/
private _initMenuBar(): void {
const editor = this.editor;
const menuBarViewElement = this.view.menuBarView.element!;
const view = this.view;

this.focusTracker.add( menuBarViewElement );
editor.keystrokes.listenTo( menuBarViewElement );

const normalizedMenuBarConfig = normalizeMenuBarConfig( editor.config.get( 'menuBar' ) || {} );

view.menuBarView.fillFromConfig( normalizedMenuBarConfig, this.componentFactory );

editor.keystrokes.set( 'Esc', ( data, cancel ) => {
if ( menuBarViewElement.contains( this.focusTracker.focusedElement ) ) {
editor.editing.view.focus();
cancel();
}
} );

editor.keystrokes.set( 'Alt+F9', ( data, cancel ) => {
if ( !menuBarViewElement.contains( this.focusTracker.focusedElement ) ) {
this.view.menuBarView.focus();
cancel();
}
} );
}

/**
* Enable the placeholder text on the editing root.
*/
Expand Down
Loading

0 comments on commit 627f842

Please sign in to comment.