|
@@ -14,11 +14,20 @@ import clickOutsideHandler from '@ckeditor/ckeditor5-ui/src/bindings/clickoutsid
|
|
|
import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';
|
|
import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';
|
|
|
import TableCellPropertiesView from './ui/tablecellpropertiesview';
|
|
import TableCellPropertiesView from './ui/tablecellpropertiesview';
|
|
|
import tableCellProperties from './../../theme/icons/table-cell-properties.svg';
|
|
import tableCellProperties from './../../theme/icons/table-cell-properties.svg';
|
|
|
-import { repositionContextualBalloon, getBalloonCellPositionData } from '../ui/utils';
|
|
|
|
|
|
|
+import {
|
|
|
|
|
+ repositionContextualBalloon,
|
|
|
|
|
+ getBalloonCellPositionData,
|
|
|
|
|
+ getLocalizedColorErrorText,
|
|
|
|
|
+ getLocalizedLengthErrorText,
|
|
|
|
|
+ colorFieldValidator,
|
|
|
|
|
+ lengthFieldValidator
|
|
|
|
|
+} from '../ui/utils';
|
|
|
|
|
+import { debounce } from 'lodash-es';
|
|
|
|
|
|
|
|
const DEFAULT_BORDER_STYLE = 'none';
|
|
const DEFAULT_BORDER_STYLE = 'none';
|
|
|
const DEFAULT_HORIZONTAL_ALIGNMENT = 'left';
|
|
const DEFAULT_HORIZONTAL_ALIGNMENT = 'left';
|
|
|
const DEFAULT_VERTICAL_ALIGNMENT = 'middle';
|
|
const DEFAULT_VERTICAL_ALIGNMENT = 'middle';
|
|
|
|
|
+const ERROR_TEXT_TIMEOUT = 500;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
|
|
* The table cell properties UI plugin. It introduces the `'tableCellProperties'` button
|
|
@@ -112,6 +121,7 @@ export default class TableCellPropertiesUI extends Plugin {
|
|
|
const editor = this.editor;
|
|
const editor = this.editor;
|
|
|
const viewDocument = editor.editing.view.document;
|
|
const viewDocument = editor.editing.view.document;
|
|
|
const view = new TableCellPropertiesView( editor.locale );
|
|
const view = new TableCellPropertiesView( editor.locale );
|
|
|
|
|
+ const t = editor.t;
|
|
|
|
|
|
|
|
// Render the view so its #element is available for the clickOutsideHandler.
|
|
// Render the view so its #element is available for the clickOutsideHandler.
|
|
|
view.render();
|
|
view.render();
|
|
@@ -148,15 +158,44 @@ export default class TableCellPropertiesUI extends Plugin {
|
|
|
callback: () => this._hideView()
|
|
callback: () => this._hideView()
|
|
|
} );
|
|
} );
|
|
|
|
|
|
|
|
|
|
+ const colorErrorText = getLocalizedColorErrorText( t );
|
|
|
|
|
+ const lengthErrorText = getLocalizedLengthErrorText( t );
|
|
|
|
|
+
|
|
|
// Create the "UI -> editor data" binding.
|
|
// Create the "UI -> editor data" binding.
|
|
|
// These listeners update the editor data (via table commands) when any observable
|
|
// These listeners update the editor data (via table commands) when any observable
|
|
|
- // property of the view has changed. This makes the view live, which means the changes are
|
|
|
|
|
|
|
+ // property of the view has changed. They also validate the value and display errors in the UI
|
|
|
|
|
+ // when necessary. This makes the view live, which means the changes are
|
|
|
// visible in the editing as soon as the user types or changes fields' values.
|
|
// visible in the editing as soon as the user types or changes fields' values.
|
|
|
view.on( 'change:borderStyle', this._getPropertyChangeCallback( 'tableCellBorderStyle' ) );
|
|
view.on( 'change:borderStyle', this._getPropertyChangeCallback( 'tableCellBorderStyle' ) );
|
|
|
- view.on( 'change:borderColor', this._getPropertyChangeCallback( 'tableCellBorderColor' ) );
|
|
|
|
|
- view.on( 'change:borderWidth', this._getPropertyChangeCallback( 'tableCellBorderWidth' ) );
|
|
|
|
|
- view.on( 'change:padding', this._getPropertyChangeCallback( 'tableCellPadding' ) );
|
|
|
|
|
- view.on( 'change:backgroundColor', this._getPropertyChangeCallback( 'tableCellBackgroundColor' ) );
|
|
|
|
|
|
|
+
|
|
|
|
|
+ view.on( 'change:borderColor', this._getValidatedPropertyChangeCallback( {
|
|
|
|
|
+ viewField: view.borderColorInput,
|
|
|
|
|
+ commandName: 'tableCellBorderColor',
|
|
|
|
|
+ errorText: colorErrorText,
|
|
|
|
|
+ validator: colorFieldValidator
|
|
|
|
|
+ } ) );
|
|
|
|
|
+
|
|
|
|
|
+ view.on( 'change:borderWidth', this._getValidatedPropertyChangeCallback( {
|
|
|
|
|
+ viewField: view.borderWidthInput,
|
|
|
|
|
+ commandName: 'tableCellBorderWidth',
|
|
|
|
|
+ errorText: lengthErrorText,
|
|
|
|
|
+ validator: lengthFieldValidator
|
|
|
|
|
+ } ) );
|
|
|
|
|
+
|
|
|
|
|
+ view.on( 'change:padding', this._getValidatedPropertyChangeCallback( {
|
|
|
|
|
+ viewField: view.paddingInput,
|
|
|
|
|
+ commandName: 'tableCellPadding',
|
|
|
|
|
+ errorText: lengthErrorText,
|
|
|
|
|
+ validator: lengthFieldValidator
|
|
|
|
|
+ } ) );
|
|
|
|
|
+
|
|
|
|
|
+ view.on( 'change:backgroundColor', this._getValidatedPropertyChangeCallback( {
|
|
|
|
|
+ viewField: view.backgroundInput,
|
|
|
|
|
+ commandName: 'tableCellBackgroundColor',
|
|
|
|
|
+ errorText: colorErrorText,
|
|
|
|
|
+ validator: colorFieldValidator
|
|
|
|
|
+ } ) );
|
|
|
|
|
+
|
|
|
view.on( 'change:horizontalAlignment', this._getPropertyChangeCallback( 'tableCellHorizontalAlignment' ) );
|
|
view.on( 'change:horizontalAlignment', this._getPropertyChangeCallback( 'tableCellHorizontalAlignment' ) );
|
|
|
view.on( 'change:verticalAlignment', this._getPropertyChangeCallback( 'tableCellVerticalAlignment' ) );
|
|
view.on( 'change:verticalAlignment', this._getPropertyChangeCallback( 'tableCellVerticalAlignment' ) );
|
|
|
|
|
|
|
@@ -275,4 +314,38 @@ export default class TableCellPropertiesUI extends Plugin {
|
|
|
} );
|
|
} );
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Creates a callback that when executed upon {@link #view view's} property change:
|
|
|
|
|
+ * * executes a related editor command with the new property value if the value is valid,
|
|
|
|
|
+ * * or sets the error text next to the invalid field, if the value did not pass the validation.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @private
|
|
|
|
|
+ * @param {Object} options
|
|
|
|
|
+ * @param {String} options.commandName
|
|
|
|
|
+ * @param {module:ui/view~View} options.viewField
|
|
|
|
|
+ * @param {Function} options.validator
|
|
|
|
|
+ * @param {String} options.errorText
|
|
|
|
|
+ * @returns {Function}
|
|
|
|
|
+ */
|
|
|
|
|
+ _getValidatedPropertyChangeCallback( { commandName, viewField, validator, errorText } ) {
|
|
|
|
|
+ const setErrorTextDebounced = debounce( () => {
|
|
|
|
|
+ viewField.errorText = errorText;
|
|
|
|
|
+ }, ERROR_TEXT_TIMEOUT );
|
|
|
|
|
+
|
|
|
|
|
+ return ( evt, propertyName, newValue ) => {
|
|
|
|
|
+ setErrorTextDebounced.cancel();
|
|
|
|
|
+
|
|
|
|
|
+ if ( validator( newValue ) ) {
|
|
|
|
|
+ this.editor.execute( commandName, {
|
|
|
|
|
+ value: newValue,
|
|
|
|
|
+ batch: this._undoStepBatch
|
|
|
|
|
+ } );
|
|
|
|
|
+
|
|
|
|
|
+ viewField.errorText = null;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ setErrorTextDebounced();
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|