@ckeditor/ckeditor5-ui
Version:
The UI framework and standard UI library of CKEditor 5.
179 lines (178 loc) • 5.89 kB
JavaScript
/**
* @license Copyright (c) 2003-2025, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module ui/dropdown/button/splitbuttonview
*/
import { IconDropdownArrow } from '@ckeditor/ckeditor5-icons';
import { KeystrokeHandler, FocusTracker } from '@ckeditor/ckeditor5-utils';
import View from '../../view.js';
import ButtonView from '../../button/buttonview.js';
import '../../../theme/components/dropdown/splitbutton.css';
/**
* The split button view class.
*
* ```ts
* const view = new SplitButtonView();
*
* view.set( {
* label: 'A button',
* keystroke: 'Ctrl+B',
* tooltip: true
* } );
*
* view.render();
*
* document.body.append( view.element );
* ```
*
* Also see the {@link module:ui/dropdown/utils~createDropdown `createDropdown()` util}.
*/
export default class SplitButtonView extends View {
/**
* Collection of the child views inside of the split button {@link #element}.
*/
children;
/**
* A main button of split button.
*/
actionView;
/**
* A secondary button of split button that opens dropdown.
*/
arrowView;
/**
* Instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}. It manages
* keystrokes of the split button:
*
* * <kbd>▶</kbd> moves focus to arrow view when action view is focused,
* * <kbd>◀</kbd> moves focus to action view when arrow view is focused.
*/
keystrokes;
/**
* Tracks information about DOM focus in the dropdown.
*/
focusTracker;
/**
* @inheritDoc
*/
constructor(locale, actionButton) {
super(locale);
const bind = this.bindTemplate;
// Implement the Button interface.
this.set('class', undefined);
this.set('labelStyle', undefined);
this.set('icon', undefined);
this.set('isEnabled', true);
this.set('isOn', false);
this.set('isToggleable', false);
this.set('isVisible', true);
this.set('keystroke', undefined);
this.set('withKeystroke', false);
this.set('label', undefined);
this.set('tabindex', -1);
this.set('tooltip', false);
this.set('tooltipPosition', 's');
this.set('type', 'button');
this.set('withText', false);
this.children = this.createCollection();
this.actionView = this._createActionView(actionButton);
this.arrowView = this._createArrowView();
this.keystrokes = new KeystrokeHandler();
this.focusTracker = new FocusTracker();
this.setTemplate({
tag: 'div',
attributes: {
class: [
'ck',
'ck-splitbutton',
bind.to('class'),
bind.if('isVisible', 'ck-hidden', value => !value),
this.arrowView.bindTemplate.if('isOn', 'ck-splitbutton_open')
]
},
children: this.children
});
}
/**
* @inheritDoc
*/
render() {
super.render();
this.children.add(this.actionView);
this.children.add(this.arrowView);
this.focusTracker.add(this.actionView.element);
this.focusTracker.add(this.arrowView.element);
this.keystrokes.listenTo(this.element);
// Overrides toolbar focus cycling behavior.
this.keystrokes.set('arrowright', (evt, cancel) => {
if (this.focusTracker.focusedElement === this.actionView.element) {
this.arrowView.focus();
cancel();
}
});
// Overrides toolbar focus cycling behavior.
this.keystrokes.set('arrowleft', (evt, cancel) => {
if (this.focusTracker.focusedElement === this.arrowView.element) {
this.actionView.focus();
cancel();
}
});
}
/**
* @inheritDoc
*/
destroy() {
super.destroy();
this.focusTracker.destroy();
this.keystrokes.destroy();
}
/**
* Focuses the {@link module:ui/button/buttonview~ButtonView#element} of the action part of split button.
*/
focus() {
this.actionView.focus();
}
/**
* Creates a {@link module:ui/button/buttonview~ButtonView} instance as {@link #actionView} and binds it with main split button
* attributes.
*/
_createActionView(actionButton) {
const actionView = actionButton || new ButtonView();
if (!actionButton) {
actionView.bind('icon', 'isEnabled', 'isOn', 'isToggleable', 'keystroke', 'label', 'tabindex', 'tooltip', 'tooltipPosition', 'type', 'withText').to(this);
}
actionView.extendTemplate({
attributes: {
class: 'ck-splitbutton__action'
}
});
actionView.delegate('execute').to(this);
return actionView;
}
/**
* Creates a {@link module:ui/button/buttonview~ButtonView} instance as {@link #arrowView} and binds it with main split button
* attributes.
*/
_createArrowView() {
const arrowView = new ButtonView();
const bind = arrowView.bindTemplate;
arrowView.icon = IconDropdownArrow;
arrowView.extendTemplate({
attributes: {
class: [
'ck-splitbutton__arrow'
],
'data-cke-tooltip-disabled': bind.to('isOn'),
'aria-haspopup': true,
'aria-expanded': bind.to('isOn', value => String(value))
}
});
arrowView.bind('isEnabled').to(this);
arrowView.bind('label').to(this);
arrowView.bind('tooltip').to(this);
arrowView.delegate('execute').to(this, 'open');
return arrowView;
}
}