| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773 |
- /**
- * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
- */
- /**
- * @module table/tablecellproperties/ui/tablecellpropertiesview
- */
- import View from '@ckeditor/ckeditor5-ui/src/view';
- import ViewCollection from '@ckeditor/ckeditor5-ui/src/viewcollection';
- import submitHandler from '@ckeditor/ckeditor5-ui/src/bindings/submithandler';
- import KeystrokeHandler from '@ckeditor/ckeditor5-utils/src/keystrokehandler';
- import FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';
- import FocusCycler from '@ckeditor/ckeditor5-ui/src/focuscycler';
- import LabeledView from '@ckeditor/ckeditor5-ui/src/labeledview/labeledview';
- import { createLabeledDropdown, createLabeledInputText } from '@ckeditor/ckeditor5-ui/src/labeledview/utils';
- import LabelView from '@ckeditor/ckeditor5-ui/src/label/labelview';
- import { addListToDropdown } from '@ckeditor/ckeditor5-ui/src/dropdown/utils';
- import ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';
- import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
- import { fillToolbar, getBorderStyleDefinitions, getBorderStyleLabels } from '../../ui/utils';
- import FormRowView from '../../ui/formrowview';
- import FormHeaderView from '../../ui/formheaderview';
- import checkIcon from '@ckeditor/ckeditor5-core/theme/icons/check.svg';
- import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg';
- import alignLeftIcon from '@ckeditor/ckeditor5-core/theme/icons/align-left.svg';
- import alignRightIcon from '@ckeditor/ckeditor5-core/theme/icons/align-right.svg';
- import alignCenterIcon from '@ckeditor/ckeditor5-core/theme/icons/align-center.svg';
- import alignJustifyIcon from '@ckeditor/ckeditor5-core/theme/icons/align-justify.svg';
- import alignTopIcon from '@ckeditor/ckeditor5-core/theme/icons/align-top.svg';
- import alignMiddleIcon from '@ckeditor/ckeditor5-core/theme/icons/align-middle.svg';
- import alignBottomIcon from '@ckeditor/ckeditor5-core/theme/icons/align-bottom.svg';
- import '../../../theme/form.css';
- import '../../../theme/tableform.css';
- import '../../../theme/tablecellproperties.css';
- const ALIGNMENT_ICONS = {
- left: alignLeftIcon,
- center: alignCenterIcon,
- right: alignRightIcon,
- justify: alignJustifyIcon,
- top: alignTopIcon,
- middle: alignMiddleIcon,
- bottom: alignBottomIcon
- };
- /**
- * The class representing a table cell properties form, allowing users to customize
- * certain style aspects of a table cell, for instance, border, padding, text alignment, etc..
- *
- * @extends module:ui/view~View
- */
- export default class TableCellPropertiesView extends View {
- /**
- * @inheritDoc
- */
- constructor( locale ) {
- super( locale );
- this.set( {
- /**
- * The value of the cell border style.
- *
- * @observable
- * @default 'none'
- * @member #borderStyle
- */
- borderStyle: 'none',
- /**
- * The value of the cell border width style.
- *
- * @observable
- * @default ''
- * @member #borderWidth
- */
- borderWidth: '',
- /**
- * The value of the cell border color style.
- *
- * @observable
- * @default ''
- * @member #borderColor
- */
- borderColor: '',
- /**
- * The value of the cell padding style.
- *
- * @observable
- * @default ''
- * @member #padding
- */
- padding: '',
- /**
- * The value of the cell background color style.
- *
- * @observable
- * @default ''
- * @member #backgroundColor
- */
- backgroundColor: '',
- /**
- * The value of the table cell width style.
- *
- * @observable
- * @default ''
- * @member #width
- */
- width: '',
- /**
- * The value of the table cell height style.
- *
- * @observable
- * @default ''
- * @member #height
- */
- height: '',
- /**
- * The value of the horizontal text alignment style.
- *
- * @observable
- * @default 'left'
- * @member #horizontalAlignment
- */
- horizontalAlignment: 'left',
- /**
- * The value of the vertical text alignment style.
- *
- * @observable
- * @default 'middle'
- * @member #verticalAlignment
- */
- verticalAlignment: 'middle'
- } );
- const { borderStyleDropdown, borderWidthInput, borderColorInput, borderRowLabel } = this._createBorderFields();
- const { widthInput, operatorLabel, heightInput, dimensionsLabel } = this._createDimensionFields();
- const { horizontalAlignmentToolbar, verticalAlignmentToolbar, alignmentLabel } = this._createAlignmentFields();
- /**
- * Tracks information about the DOM focus in the form.
- *
- * @readonly
- * @member {module:utils/focustracker~FocusTracker}
- */
- this.focusTracker = new FocusTracker();
- /**
- * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
- *
- * @readonly
- * @member {module:utils/keystrokehandler~KeystrokeHandler}
- */
- this.keystrokes = new KeystrokeHandler();
- /**
- * A collection of child views in the form.
- *
- * @readonly
- * @type {module:ui/viewcollection~ViewCollection}
- */
- this.children = this.createCollection();
- /**
- * A dropdown that allows selecting the style of the table cell border.
- *
- * @readonly
- * @member {module:ui/dropdown/dropdownview~DropdownView}
- */
- this.borderStyleDropdown = borderStyleDropdown;
- /**
- * An input that allows specifying the width of the table cell border.
- *
- * @readonly
- * @member {module:ui/inputtext/inputtextview~InputTextView}
- */
- this.borderWidthInput = borderWidthInput;
- /**
- * An input that allows specifying the color of the table cell border.
- *
- * @readonly
- * @member {module:ui/inputtext/inputtextview~InputTextView}
- */
- this.borderColorInput = borderColorInput;
- /**
- * An input that allows specifying the table cell background color.
- *
- * @readonly
- * @member {module:ui/inputtext/inputtextview~InputTextView}
- */
- this.backgroundInput = this._createBackgroundField();
- /**
- * An input that allows specifying the table cell padding.
- *
- * @readonly
- * @member {module:ui/inputtext/inputtextview~InputTextView}
- */
- this.paddingInput = this._createPaddingField();
- /**
- * An input that allows specifying the table cell width.
- *
- * @readonly
- * @member {module:ui/inputtext/inputtextview~InputTextView}
- */
- this.widthInput = widthInput;
- /**
- * An input that allows specifying the table cell height.
- *
- * @readonly
- * @member {module:ui/inputtext/inputtextview~InputTextView}
- */
- this.heightInput = heightInput;
- /**
- * A toolbar with buttons that allow changing the horizontal text alignment in a table cell.
- *
- * @readonly
- * @member {module:ui/toolbar/toolbar~ToolbarView}
- */
- this.horizontalAlignmentToolbar = horizontalAlignmentToolbar;
- /**
- * A toolbar with buttons that allow changing the vertical text alignment in a table cell.
- *
- * @readonly
- * @member {module:ui/toolbar/toolbar~ToolbarView}
- */
- this.verticalAlignmentToolbar = verticalAlignmentToolbar;
- // Defer creating to make sure other fields are present and the Save button can
- // bind its #isEnabled to their error messages so there's no way to save unless all
- // fields are valid.
- const { saveButtonView, cancelButtonView } = this._createActionButtons();
- /**
- * The "Save" button view.
- *
- * @member {module:ui/button/buttonview~ButtonView}
- */
- this.saveButtonView = saveButtonView;
- /**
- * The "Cancel" button view.
- *
- * @member {module:ui/button/buttonview~ButtonView}
- */
- this.cancelButtonView = cancelButtonView;
- /**
- * A collection of views that can be focused in the form.
- *
- * @readonly
- * @protected
- * @member {module:ui/viewcollection~ViewCollection}
- */
- this._focusables = new ViewCollection();
- /**
- * Helps cycling over {@link #_focusables} in the form.
- *
- * @readonly
- * @protected
- * @member {module:ui/focuscycler~FocusCycler}
- */
- this._focusCycler = new FocusCycler( {
- focusables: this._focusables,
- focusTracker: this.focusTracker,
- keystrokeHandler: this.keystrokes,
- actions: {
- // Navigate form fields backwards using the Shift + Tab keystroke.
- focusPrevious: 'shift + tab',
- // Navigate form fields forwards using the Tab key.
- focusNext: 'tab'
- }
- } );
- // Form header.
- this.children.add( new FormHeaderView( locale, {
- label: this.t( 'Cell properties' )
- } ) );
- // Border row.
- this.children.add( new FormRowView( locale, {
- labelView: borderRowLabel,
- children: [
- borderRowLabel,
- borderStyleDropdown,
- borderColorInput,
- borderWidthInput
- ],
- class: 'ck-table-form__border-row'
- } ) );
- // Background.
- this.children.add( new FormRowView( locale, {
- children: [
- this.backgroundInput
- ]
- } ) );
- // Dimensions row and padding.
- this.children.add( new FormRowView( locale, {
- children: [
- // Dimensions row.
- new FormRowView( locale, {
- labelView: dimensionsLabel,
- children: [
- dimensionsLabel,
- widthInput,
- operatorLabel,
- heightInput
- ],
- class: 'ck-table-cell-properties-form__dimensions-row'
- } ),
- // Padding row.
- new FormRowView( locale, {
- children: [
- this.paddingInput
- ],
- class: 'ck-table-cell-properties-form__padding-row'
- } )
- ]
- } ) );
- // Text alignment row.
- this.children.add( new FormRowView( locale, {
- labelView: alignmentLabel,
- children: [
- alignmentLabel,
- horizontalAlignmentToolbar,
- verticalAlignmentToolbar,
- ],
- class: 'ck-table-cell-properties-form__alignment-row'
- } ) );
- // Action row.
- this.children.add( new FormRowView( locale, {
- children: [
- this.saveButtonView,
- this.cancelButtonView,
- ],
- class: 'ck-table-form__action-row'
- } ) );
- this.setTemplate( {
- tag: 'form',
- attributes: {
- class: [
- 'ck',
- 'ck-form',
- 'ck-table-form',
- 'ck-table-cell-properties-form'
- ],
- // https://github.com/ckeditor/ckeditor5-link/issues/90
- tabindex: '-1'
- },
- children: this.children
- } );
- }
- /**
- * @inheritDoc
- */
- render() {
- super.render();
- // Enable the "submit" event for this view. It can be triggered by the #saveButtonView
- // which is of the "submit" DOM "type".
- submitHandler( {
- view: this
- } );
- [
- this.borderStyleDropdown,
- this.borderColorInput,
- this.borderWidthInput,
- this.backgroundInput,
- this.widthInput,
- this.heightInput,
- this.paddingInput,
- this.horizontalAlignmentToolbar,
- this.verticalAlignmentToolbar,
- this.saveButtonView,
- this.cancelButtonView
- ].forEach( view => {
- // Register the view as focusable.
- this._focusables.add( view );
- // Register the view in the focus tracker.
- this.focusTracker.add( view.element );
- } );
- // Mainly for closing using "Esc" and navigation using "Tab".
- this.keystrokes.listenTo( this.element );
- }
- /**
- * Focuses the fist focusable field in the form.
- */
- focus() {
- this._focusCycler.focusFirst();
- }
- /**
- * Creates the following form fields:
- *
- * * {@link #borderStyleDropdown},
- * * {@link #borderWidthInput},
- * * {@link #borderColorInput}.
- *
- * @private
- * @returns {Object.<String,module:ui/view~View>}
- */
- _createBorderFields() {
- const locale = this.locale;
- const t = this.t;
- // -- Group label ---------------------------------------------
- const borderRowLabel = new LabelView( locale );
- borderRowLabel.text = t( 'Border' );
- // -- Style ---------------------------------------------------
- const styleLabels = getBorderStyleLabels( t );
- const borderStyleDropdown = new LabeledView( locale, createLabeledDropdown );
- borderStyleDropdown.set( {
- label: t( 'Style' ),
- class: 'ck-table-form__border-style'
- } );
- borderStyleDropdown.view.buttonView.set( {
- isOn: false,
- withText: true,
- tooltip: t( 'Style' )
- } );
- borderStyleDropdown.view.buttonView.bind( 'label' ).to( this, 'borderStyle', value => {
- return styleLabels[ value ];
- } );
- borderStyleDropdown.view.on( 'execute', evt => {
- this.borderStyle = evt.source._borderStyleValue;
- } );
- addListToDropdown( borderStyleDropdown.view, getBorderStyleDefinitions( this ) );
- // -- Width ---------------------------------------------------
- const borderWidthInput = new LabeledView( locale, createLabeledInputText );
- borderWidthInput.set( {
- label: t( 'Width' ),
- class: 'ck-table-form__border-width',
- } );
- borderWidthInput.view.bind( 'value' ).to( this, 'borderWidth' );
- borderWidthInput.bind( 'isEnabled' ).to( this, 'borderStyle', value => {
- return value !== 'none';
- } );
- borderWidthInput.view.on( 'input', () => {
- this.borderWidth = borderWidthInput.view.element.value;
- } );
- // -- Color ---------------------------------------------------
- const borderColorInput = new LabeledView( locale, createLabeledInputText );
- borderColorInput.label = t( 'Color' );
- borderColorInput.view.bind( 'value' ).to( this, 'borderColor' );
- borderColorInput.bind( 'isEnabled' ).to( this, 'borderStyle', value => {
- return value !== 'none';
- } );
- borderColorInput.view.on( 'input', () => {
- this.borderColor = borderColorInput.view.element.value;
- } );
- this.on( 'change:borderStyle', ( evt, name, value ) => {
- if ( value === 'none' ) {
- this.borderColor = '';
- this.borderWidth = '';
- }
- } );
- return {
- borderRowLabel,
- borderStyleDropdown,
- borderColorInput,
- borderWidthInput,
- };
- }
- /**
- * Creates the following form fields:
- *
- * * {@link #backgroundInput}.
- *
- * @private
- * @returns {module:ui/labeledview/labeledview~LabeledView}
- */
- _createBackgroundField() {
- const locale = this.locale;
- const t = this.t;
- const backgroundInput = new LabeledView( locale, createLabeledInputText );
- backgroundInput.set( {
- label: t( 'Background' ),
- class: 'ck-table-cell-properties-form__background',
- } );
- backgroundInput.view.bind( 'value' ).to( this, 'backgroundColor' );
- backgroundInput.view.on( 'input', () => {
- this.backgroundColor = backgroundInput.view.element.value;
- } );
- return backgroundInput;
- }
- /**
- * Creates the following form fields:
- *
- * * {@link #widthInput}.
- * * {@link #heightInput}.
- *
- * @private
- * @returns {module:ui/labeledview/labeledview~LabeledView}
- */
- _createDimensionFields() {
- const locale = this.locale;
- const t = this.t;
- // -- Label ---------------------------------------------------
- const dimensionsLabel = new LabelView( locale );
- dimensionsLabel.text = t( 'Dimensions' );
- // -- Width ---------------------------------------------------
- const widthInput = new LabeledView( locale, createLabeledInputText );
- widthInput.set( {
- label: t( 'Width' ),
- class: 'ck-table-cell-properties-form__width',
- } );
- widthInput.view.bind( 'value' ).to( this, 'width' );
- widthInput.view.on( 'input', () => {
- this.width = widthInput.view.element.value;
- } );
- // -- Operator ---------------------------------------------------
- const operatorLabel = new View( locale );
- operatorLabel.setTemplate( {
- tag: 'span',
- attributes: {
- class: [
- 'ck-table-form__dimension-operator'
- ]
- },
- children: [
- { text: '×' }
- ]
- } );
- // -- Height ---------------------------------------------------
- const heightInput = new LabeledView( locale, createLabeledInputText );
- heightInput.set( {
- label: t( 'Height' ),
- class: 'ck-table-cell-properties-form__height',
- } );
- heightInput.view.bind( 'value' ).to( this, 'height' );
- heightInput.view.on( 'input', () => {
- this.height = heightInput.view.element.value;
- } );
- return {
- dimensionsLabel,
- widthInput,
- operatorLabel,
- heightInput
- };
- }
- /**
- * Creates the following form fields:
- *
- * * {@link #paddingInput}.
- *
- * @private
- * @returns {module:ui/labeledview/labeledview~LabeledView}
- */
- _createPaddingField() {
- const locale = this.locale;
- const t = this.t;
- const paddingInput = new LabeledView( locale, createLabeledInputText );
- paddingInput.set( {
- label: t( 'Padding' ),
- class: 'ck-table-cell-properties-form__padding',
- } );
- paddingInput.view.bind( 'value' ).to( this, 'padding' );
- paddingInput.view.on( 'input', () => {
- this.padding = paddingInput.view.element.value;
- } );
- return paddingInput;
- }
- /**
- * Creates the following form fields:
- *
- * * {@link #horizontalAlignmentToolbar},
- * * {@link #verticalAlignmentToolbar}.
- *
- * @private
- * @returns {Object.<String,module:ui/view~View>}
- */
- _createAlignmentFields() {
- const locale = this.locale;
- const t = this.t;
- const alignmentLabel = new LabelView( locale );
- alignmentLabel.text = t( 'Text alignment' );
- // -- Horizontal ---------------------------------------------------
- const horizontalAlignmentToolbar = new ToolbarView( locale );
- horizontalAlignmentToolbar.set( {
- isCompact: true,
- ariaLabel: t( 'Horizontal text alignment toolbar' )
- } );
- fillToolbar( {
- view: this,
- icons: ALIGNMENT_ICONS,
- toolbar: horizontalAlignmentToolbar,
- labels: this._horizontalAlignmentLabels,
- propertyName: 'horizontalAlignment'
- } );
- // -- Vertical -----------------------------------------------------
- const verticalAlignmentToolbar = new ToolbarView( locale );
- verticalAlignmentToolbar.set( {
- isCompact: true,
- ariaLabel: t( 'Vertical text alignment toolbar' )
- } );
- fillToolbar( {
- view: this,
- icons: ALIGNMENT_ICONS,
- toolbar: verticalAlignmentToolbar,
- labels: this._verticalAlignmentLabels,
- propertyName: 'verticalAlignment'
- } );
- return {
- horizontalAlignmentToolbar,
- verticalAlignmentToolbar,
- alignmentLabel
- };
- }
- /**
- * Creates the following form controls:
- *
- * * {@link #saveButtonView},
- * * {@link #cancelButtonView}.
- *
- * @private
- * @returns {Object.<String,module:ui/view~View>}
- */
- _createActionButtons() {
- const locale = this.locale;
- const t = this.t;
- const saveButtonView = new ButtonView( locale );
- const cancelButtonView = new ButtonView( locale );
- const fieldsThatShouldValidateToSave = [
- this.borderWidthInput,
- this.borderColorInput,
- this.backgroundInput,
- this.paddingInput
- ];
- saveButtonView.set( {
- label: t( 'Save' ),
- icon: checkIcon,
- class: 'ck-button-save',
- type: 'submit',
- withText: true,
- } );
- saveButtonView.bind( 'isEnabled' ).toMany( fieldsThatShouldValidateToSave, 'errorText', ( ...errorTexts ) => {
- return errorTexts.every( errorText => !errorText );
- } );
- cancelButtonView.set( {
- label: t( 'Cancel' ),
- icon: cancelIcon,
- class: 'ck-button-cancel',
- type: 'cancel',
- withText: true,
- } );
- cancelButtonView.delegate( 'execute' ).to( this, 'cancel' );
- return {
- saveButtonView, cancelButtonView
- };
- }
- /**
- * Provides localized labels for {@link #horizontalAlignmentToolbar} buttons.
- *
- * @private
- * @type {Object.<String,String>}
- */
- get _horizontalAlignmentLabels() {
- const t = this.t;
- return {
- left: t( 'Align cell text to the left' ),
- center: t( 'Align cell text to the center' ),
- right: t( 'Align cell text to the right' ),
- justify: t( 'Justify cell text' ),
- };
- }
- /**
- * Provides localized labels for {@link #verticalAlignmentToolbar} buttons.
- *
- * @private
- * @type {Object.<String,String>}
- */
- get _verticalAlignmentLabels() {
- const t = this.t;
- return {
- top: t( 'Align cell text to the top' ),
- middle: t( 'Align cell text to the middle' ),
- bottom: t( 'Align cell text to the bottom' )
- };
- }
- }
|