diff --git a/packages/ckeditor5-core/theme/icons/object-size-full.svg b/packages/ckeditor5-core/theme/icons/object-size-full.svg
new file mode 100644
index 00000000000..9120563d753
--- /dev/null
+++ b/packages/ckeditor5-core/theme/icons/object-size-full.svg
@@ -0,0 +1 @@
+
diff --git a/packages/ckeditor5-core/theme/icons/object-size-large.svg b/packages/ckeditor5-core/theme/icons/object-size-large.svg
new file mode 100644
index 00000000000..f5e5a37f76f
--- /dev/null
+++ b/packages/ckeditor5-core/theme/icons/object-size-large.svg
@@ -0,0 +1 @@
+
diff --git a/packages/ckeditor5-core/theme/icons/object-size-medium.svg b/packages/ckeditor5-core/theme/icons/object-size-medium.svg
new file mode 100644
index 00000000000..69713e30376
--- /dev/null
+++ b/packages/ckeditor5-core/theme/icons/object-size-medium.svg
@@ -0,0 +1 @@
+
diff --git a/packages/ckeditor5-core/theme/icons/object-size-small.svg b/packages/ckeditor5-core/theme/icons/object-size-small.svg
new file mode 100644
index 00000000000..661c575fd73
--- /dev/null
+++ b/packages/ckeditor5-core/theme/icons/object-size-small.svg
@@ -0,0 +1 @@
+
diff --git a/packages/ckeditor5-image/docs/_snippets/features/image-resizeui.js b/packages/ckeditor5-image/docs/_snippets/features/image-resizeui.js
index 2327d7c1167..f2f8b1c827d 100644
--- a/packages/ckeditor5-image/docs/_snippets/features/image-resizeui.js
+++ b/packages/ckeditor5-image/docs/_snippets/features/image-resizeui.js
@@ -17,26 +17,29 @@ ClassicEditor
resizeOptions: [
{
name: 'imageResize:original',
- label: 'Original size',
- value: null
+ label: 'Original',
+ value: null,
+ icon: 'original'
},
{
name: 'imageResize:50',
label: '50%',
- value: '50'
+ value: '50',
+ icon: 'medium'
},
{
name: 'imageResize:75',
label: '75%',
- value: '75'
+ value: '75',
+ icon: 'large'
}
],
toolbar: [
'imageStyle:full',
'imageStyle:side', '|',
- 'imageResize:original',
'imageResize:50',
- 'imageResize:75'
+ 'imageResize:75',
+ 'imageResize:original'
]
},
cloudServices: CS_CONFIG
diff --git a/packages/ckeditor5-image/docs/_snippets/features/image-resizeuidropdown.js b/packages/ckeditor5-image/docs/_snippets/features/image-resizeuidropdown.js
index 15675720c49..3314067ecea 100644
--- a/packages/ckeditor5-image/docs/_snippets/features/image-resizeuidropdown.js
+++ b/packages/ckeditor5-image/docs/_snippets/features/image-resizeuidropdown.js
@@ -17,7 +17,7 @@ ClassicEditor
resizeOptions: [
{
name: 'imageResize:original',
- label: 'Original size',
+ label: 'Original',
value: null
},
{
diff --git a/packages/ckeditor5-image/lang/contexts.json b/packages/ckeditor5-image/lang/contexts.json
index 80bba6e2d8d..da6c3337c43 100644
--- a/packages/ckeditor5-image/lang/contexts.json
+++ b/packages/ckeditor5-image/lang/contexts.json
@@ -11,7 +11,9 @@
"Insert image": "Label for the insert image toolbar button.",
"Upload failed": "Title of the notification displayed when upload fails.",
"Image toolbar": "The label used by assistive technologies describing an image toolbar attached to an image widget.",
- "Resize image to": "The label used for the standalone resize option buttons in the image toolbar",
- "Resize image": "The label used for the dropdown in the image toolbar, containing defined resize options",
- "Resize image to the original size": "The label used for the standalone resize reset option button in the image toolbar, when user set the value to `null`"
+ "Resize image": "The label used for the dropdown in the image toolbar containing defined resize options",
+ "Resize image to %0": "The label used for the standalone resize options buttons in the image toolbar",
+ "Resize image to the original size": "The accessibility label of the standalone image resize reset option button in the image toolbar for the screen readers",
+ "Original": "Default label for the resize option that resets the size of the image.",
+ "Image resize list": "The accessibility label of the image resize dropdown list for the screen readers."
}
diff --git a/packages/ckeditor5-image/src/imageresize.js b/packages/ckeditor5-image/src/imageresize.js
index d32eab59bea..faad8b2ae76 100644
--- a/packages/ckeditor5-image/src/imageresize.js
+++ b/packages/ckeditor5-image/src/imageresize.js
@@ -58,16 +58,21 @@ export default class ImageResize extends Plugin {
*/
/**
- * The resize options.
+ * The image resize options.
*
- * Each option should have its `name`, which is a component name definition that will be
- * used in the {@link module:image/imageresize/imageresizeui~ImageResizeUI} plugin.
- * Other properties like `label` and `value` define the following:
- * a text label for the option button and the value that will be applied to the image's width.
+ * Each option should have at least these two properties:
*
- * The value property is combined with the `resizeUnit` (`%` by default), eg: `value: '50'` and `resizeUnit: '%'` is `50%`.
+ * * name: The name of the UI component registered in the global
+ * {@link module:core/editor/editorui~EditorUI#componentFactory component factory} of the editor,
+ * representing the button a user can click to change the size of an image,
+ * * value: An actual image width applied when a user clicks the mentioned button
+ * ({@link module:image/imageresize/imageresizecommand~ImageResizeCommand} gets executed).
+ * The value property is combined with the {@link module:image/image~ImageConfig#resizeUnit `config.image.resizeUnit`} (`%` by default).
+ * For instance: `value: '50'` and `resizeUnit: '%'` will render as `'50%'` in the UI.
*
- * **NOTE:** If you want to set an option that will reset image to its original size, you need to pass a `null` value
+ * **Resetting the image size**
+ *
+ * If you want to set an option that will reset image to its original size, you need to pass a `null` value
* to one of the options. The `:original` token is not mandatory, you can call it anything you wish, but it must reflect
* in the standalone buttons configuration for the image toolbar.
*
@@ -77,17 +82,14 @@ export default class ImageResize extends Plugin {
* resizeUnit: "%",
* resizeOptions: [ {
* name: 'imageResize:original',
- * label: 'Original size',
* value: null
* },
* {
* name: 'imageResize:50',
- * label: '50%',
* value: '50'
* },
* {
* name: 'imageResize:75',
- * label: '75%',
* value: '75'
* } ]
* }
@@ -95,27 +97,26 @@ export default class ImageResize extends Plugin {
* .then( ... )
* .catch( ... );
*
+ * **Resizing images using a dropdown**
+ *
* With resize options defined, you can decide whether you want to display them as a dropdown or as standalone buttons.
- * For the dropdown, you need to pass only the `imageResize` token to the `image.toolbar`.
- * The dropdown contains all defined options by default:
+ * For the dropdown, you need to pass only the `imageResize` token to the
+{@link module:image/image~ImageConfig#toolbar `config.image.toolbar`}. The dropdown contains all defined options by default:
*
- * ClassicEditor
+ * ClassicEditor
* .create( editorElement, {
* image: {
* resizeUnit: "%",
* resizeOptions: [ {
* name: 'imageResize:original',
- * label: 'Original size',
* value: null
* },
* {
* name: 'imageResize:50',
- * label: '50%',
* value: '50'
* },
* {
* name: 'imageResize:75',
- * label: '75%',
* value: '75'
* } ],
* toolbar: [ 'imageResize', ... ],
@@ -124,33 +125,76 @@ export default class ImageResize extends Plugin {
* .then( ... )
* .catch( ... );
*
- * If you want to have separate buttons for each option, pass their names instead:
+ * **Resizing images using individual buttons**
+ *
+ * If you want to have separate buttons for {@link module:image/imageresize/imageresizeui~ImageResizeOption each option},
+ * pass their names to the {@link module:image/image~ImageConfig#toolbar `config.image.toolbar`} instead. Please keep in mind
+ * that this time **you must define the additional
+ * {@link module:image/imageresize/imageresizeui~ImageResizeOption `icon` property}**:
*
- * ClassicEditor
+ * ClassicEditor
* .create( editorElement, {
* image: {
* resizeUnit: "%",
* resizeOptions: [ {
* name: 'imageResize:original',
- * label: 'Original size',
* value: null
+ * icon: 'original'
+ * },
+ * {
+ * name: 'imageResize:25',
+ * value: '25'
+ * icon: 'small'
* },
* {
* name: 'imageResize:50',
- * label: '50%',
* value: '50'
+ * icon: 'medium'
* },
* {
* name: 'imageResize:75',
- * label: '75%',
* value: '75'
+ * icon: 'large'
* } ],
- * toolbar: [ 'imageResize:original', 'imageResize:50', 'imageResize:75', ... ],
+ * toolbar: [ 'imageResize:25', 'imageResize:50', 'imageResize:75', 'imageResize:original', ... ],
* }
* } )
* .then( ... )
* .catch( ... );
*
+ * **Customizing resize button labels**
+ *
+ * You can set your own label for each resize button. To do that, add the `label` property like in the example below.
+ *
+ * * When using the **dropdown**, the labels are displayed on the list of all options when you open the dropdown.
+ * * When using **standalone buttons**, the labels will are displayed as tooltips when a user hovers over the button.
+ *
+ * ClassicEditor
+ * .create( editorElement, {
+ * image: {
+ * resizeUnit: "%",
+ * resizeOptions: [ {
+ * name: 'imageResize:original',
+ * value: null,
+ * label: 'Original size'
+ * // Note: add the "icon" property if you're configuring a standalone button.
+ * },
+ * {
+ * name: 'imageResize:50',
+ * value: '50',
+ * label: 'Medium size'
+ * // Note: add the "icon" property if you're configuring a standalone button.
+ * },
+ * {
+ * name: 'imageResize:75',
+ * value: '75',
+ * label: 'Large size'
+ * // Note: add the "icon" property if you're configuring a standalone button.
+ * } ]
+ * }
+ * } )
+ * .then( ... )
+ * .catch( ... );
*
* @member {Array.} module:image/image~ImageConfig#resizeOptions
*/
diff --git a/packages/ckeditor5-image/src/imageresize/imageresizeediting.js b/packages/ckeditor5-image/src/imageresize/imageresizeediting.js
index 4e6bd1fa94e..6022a87e122 100644
--- a/packages/ckeditor5-image/src/imageresize/imageresizeediting.js
+++ b/packages/ckeditor5-image/src/imageresize/imageresizeediting.js
@@ -4,7 +4,7 @@
*/
/**
- * @module image/imageresizeediting
+ * @module image/imageresize/imageresizeediting
*/
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
diff --git a/packages/ckeditor5-image/src/imageresize/imageresizeui.js b/packages/ckeditor5-image/src/imageresize/imageresizeui.js
index abf1f909ef0..813a8857afa 100644
--- a/packages/ckeditor5-image/src/imageresize/imageresizeui.js
+++ b/packages/ckeditor5-image/src/imageresize/imageresizeui.js
@@ -16,10 +16,24 @@ import DropdownButtonView from '@ckeditor/ckeditor5-ui/src/dropdown/button/dropd
import Model from '@ckeditor/ckeditor5-ui/src/model';
import Collection from '@ckeditor/ckeditor5-utils/src/collection';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+import iconSmall from '@ckeditor/ckeditor5-core/theme/icons/object-size-small.svg';
+import iconMedium from '@ckeditor/ckeditor5-core/theme/icons/object-size-medium.svg';
+import iconLarge from '@ckeditor/ckeditor5-core/theme/icons/object-size-large.svg';
+import iconFull from '@ckeditor/ckeditor5-core/theme/icons/object-size-full.svg';
+
+const RESIZE_ICONS = {
+ small: iconSmall,
+ medium: iconMedium,
+ large: iconLarge,
+ original: iconFull
+};
+
/**
* The `ImageResizeUI` plugin.
*
- * It adds a possibility to resize each image using toolbar dropdown or separate buttons, depends on the plugin configuration.
+ * It adds a possibility to resize images using the toolbar dropdown or individual buttons, depending on the plugin configuration.
*
* @extends module:core/plugin~Plugin
*/
@@ -38,6 +52,23 @@ export default class ImageResizeUI extends Plugin {
return 'ImageResizeUI';
}
+ /**
+ * @inheritDoc
+ */
+ constructor( editor ) {
+ super( editor );
+
+ /**
+ * The resize unit.
+ *
+ * @readonly
+ * @private
+ * @type {module:image/image~ImageConfig#resizeUnit}
+ * @default '%'
+ */
+ this._resizeUnit = editor.config.get( 'image.resizeUnit' ) || '%';
+ }
+
/**
* @inheritDoc
*/
@@ -45,7 +76,6 @@ export default class ImageResizeUI extends Plugin {
const editor = this.editor;
const options = editor.config.get( 'image.resizeOptions' );
const command = editor.commands.get( 'imageResize' );
- const resizeUnit = editor.config.get( 'image.resizeUnit' ) || '%';
if ( !options ) {
return;
@@ -54,44 +84,62 @@ export default class ImageResizeUI extends Plugin {
this.bind( 'isEnabled' ).to( command );
for ( const option of options ) {
- this._addButton( option, resizeUnit );
+ this._registerImageResizeButton( option );
}
- this._addDropdown( options, resizeUnit );
+ this._registerImageResizeDropdown( options );
}
/**
* A helper function that creates a standalone button component for the plugin.
*
* @private
- *
* @param {module:image/imageresize/imageresizeui~ImageResizeOption} resizeOption A model of resize option.
- * @param {String} unit A resize unit.
*/
- _addButton( { name, label, value }, unit ) {
+ _registerImageResizeButton( option ) {
const editor = this.editor;
- const t = editor.t;
- const parsedValue = value ? value + unit : null;
+ const { name, value, icon } = option;
+ const optionValueWithUnit = value ? value + this._resizeUnit : null;
editor.ui.componentFactory.add( name, locale => {
const button = new ButtonView( locale );
const command = editor.commands.get( 'imageResize' );
- const commandCallback = setOptionOn( parsedValue );
+ const labelText = this._getOptionLabelValue( option, true );
+
+ if ( !RESIZE_ICONS[ icon ] ) {
+ /**
+ * When configuring {@link module:image/image~ImageConfig#resizeOptions `config.image.resizeOptions`} for standalone
+ * buttons, a valid `icon` token must be set for each option.
+ *
+ * See all valid options described in the
+ * {@link module:image/imageresize/imageresizeui~ImageResizeOption plugin configuration}.
+ *
+ * @error imageresizeui-missing-icon
+ * @param {module:image/imageresize/imageresizeui~ImageResizeOption} option Invalid image resize option.
+ */
+ throw new CKEditorError(
+ 'imageresizeui-missing-icon: ' +
+ 'The resize option "' + name + '" misses the "icon" property ' +
+ 'or the property value doesn\'t match any of available icons.',
+ editor,
+ option
+ );
+ }
button.set( {
- label: t( label ),
- withText: true,
- tooltip: parsedValue ? t( 'Resize image to' ) + ' ' + parsedValue : t( 'Resize image to the original size' ),
- isToggleable: true,
- commandValue: parsedValue
+ // Use the `label` property for a verbose description (because of ARIA).
+ label: labelText,
+ icon: RESIZE_ICONS[ icon ],
+ tooltip: labelText,
+ isToggleable: true
} );
// Bind button to the command.
button.bind( 'isEnabled' ).to( this );
- button.bind( 'isOn' ).to( command, 'value', commandCallback );
+ button.bind( 'isOn' ).to( command, 'value', getIsOnButtonCallback( optionValueWithUnit ) );
- this.listenTo( button, 'execute', evt => {
- editor.execute( 'imageResize', { width: evt.source.commandValue } );
+ this.listenTo( button, 'execute', () => {
+ editor.execute( 'imageResize', { width: optionValueWithUnit } );
} );
return button;
@@ -99,19 +147,16 @@ export default class ImageResizeUI extends Plugin {
}
/**
- * A helper function that creates a dropdown component for the plugin containing all resize options created through the
- * plugin configuration settings.
+ * A helper function that creates a dropdown component for the plugin containing all resize options defined in
+ * the editor configuration.
*
* @private
- *
- * @param {Array.} options An array of the configured options.
- * @param {String} unit A resize unit.
+ * @param {Array.} options An array of configured options.
*/
- _addDropdown( options, unit ) {
+ _registerImageResizeDropdown( options ) {
const editor = this.editor;
const t = editor.t;
- const firstOption = options[ 0 ];
- const resetOption = options.find( option => option.value === null );
+ const originalSizeOption = options.find( option => !option.value );
// Register dropdown.
editor.ui.componentFactory.add( 'imageResize', locale => {
@@ -121,19 +166,25 @@ export default class ImageResizeUI extends Plugin {
dropdownButton.set( {
tooltip: t( 'Resize image' ),
- commandValue: firstOption.value,
+ commandValue: originalSizeOption.value,
+ icon: iconMedium,
isToggleable: true,
- label: firstOption.label,
- withText: true
+ label: this._getOptionLabelValue( originalSizeOption ),
+ withText: true,
+ class: 'ck-resize-image-button'
} );
dropdownButton.bind( 'label' ).to( command, 'value', commandValue => {
- return commandValue && commandValue.width || resetOption.label;
+ if ( commandValue && commandValue.width ) {
+ return commandValue.width;
+ } else {
+ return this._getOptionLabelValue( originalSizeOption );
+ }
} );
dropdownView.bind( 'isOn' ).to( command );
dropdownView.bind( 'isEnabled' ).to( this );
- addListToDropdown( dropdownView, prepareListDefinitions( options, command, unit ) );
+ addListToDropdown( dropdownView, this._getResizeDropdownListItemDefinitions( options, command ) );
dropdownView.listView.ariaLabel = t( 'Image resize list' );
@@ -146,40 +197,73 @@ export default class ImageResizeUI extends Plugin {
return dropdownView;
} );
}
-}
-// A helper function for parsing resize options definitions.
-function prepareListDefinitions( definitions, command, resizeUnit ) {
- const itemDefinitions = new Collection();
-
- definitions.map( itemDefinition => {
- const parsedValue = itemDefinition.value ? itemDefinition.value + resizeUnit : null;
- const definition = {
- type: 'button',
- model: new Model( {
- commandName: 'imageResize',
- commandValue: parsedValue,
- label: itemDefinition.label,
- withText: true,
- icon: null
- } )
- };
-
- const commandCallback = setOptionOn( parsedValue );
-
- definition.model.bind( 'isOn' ).to( command, 'value', commandCallback );
+ /**
+ * A helper function for creating an option label value string.
+ *
+ * @private
+ * @param {module:image/imageresize/imageresizeui~ImageResizeOption} option A resize option object.
+ * @param {Boolean} [forTooltip] An optional flag for creating a tooltip label.
+ * @returns {String} A user-defined label, a label combined from the value and resize unit or the default label
+ * for reset options (`Original`).
+ */
+ _getOptionLabelValue( option, forTooltip ) {
+ const t = this.editor.t;
+
+ if ( option.label ) {
+ return option.label;
+ } else if ( forTooltip ) {
+ if ( option.value ) {
+ return t( 'Resize image to %0', option.value + this._resizeUnit );
+ } else {
+ return t( 'Resize image to the original size' );
+ }
+ } else {
+ if ( option.value ) {
+ return option.value + this._resizeUnit;
+ } else {
+ return t( 'Original' );
+ }
+ }
+ }
- itemDefinitions.add( definition );
- } );
+ /**
+ * A helper function that parses resize options and returns list item definitions ready for use in a dropdown.
+ *
+ * @private
+ * @param {Array.} options The resize options.
+ * @param {module:image/imageresize/imageresizecommand~ImageResizeCommand} command A resize image command.
+ * @returns {Iterable.} Dropdown item definitions.
+ */
+ _getResizeDropdownListItemDefinitions( options, command ) {
+ const itemDefinitions = new Collection();
+
+ options.map( option => {
+ const optionValueWithUnit = option.value ? option.value + this._resizeUnit : null;
+ const definition = {
+ type: 'button',
+ model: new Model( {
+ commandName: 'imageResize',
+ commandValue: optionValueWithUnit,
+ label: this._getOptionLabelValue( option ),
+ withText: true,
+ icon: null
+ } )
+ };
+
+ definition.model.bind( 'isOn' ).to( command, 'value', getIsOnButtonCallback( optionValueWithUnit ) );
+
+ itemDefinitions.add( definition );
+ } );
- return itemDefinitions;
+ return itemDefinitions;
+ }
}
-// A helper function for setting the `isOn` state used for creating a callback function in a value binding.
-function setOptionOn( value ) {
+// A helper function for setting the `isOn` state of buttons in value bindings.
+function getIsOnButtonCallback( value ) {
return commandValue => {
- // Set reseting option on when command equals `null`.
- if ( commandValue === value ) {
+ if ( value === null && commandValue === value ) {
return true;
}
@@ -188,12 +272,19 @@ function setOptionOn( value ) {
}
/**
- * A resize option type.
+ * An image resize option used in the {@link module:image/image~ImageConfig#resizeOptions image resize configuration}.
*
* @typedef {Object} module:image/imageresize/imageresizeui~ImageResizeOption
- *
- * @property {String} resizeOption.name A name of the option used for creating a component.
- * You refer to that name later in the {@link module:image/image~ImageConfig#toolbar}.
- * @property {String} resizeOption.label A label to be displayed with a button.
- * @property {String} resizeOption.value A value of a resize option. `null` value is for resetting an image to its original size.
+ * @property {String} name A name of the UI component that changes the image size.
+ * * If you configure the feature using individual resize buttons, you can refer to this name in the
+ * {@link module:image/image~ImageConfig#toolbar image toolbar configuration}.
+ * * If you configure the feature using the resize dropdown, this name will be used for a list item in the dropdown.
+ * @property {String} value A value of a resize option without the unit
+ * ({@link module:image/image~ImageConfig#resizeUnit configured separately}). `null` resets an image to its original size.
+ * @property {String} [resizeOptions.icon] An icon used by an individual resize button (see the `name` property to learn more).
+ * Available icons are: `'small'`, `'medium'`, `'large'`, `'original'`.
+ * @property {String} [label] A label of the option displayed in the dropdown or, if the feature is configured using
+ * individual buttons, a {@link module:ui/button/buttonview~ButtonView#tooltip} and an ARIA attribute of a button.
+ * If not specified, the label is generated automatically based on the option `value` and the
+ * {@link module:image/image~ImageConfig#resizeUnit `config.image.resizeUnit`}.
*/
diff --git a/packages/ckeditor5-image/tests/imageresize/imageresizeui.js b/packages/ckeditor5-image/tests/imageresize/imageresizeui.js
index aeacf1340d5..aa49d04a06d 100644
--- a/packages/ckeditor5-image/tests/imageresize/imageresizeui.js
+++ b/packages/ckeditor5-image/tests/imageresize/imageresizeui.js
@@ -17,23 +17,30 @@ import Undo from '@ckeditor/ckeditor5-undo/src/undo';
import Table from '@ckeditor/ckeditor5-table/src/table';
import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
+import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
+
+import iconSmall from '@ckeditor/ckeditor5-core/theme/icons/object-size-small.svg';
+import iconMedium from '@ckeditor/ckeditor5-core/theme/icons/object-size-medium.svg';
+import iconLarge from '@ckeditor/ckeditor5-core/theme/icons/object-size-large.svg';
+import iconFull from '@ckeditor/ckeditor5-core/theme/icons/object-size-full.svg';
describe( 'ImageResizeUI', () => {
let plugin, command, editor, editorElement;
const resizeOptions = [ {
name: 'imageResize:original',
- label: 'Original size',
value: null
},
+ {
+ name: 'imageResize:25',
+ value: '25'
+ },
{
name: 'imageResize:50',
- label: '50%',
value: '50'
},
{
name: 'imageResize:75',
- label: '75%',
value: '75'
} ];
@@ -47,7 +54,6 @@ describe( 'ImageResizeUI', () => {
.create( editorElement, {
plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeUI ],
image: {
- resizeUnit: '%',
resizeOptions
}
} );
@@ -70,66 +76,25 @@ describe( 'ImageResizeUI', () => {
it( 'should be named', () => {
expect( ImageResizeUI.pluginName ).to.equal( 'ImageResizeUI' );
} );
-
- it( 'should be disabled when command is disabled', () => {
- command.isEnabled = true;
-
- expect( plugin.isEnabled ).to.be.true;
-
- command.isEnabled = false;
-
- expect( plugin.isEnabled ).to.be.false;
- } );
} );
- describe( 'init()', () => {
- it( 'should have set "%" resize unit', () => {
- const unit = editor.config.get( 'image.resizeUnit' );
+ describe( 'constructor()', () => {
+ it( 'should create `_resizeUnit` with default value of `%`', () => {
+ const unit = plugin._resizeUnit;
expect( unit ).to.equal( '%' );
} );
+ } );
- it( 'should have set "%" resize unit if not defined', async () => {
- const editor = await ClassicTestEditor
- .create( editorElement, {
- plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeUI ],
- image: {
- resizeOptions
- }
- } );
-
- const button = editor.ui.componentFactory.create( 'imageResize:50' );
- const command = editor.commands.get( 'imageResize' );
-
- command.isEnabled = true;
-
- button.fire( 'execute' );
-
- expect( command.value.width.includes( '%' ) ).to.be.true;
-
- await editor.destroy();
- } );
-
- it( 'should have set "px" resize unit', async () => {
- const editor = await ClassicTestEditor
- .create( editorElement, {
- plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeUI ],
- image: {
- resizeUnit: 'px',
- resizeOptions
- }
- } );
-
- const button = editor.ui.componentFactory.create( 'imageResize:50' );
- const command = editor.commands.get( 'imageResize' );
-
+ describe( 'init()', () => {
+ it( 'should be disabled when command is disabled', () => {
command.isEnabled = true;
- button.fire( 'execute' );
+ expect( plugin.isEnabled ).to.be.true;
- expect( command.value.width.includes( 'px' ) ).to.be.true;
+ command.isEnabled = false;
- await editor.destroy();
+ expect( plugin.isEnabled ).to.be.false;
} );
it( 'should not register a dropdown or buttons if no resize options passed', async () => {
@@ -167,12 +132,12 @@ describe( 'ImageResizeUI', () => {
expect( editor.ui.componentFactory.create( 'imageResize' ) ).to.be.instanceof( DropdownView );
} );
- it( 'should have 3 resize options in the `imageResize` dropdown', () => {
+ it( 'should have 4 resize options in the `imageResize` dropdown', () => {
const dropdownView = editor.ui.componentFactory.create( 'imageResize' );
- expect( dropdownView.listView.items.length ).to.equal( 3 );
- expect( dropdownView.listView.items.first.element.textContent ).to.equal( 'Original size' );
- expect( dropdownView.listView.items._items[ 1 ].element.textContent ).to.equal( '50%' );
+ expect( dropdownView.listView.items.length ).to.equal( 4 );
+ expect( dropdownView.listView.items.first.element.textContent ).to.equal( 'Original' );
+ expect( dropdownView.listView.items._items[ 1 ].element.textContent ).to.equal( '25%' );
expect( dropdownView.listView.items.last.element.textContent ).to.equal( '75%' );
} );
@@ -192,11 +157,56 @@ describe( 'ImageResizeUI', () => {
resizeBy50Percent.fire( 'execute' );
sinon.assert.calledOnce( commandSpy );
- expect( command.value.width ).to.equal( '50%' );
+ expect( command.value.width ).to.equal( '25%' );
} );
} );
describe( 'resize option button', () => {
+ let editor, plugin;
+
+ beforeEach( async () => {
+ editor = await ClassicTestEditor
+ .create( editorElement, {
+ plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeUI ],
+ image: {
+ resizeUnit: '%',
+ resizeOptions: [ {
+ name: 'imageResize:original',
+ value: null,
+ icon: 'original'
+ },
+ {
+ name: 'imageResize:25',
+ value: '25',
+ icon: 'small'
+ },
+ {
+ name: 'imageResize:50',
+ value: '50',
+ icon: 'medium'
+ },
+ {
+ name: 'imageResize:75',
+ value: '75',
+ icon: 'large'
+ } ],
+ toolbar: [ 'imageResize:original', 'imageResize:25', 'imageResize:50', 'imageResize:75' ]
+ }
+ } );
+
+ plugin = editor.plugins.get( 'ImageResizeUI' );
+ } );
+
+ afterEach( async () => {
+ if ( editorElement ) {
+ editorElement.remove();
+ }
+
+ if ( editor ) {
+ await editor.destroy();
+ }
+ } );
+
it( 'should be bound to `#isEnabled`', () => {
const buttonView = editor.ui.componentFactory.create( 'imageResize:50' );
@@ -213,13 +223,41 @@ describe( 'ImageResizeUI', () => {
expect( editor.ui.componentFactory.create( 'imageResize:50' ) ).to.be.instanceof( ButtonView );
} );
- it( 'should be created with visible "50%" label', () => {
+ it( 'should be created with invisible "Resize image: 30%" label when is provided', async () => {
+ const editor = await ClassicTestEditor
+ .create( editorElement, {
+ plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeUI ],
+ image: {
+ resizeUnit: '%',
+ resizeOptions: [ {
+ name: 'imageResize:30',
+ value: '30',
+ label: 'Resize image: 30%',
+ icon: 'small'
+ } ],
+ toolbar: [ 'imageResize:30' ]
+ }
+ } );
+
+ const buttonView = editor.ui.componentFactory.create( 'imageResize:30' );
+ buttonView.render();
+
+ expect( buttonView.withText ).to.be.false;
+ expect( buttonView.label ).to.equal( 'Resize image: 30%' );
+ expect( buttonView.labelView ).to.be.instanceOf( View );
+
+ editor.destroy();
+ } );
+
+ it( 'should be created with invisible "Resize image to 50%" label when is not provided', async () => {
const buttonView = editor.ui.componentFactory.create( 'imageResize:50' );
buttonView.render();
- expect( buttonView.withText ).to.be.true;
- expect( buttonView.label ).to.equal( '50%' );
+ expect( buttonView.withText ).to.be.false;
+ expect( buttonView.label ).to.equal( 'Resize image to 50%' );
expect( buttonView.labelView ).to.be.instanceOf( View );
+
+ editor.destroy();
} );
it( 'should be created with a proper tooltip, depends on the set value', () => {
@@ -233,12 +271,6 @@ describe( 'ImageResizeUI', () => {
expect( buttonView50.tooltip ).to.equal( 'Resize image to 50%' );
} );
- it( 'should have `commandValue` equal "50%"', () => {
- const buttonView = editor.ui.componentFactory.create( 'imageResize:50' );
-
- expect( buttonView.commandValue ).to.equal( '50%' );
- } );
-
it( 'should execute `imageResize` command with "50%" value', () => {
const buttonView = editor.ui.componentFactory.create( 'imageResize:50' );
const command = editor.commands.get( 'imageResize' );
@@ -251,5 +283,41 @@ describe( 'ImageResizeUI', () => {
sinon.assert.calledOnce( commandSpy );
expect( command.value.width ).to.equal( '50%' );
} );
+
+ it( 'should have set a proper icon', () => {
+ const buttonOriginal = editor.ui.componentFactory.create( 'imageResize:original' );
+ const button25 = editor.ui.componentFactory.create( 'imageResize:25' );
+ const button50 = editor.ui.componentFactory.create( 'imageResize:50' );
+ const button75 = editor.ui.componentFactory.create( 'imageResize:75' );
+
+ expect( buttonOriginal.icon ).to.deep.equal( iconFull );
+ expect( button25.icon ).to.deep.equal( iconSmall );
+ expect( button50.icon ).to.deep.equal( iconMedium );
+ expect( button75.icon ).to.deep.equal( iconLarge );
+ } );
+
+ it( 'should throw the CKEditorError if no `icon` is provided', async () => {
+ const editor = await ClassicTestEditor
+ .create( editorElement, {
+ plugins: [ Image, ImageStyle, Paragraph, Undo, Table, ImageResizeUI ],
+ image: {
+ resizeUnit: '%',
+ resizeOptions: [ {
+ name: 'imageResize:noicon',
+ value: '100'
+ } ],
+ toolbar: [ 'imageResize:noicon' ]
+ }
+ } );
+
+ const errMsg = 'The resize option "imageResize:noicon" misses the "icon" property ' +
+ 'or the property value doesn\'t match any of available icons.';
+
+ expectToThrowCKEditorError( () => {
+ editor.ui.componentFactory.create( 'imageResize:noicon' );
+ }, errMsg, editor );
+
+ editor.destroy();
+ } );
} );
} );
diff --git a/packages/ckeditor5-image/tests/manual/imageresizeui.js b/packages/ckeditor5-image/tests/manual/imageresizeui.js
index 015043ef6a8..dec851c7626 100644
--- a/packages/ckeditor5-image/tests/manual/imageresizeui.js
+++ b/packages/ckeditor5-image/tests/manual/imageresizeui.js
@@ -36,17 +36,14 @@ const imageConfig1 = {
resizeOptions: [
{
name: 'imageResize:original',
- label: 'Original size',
value: null
},
{
name: 'imageResize:50',
- label: '50%',
value: '50'
},
{
name: 'imageResize:75',
- label: '75%',
value: '75'
}
],
@@ -66,7 +63,7 @@ const config1 = {
ClassicEditor
.create( document.querySelector( '#editor1' ), config1 )
.then( editor => {
- window.editor = editor;
+ window.editor1 = editor;
} )
.catch( err => {
console.error( err.stack );
@@ -77,27 +74,27 @@ const imageConfig2 = {
resizeOptions: [
{
name: 'imageResize:original',
- label: 'Original size',
- value: null
+ value: null,
+ icon: 'original'
},
{
name: 'imageResize:50',
- label: '50%',
- value: '50'
+ value: '50',
+ icon: 'medium'
},
{
name: 'imageResize:75',
- label: '75%',
- value: '75'
+ value: '75',
+ icon: 'large'
}
],
toolbar: [
'imageStyle:alignLeft',
'imageStyle:full',
'imageStyle:side', '|',
- 'imageResize:original',
'imageResize:50',
- 'imageResize:75'
+ 'imageResize:75',
+ 'imageResize:original'
],
styles: [
'full',
@@ -114,7 +111,7 @@ const config2 = {
ClassicEditor
.create( document.querySelector( '#editor2' ), config2 )
.then( editor => {
- window.editor = editor;
+ window.editor2 = editor;
} )
.catch( err => {
console.error( err.stack );
diff --git a/packages/ckeditor5-image/tests/manual/imageresizeui.md b/packages/ckeditor5-image/tests/manual/imageresizeui.md
index 2b4205a8569..861014a9a87 100644
--- a/packages/ckeditor5-image/tests/manual/imageresizeui.md
+++ b/packages/ckeditor5-image/tests/manual/imageresizeui.md
@@ -1,11 +1,20 @@
## Image Resize UI
-The tests for manual image resizing.
-- The first test should have the dropdown with configured options in the image toolbar (using `imageResize`).
- - Plugin icon should appear only in the dropbdown button.
- - Each option should have a label text represented an option value defined in the plugin configuration.
- - Selected options should be set "on" when dropdown is open.
-- The second one should have the standalone buttons instead of dropdown (from the first test) in the image toolbar (using
-`imageResize:option`).
- - Each option should have the plugin icon "stretched" over the label text which represents an option value defined in the plugin configuration.
- - Selected option should be set "on".
+Tests for manual image resizing using the UI in the image toolbar.
+
+## Dropdown
+
+1. Select an image in the editor.
+2. A dropdown with configured options (`config.image.resizeOptions`) should be visible in the toolbar.
+ - The plugin icon should appear only next to the dropdown button.
+ - Each option should have a label text corresponding to an option value defined in the configuration.
+ - The selected option should be "on" when the dropdown is open.
+
+## Buttons
+
+1. Select an image in the editor.
+2. Standalone buttons should be displayed in the image toolbar (corresponding to `config.image.resizeOptions`).
+ - Each button should have an icon as in the configuration (`small`, `medium`, `large` or `original`).
+ - No label should be rendered,
+ - The tooltip text and the `aria-label` attribute should be the same (and more verbose).
+ - The selected option button should be "on".
diff --git a/packages/ckeditor5-image/theme/imageresize.css b/packages/ckeditor5-image/theme/imageresize.css
index 1ba212cfd88..4c9c336c5e5 100644
--- a/packages/ckeditor5-image/theme/imageresize.css
+++ b/packages/ckeditor5-image/theme/imageresize.css
@@ -23,3 +23,15 @@
display: block;
}
}
+
+[dir="ltr"] .ck.ck-button.ck-button_with-text.ck-resize-image-button .ck-button__icon {
+ margin-right: var(--ck-spacing-standard);
+}
+
+[dir="rtl"] .ck.ck-button.ck-button_with-text.ck-resize-image-button .ck-button__icon {
+ margin-left: var(--ck-spacing-standard);
+}
+
+.ck.ck-dropdown .ck-button.ck-resize-image-button .ck-button__label {
+ width: 4em;
+}