Skip to content

Commit

Permalink
Merge pull request #7654 from ckeditor/i/7579
Browse files Browse the repository at this point in the history
Other (image): Allow to configure `ImageResize` in a more granular way. For example, by combining `ImageResizeEditing` with `ImageResizeHandles` or `ImageResizeButtons` to resize image by handles or by image toolbar UI components (dropdown or standalone buttons) respectively. Closes #7579.

Docs (image): Add a new section to feature documentation for the `Image` plugin about disabling image resize handles.

Internal (image): Separate `ImageResizeHandles` plugin from the `ImageResizeEditing`.

Tests (image): Refactor unit tests for `ImageResizeHandles` and `ImageResizeEditing`.
  • Loading branch information
jodator authored Jul 23, 2020
2 parents c175e1c + 0e9ccc0 commit 3396d4e
Show file tree
Hide file tree
Showing 18 changed files with 670 additions and 477 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div id="snippet-image-resizeui-dropdown">
<div id="snippet-image-resize-buttons-dropdown">
<h3>Resize me using the dropdown!</h3>

<figure class="image">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config.js';

ClassicEditor
.create( document.querySelector( '#snippet-image-resizeui-dropdown' ), {
.create( document.querySelector( '#snippet-image-resize-buttons-dropdown' ), {
removePlugins: [ 'LinkImage' ],
toolbar: {
viewportTopOffset: window.getViewportTopOffsetConfig()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div id="snippet-image-resizeui">
<div id="snippet-image-resize-buttons">
<h3>Resize me using image toolbar buttons!</h3>

<figure class="image">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config.js';

ClassicEditor
.create( document.querySelector( '#snippet-image-resizeui' ), {
.create( document.querySelector( '#snippet-image-resize-buttons' ), {
removePlugins: [ 'LinkImage' ],
toolbar: {
viewportTopOffset: window.getViewportTopOffsetConfig()
Expand Down
84 changes: 81 additions & 3 deletions packages/ckeditor5-image/docs/features/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,49 @@ The plugin also gives you an ability to change the size of the image through the

### Methods to resize images

The editor offers three ways to resize images. One of them (resize handles) is
The editor offers different ways to resize images either by using resize handles or by using dedicated UI components.

#### Using handles

In this case, the user is able to resize images via dragging square handles displayed in each corner of the image. Once [image resizing was enabled](#enabling-image-resizing), this option does not require any additional configuration.

{@snippet features/image-resize}

You can configure the editor for resizing images by handles in two different ways:

- By installing the {@link module:image/imageresize~ImageResize} plugin, which contains **all** needed features (`ImageResizeEditing`, `ImageResizeHandles`, `ImageResizeButtons`).

```js
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';

ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ Image, ImageResize, ... ],
...
} )
.then( ... )
.catch( ... );
```

- Or by installing the combination of {@link module:image/imageresize/imageresizeediting~ImageResizeEditing} and {@link module:image/imageresize/imageresizehandles~ImageResizeHandles} plugins.

```js
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageResizeEditing from '@ckeditor/ckeditor5-image/src/imageresize/imageresizeediting';
import ImageResizeHandles from '@ckeditor/ckeditor5-image/src/imageresize/imageresizehandles';

ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ Image, ImageResizeEditing, ImageResizeHandles, ... ],
...
} )
.then( ... )
.catch( ... );
```

Both ways enable resize handles by default.

#### Using the dropdown

In this case, the user is able to choose from a set of predefined options. These options can be displayed in the image toolbar in form of a dropdown.
Expand Down Expand Up @@ -263,7 +298,7 @@ const imageConfiguration = {
}
```

{@snippet features/image-resizeuidropdown}
{@snippet features/image-resize-buttons-dropdown}

#### Using standalone buttons

Expand Down Expand Up @@ -299,7 +334,50 @@ const imageConfiguration = {
}
```

{@snippet features/image-resizeui}
{@snippet features/image-resize-buttons}

### Disabling image resize handles

If, for some reason, you want to configure the editor in such a way that images can be resized only by buttons you can do so by omitting the {@link module:image/imageresize/imageresizehandles~ImageResizeHandles `ImageResizeHandles`} plugin. As a result, plugins setup should look like this: `plugins: [ 'ImageResizeEditing', 'ImageResizeButtons', ... ]` as opposed to `plugins: [ 'ImageResize', ... ]`. It will enable resizing image feature only by means of the chosen UI ([dropdown](#using-the-dropdown) or [standalone buttons](#using-standalone-buttons)) in the image toolbar.

```js
import Image from '@ckeditor/ckeditor5-image/src/image';
import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar';
import ImageResizeEditing from '@ckeditor/ckeditor5-image/src/imageresize/imageresizeedititing';
import ImageResizeButtons from '@ckeditor/ckeditor5-image/src/imageresize/imageresizebuttons';

ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ Image, ImageResizeEditing, ImageResizeButtons, ImageToolbar, ... ],
image: {
resizeOptions: [
{
name: 'imageResize:original',
value: null,
icon: 'original'
},
{
name: 'imageResize:50',
value: '50',
icon: 'medium'
},
{
name: 'imageResize:75',
value: '75',
icon: 'large'
}
],
toolbar: [
// ...,
'imageResize:50',
'imageResize:75',
'imageResize:original',
]
}
} )
.then( ... )
.catch( ... );
```

### Enabling image resizing

Expand Down
11 changes: 6 additions & 5 deletions packages/ckeditor5-image/src/imageresize.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ImageResizeUI from './imageresize/imageresizeui';
import ImageResizeButtons from './imageresize/imageresizebuttons';
import ImageResizeEditing from './imageresize/imageresizeediting';
import ImageResizeHandles from './imageresize/imageresizehandles';

import '../theme/imageresize.css';

Expand All @@ -25,7 +26,7 @@ export default class ImageResize extends Plugin {
* @inheritDoc
*/
static get requires() {
return [ ImageResizeEditing, ImageResizeUI ];
return [ ImageResizeEditing, ImageResizeHandles, ImageResizeButtons ];
}

/**
Expand Down Expand Up @@ -127,10 +128,10 @@ export default class ImageResize extends Plugin {
*
* **Resizing images using individual buttons**
*
* If you want to have separate buttons for {@link module:image/imageresize/imageresizeui~ImageResizeOption each option},
* If you want to have separate buttons for {@link module:image/imageresize/imageresizebuttons~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}**:
* {@link module:image/imageresize/imageresizebuttons~ImageResizeOption `icon` property}**:
*
* ClassicEditor
* .create( editorElement, {
Expand Down Expand Up @@ -196,5 +197,5 @@ export default class ImageResize extends Plugin {
* .then( ... )
* .catch( ... );
*
* @member {Array.<module:image/imageresize/imageresizeui~ImageResizeOption>} module:image/image~ImageConfig#resizeOptions
* @member {Array.<module:image/imageresize/imageresizebuttons~ImageResizeOption>} module:image/image~ImageConfig#resizeOptions
*/
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

/**
* @module image/imageresize/imageresizeui
* @module image/imageresize/imageresizebuttons
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
Expand All @@ -31,13 +31,13 @@ const RESIZE_ICONS = {
};

/**
* The `ImageResizeUI` plugin.
* The `ImageResizeButtons` plugin.
*
* It adds a possibility to resize images using the toolbar dropdown or individual buttons, depending on the plugin configuration.
*
* @extends module:core/plugin~Plugin
*/
export default class ImageResizeUI extends Plugin {
export default class ImageResizeButtons extends Plugin {
/**
* @inheritDoc
*/
Expand All @@ -49,7 +49,7 @@ export default class ImageResizeUI extends Plugin {
* @inheritDoc
*/
static get pluginName() {
return 'ImageResizeUI';
return 'ImageResizeButtons';
}

/**
Expand Down Expand Up @@ -94,7 +94,7 @@ export default class ImageResizeUI extends Plugin {
* 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 {module:image/imageresize/imageresizebuttons~ImageResizeOption} resizeOption A model of resize option.
*/
_registerImageResizeButton( option ) {
const editor = this.editor;
Expand All @@ -112,13 +112,13 @@ export default class ImageResizeUI extends Plugin {
* 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}.
* {@link module:image/imageresize/imageresizebuttons~ImageResizeOption plugin configuration}.
*
* @error imageresizeui-missing-icon
* @param {module:image/imageresize/imageresizeui~ImageResizeOption} option Invalid image resize option.
* @error imageresizebuttons-missing-icon
* @param {module:image/imageresize/imageresizebuttons~ImageResizeOption} option Invalid image resize option.
*/
throw new CKEditorError(
'imageresizeui-missing-icon: ' +
'imageresizebuttons-missing-icon: ' +
'The resize option "' + name + '" misses the "icon" property ' +
'or the property value doesn\'t match any of available icons.',
editor,
Expand Down Expand Up @@ -151,7 +151,7 @@ export default class ImageResizeUI extends Plugin {
* the editor configuration.
*
* @private
* @param {Array.<module:image/imageresize/imageresizeui~ImageResizeOption>} options An array of configured options.
* @param {Array.<module:image/imageresize/imageresizebuttons~ImageResizeOption>} options An array of configured options.
*/
_registerImageResizeDropdown( options ) {
const editor = this.editor;
Expand Down Expand Up @@ -202,7 +202,7 @@ export default class ImageResizeUI extends Plugin {
* A helper function for creating an option label value string.
*
* @private
* @param {module:image/imageresize/imageresizeui~ImageResizeOption} option A resize option object.
* @param {module:image/imageresize/imageresizebuttons~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`).
Expand Down Expand Up @@ -231,7 +231,7 @@ export default class ImageResizeUI extends Plugin {
* A helper function that parses resize options and returns list item definitions ready for use in a dropdown.
*
* @private
* @param {Array.<module:image/imageresize/imageresizeui~ImageResizeOption>} options The resize options.
* @param {Array.<module:image/imageresize/imageresizebuttons~ImageResizeOption>} options The resize options.
* @param {module:image/imageresize/imageresizecommand~ImageResizeCommand} command A resize image command.
* @returns {Iterable.<module:ui/dropdown/utils~ListDropdownItemDefinition>} Dropdown item definitions.
*/
Expand Down Expand Up @@ -274,7 +274,7 @@ function getIsOnButtonCallback( value ) {
/**
* An image resize option used in the {@link module:image/image~ImageConfig#resizeOptions image resize configuration}.
*
* @typedef {Object} module:image/imageresize/imageresizeui~ImageResizeOption
* @typedef {Object} module:image/imageresize/imageresizebuttons~ImageResizeOption
* @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}.
Expand Down
58 changes: 5 additions & 53 deletions packages/ckeditor5-image/src/imageresize/imageresizeediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,17 @@
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import WidgetResize from '@ckeditor/ckeditor5-widget/src/widgetresize';
import ImageResizeCommand from './imageresizecommand';

/**
* The image resize feature.
* The image resize editing feature.
*
* It adds a possibility to resize each image using handles or manually by
* {@link module:image/imageresize/imageresizeui~ImageResizeUI} buttons.
* {@link module:image/imageresize/imageresizebuttons~ImageResizeButtons} buttons.
*
* @extends module:core/plugin~Plugin
*/
export default class ImageResizeEditing extends Plugin {
/**
* @inheritDoc
*/
static get requires() {
return [ WidgetResize ];
}

/**
* @inheritDoc
*/
Expand All @@ -45,55 +37,15 @@ export default class ImageResizeEditing extends Plugin {
this._registerConverters();

editor.commands.add( 'imageResize', command );

editor.editing.downcastDispatcher.on( 'insert:image', ( evt, data, conversionApi ) => {
const widget = conversionApi.mapper.toViewElement( data.item );

const resizer = editor.plugins
.get( WidgetResize )
.attachTo( {
unit: editor.config.get( 'image.resizeUnit' ) || '%',

modelElement: data.item,
viewElement: widget,
editor,

getHandleHost( domWidgetElement ) {
return domWidgetElement.querySelector( 'img' );
},
getResizeHost( domWidgetElement ) {
return domWidgetElement;
},
// TODO consider other positions.
isCentered() {
const imageStyle = data.item.getAttribute( 'imageStyle' );

return !imageStyle || imageStyle == 'full' || imageStyle == 'alignCenter';
},

onCommit( newValue ) {
editor.execute( 'imageResize', { width: newValue } );
}
} );

resizer.on( 'updateSize', () => {
if ( !widget.hasClass( 'image_resized' ) ) {
editor.editing.view.change( writer => {
writer.addClass( 'image_resized', widget );
} );
}
} );

resizer.bind( 'isEnabled' ).to( command );
}, { priority: 'low' } );
}

/**
* @private
*/
_registerSchema() {
this.editor.model.schema.extend( 'image', {
allowAttributes: 'width'
this.editor.model.schema.extend( 'image', { allowAttributes: 'width' } );
this.editor.model.schema.setAttributeProperties( 'width', {
isFormatting: true
} );
}

Expand Down
Loading

0 comments on commit 3396d4e

Please sign in to comment.