Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit ddcb1b3

Browse files
authored
Merge pull request #298 from ckeditor/t/ckeditor5-image/241
Feature: Introduced image widget resizer. Closes #241.
2 parents 13af143 + 195fcfc commit ddcb1b3

27 files changed

+1464
-35
lines changed

docs/_snippets/features/build-image-source.html

Whitespace-only changes.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4+
*/
5+
6+
/* globals window */
7+
8+
import ClassicEditor from '@ckeditor/ckeditor5-build-classic/src/ckeditor';
9+
10+
import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';
11+
12+
ClassicEditor.builtinPlugins.push( ImageResize );
13+
14+
window.ClassicEditor = ClassicEditor;

docs/_snippets/features/image-caption.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud
99

1010
ClassicEditor
1111
.create( document.querySelector( '#snippet-image-caption' ), {
12-
removePlugins: [ 'ImageStyle' ],
12+
removePlugins: [ 'ImageStyle', 'ImageResize' ],
1313
image: {
1414
toolbar: [ 'imageTextAlternative' ]
1515
},
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<div id="snippet-image-resize-px">
2+
<h2>Resize me!</h2>
3+
4+
<figure class="image">
5+
<img src="%BASE_PATH%/assets/img/fields.jpg" alt="Autumn fields">
6+
<figcaption>Autumn fields by Aleksander Nowodziński</figcaption>
7+
</figure>
8+
9+
<h2>Resized image (width: 400px):</h2>
10+
11+
<figure class="image image_resized" style="width:400px;">
12+
<img src="%BASE_PATH%/assets/img/fields.jpg" alt="Autumn fields">
13+
</figure>
14+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4+
*/
5+
6+
/* globals ClassicEditor, console, window, document */
7+
8+
import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config.js';
9+
10+
ClassicEditor
11+
.create( document.querySelector( '#snippet-image-resize-px' ), {
12+
image: {
13+
resizeUnit: 'px'
14+
},
15+
toolbar: {
16+
viewportTopOffset: window.getViewportTopOffsetConfig()
17+
},
18+
cloudServices: CS_CONFIG
19+
} )
20+
.then( editor => {
21+
window.editorResizePX = editor;
22+
} )
23+
.catch( err => {
24+
console.error( err );
25+
} );
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<div id="snippet-image-resize">
2+
<h2>Resize me!</h2>
3+
4+
<figure class="image">
5+
<img src="%BASE_PATH%/assets/img/fields.jpg" alt="Autumn fields">
6+
<figcaption>Autumn fields by Aleksander Nowodziński</figcaption>
7+
</figure>
8+
9+
<h2>Resized image (width: 75%):</h2>
10+
11+
<figure class="image image_resized" style="width:75%;">
12+
<img src="%BASE_PATH%/assets/img/fields.jpg" alt="Autumn fields">
13+
</figure>
14+
</div>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4+
*/
5+
6+
/* globals ClassicEditor, console, window, document */
7+
8+
import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config.js';
9+
10+
ClassicEditor
11+
.create( document.querySelector( '#snippet-image-resize' ), {
12+
toolbar: {
13+
viewportTopOffset: window.getViewportTopOffsetConfig()
14+
},
15+
cloudServices: CS_CONFIG
16+
} )
17+
.then( editor => {
18+
window.editorResize = editor;
19+
} )
20+
.catch( err => {
21+
console.error( err );
22+
} );

docs/_snippets/features/image-style-custom.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud
99

1010
ClassicEditor
1111
.create( document.querySelector( '#snippet-image-style-custom' ), {
12+
removePlugins: [ 'ImageResize' ],
1213
image: {
1314
styles: [
1415
// This option is equal to a situation where no style is applied.

docs/_snippets/features/image-style.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud
99

1010
ClassicEditor
1111
.create( document.querySelector( '#snippet-image-style' ), {
12+
removePlugins: [ 'ImageResize' ],
1213
toolbar: {
1314
viewportTopOffset: window.getViewportTopOffsetConfig()
1415
},

docs/_snippets/features/image-toolbar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud
99

1010
ClassicEditor
1111
.create( document.querySelector( '#snippet-image-toolbar' ), {
12-
removePlugins: [ 'ImageCaption', 'ImageStyle' ],
12+
removePlugins: [ 'ImageCaption', 'ImageStyle', 'ImageResize' ],
1313
image: {
1414
toolbar: [ 'imageTextAlternative' ]
1515
},

docs/_snippets/features/image.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud
99

1010
ClassicEditor
1111
.create( document.querySelector( '#snippet-image' ), {
12-
removePlugins: [ 'ImageToolbar', 'ImageCaption', 'ImageStyle' ],
12+
removePlugins: [ 'ImageToolbar', 'ImageCaption', 'ImageStyle', 'ImageResize' ],
1313
toolbar: {
1414
viewportTopOffset: window.getViewportTopOffsetConfig()
1515
},

docs/features/image.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ title: Images
33
category: features
44
---
55

6-
{@snippet build-classic-source}
6+
{@snippet features/build-image-source}
77

88
The [`@ckeditor/ckeditor5-image`](https://www.npmjs.com/package/@ckeditor/ckeditor5-image) package contains multiple plugins that implement various image-related features:
99

@@ -13,9 +13,12 @@ The [`@ckeditor/ckeditor5-image`](https://www.npmjs.com/package/@ckeditor/ckedit
1313
* {@link module:image/imagestyle~ImageStyle} adds support for image styles.
1414
* {@link module:image/imagetextalternative~ImageTextAlternative} adds support for adding text alternative.
1515
* {@link module:image/imageupload~ImageUpload} adds support for uploading dropped or pasted images (see: {@link features/image-upload Image upload}).
16+
* {@link module:image/imageresize~ImageResize} adds support for resizing images.
1617

1718
<info-box info>
18-
All features listed above are enabled by default in all builds.
19+
All features listed above expect image resize are enabled by default in all builds.
20+
21+
Check the documentation of each sub-feature to learn more about it.
1922
</info-box>
2023

2124
## Base image support
@@ -175,6 +178,29 @@ See the {@link features/image-upload Image upload} guide.
175178

176179
Responsive images support in CKEditor 5 is brought by the {@link features/easy-image Easy Image} feature without any additional configuration. Learn more how to use the feature in your project in the {@link features/easy-image#responsive-images "Easy Image integration"} guide.
177180

181+
## Resizing images
182+
183+
TODO:
184+
185+
* overview
186+
* markup
187+
* styling concerns
188+
* installation
189+
* note about it not being enabled by default
190+
* a note about followups? a dialog, a toggle predefined sizes (e.g. 40%, 50%, 75%, 100%)
191+
192+
{@snippet features/image-resize}
193+
194+
### Using pixels instead of percentage width
195+
196+
TODO:
197+
198+
* overview
199+
* downsides
200+
* configuration
201+
202+
{@snippet features/image-resize-px}
203+
178204
## Installation
179205

180206
To add image features to your editor, install the [`@ckeditor/ckeditor5-image`](https://www.npmjs.com/package/@ckeditor/ckeditor5-image) package:

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@
1919
},
2020
"devDependencies": {
2121
"@ckeditor/ckeditor5-basic-styles": "^11.1.3",
22+
"@ckeditor/ckeditor5-block-quote": "^11.1.2",
2223
"@ckeditor/ckeditor5-clipboard": "^12.0.1",
2324
"@ckeditor/ckeditor5-editor-classic": "^12.1.3",
24-
"@ckeditor/ckeditor5-enter": "^11.0.4",
25+
"@ckeditor/ckeditor5-enter": "^11.0.4",
26+
"@ckeditor/ckeditor5-easy-image": "^11.0.4",
2527
"@ckeditor/ckeditor5-heading": "^11.0.4",
28+
"@ckeditor/ckeditor5-indent": "^10.0.1",
2629
"@ckeditor/ckeditor5-link": "^11.1.1",
2730
"@ckeditor/ckeditor5-list": "^12.0.4",
2831
"@ckeditor/ckeditor5-paragraph": "^11.0.4",
32+
"@ckeditor/ckeditor5-table": "^13.0.0",
2933
"@ckeditor/ckeditor5-typing": "^12.1.1",
3034
"@ckeditor/ckeditor5-undo": "^11.0.4",
3135
"eslint": "^5.5.0",

src/imageresize.js

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4+
*/
5+
6+
/**
7+
* @module image/imageresize
8+
*/
9+
10+
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
11+
import WidgetResize from '@ckeditor/ckeditor5-widget/src/widgetresize';
12+
import ImageResizeCommand from './imageresize/imageresizecommand';
13+
14+
import '../theme/imageresize.css';
15+
16+
/**
17+
* The image resize plugin.
18+
*
19+
* It adds a possibility to resize each image using handles.
20+
*
21+
* @extends module:core/plugin~Plugin
22+
*/
23+
export default class ImageResize extends Plugin {
24+
/**
25+
* @inheritDoc
26+
*/
27+
static get requires() {
28+
return [ WidgetResize ];
29+
}
30+
31+
/**
32+
* @inheritDoc
33+
*/
34+
static get pluginName() {
35+
return 'ImageResize';
36+
}
37+
38+
/**
39+
* @inheritDoc
40+
*/
41+
init() {
42+
const editor = this.editor;
43+
const command = new ImageResizeCommand( editor );
44+
45+
this._registerSchema();
46+
this._registerConverters();
47+
48+
editor.commands.add( 'imageResize', command );
49+
50+
editor.editing.downcastDispatcher.on( 'insert:image', ( evt, data, conversionApi ) => {
51+
const widget = conversionApi.mapper.toViewElement( data.item );
52+
53+
const resizer = editor.plugins
54+
.get( WidgetResize )
55+
.attachTo( {
56+
unit: editor.config.get( 'image.resizeUnit' ) || '%',
57+
58+
modelElement: data.item,
59+
viewElement: widget,
60+
downcastWriter: conversionApi.writer,
61+
62+
getHandleHost( domWidgetElement ) {
63+
return domWidgetElement.querySelector( 'img' );
64+
},
65+
getResizeHost( domWidgetElement ) {
66+
return domWidgetElement;
67+
},
68+
// TODO consider other positions.
69+
isCentered() {
70+
const imageStyle = data.item.getAttribute( 'imageStyle' );
71+
72+
return !imageStyle || imageStyle == 'full' || imageStyle == 'alignCenter';
73+
},
74+
75+
onCommit( newValue ) {
76+
editor.execute( 'imageResize', { width: newValue } );
77+
}
78+
} );
79+
80+
resizer.on( 'updateSize', () => {
81+
if ( !widget.hasClass( 'image_resized' ) ) {
82+
editor.editing.view.change( writer => {
83+
writer.addClass( 'image_resized', widget );
84+
} );
85+
}
86+
} );
87+
88+
resizer.bind( 'isEnabled' ).to( command );
89+
}, { priority: 'low' } );
90+
}
91+
92+
/**
93+
* @private
94+
*/
95+
_registerSchema() {
96+
this.editor.model.schema.extend( 'image', {
97+
allowAttributes: 'width'
98+
} );
99+
}
100+
101+
/**
102+
* Registers image resize converters.
103+
*
104+
* @private
105+
*/
106+
_registerConverters() {
107+
const editor = this.editor;
108+
109+
// Dedicated converter to propagate image's attribute to the img tag.
110+
editor.conversion.for( 'downcast' ).add( dispatcher =>
111+
dispatcher.on( 'attribute:width:image', ( evt, data, conversionApi ) => {
112+
if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
113+
return;
114+
}
115+
116+
const viewWriter = conversionApi.writer;
117+
const figure = conversionApi.mapper.toViewElement( data.item );
118+
119+
if ( data.attributeNewValue !== null ) {
120+
viewWriter.setStyle( 'width', data.attributeNewValue, figure );
121+
viewWriter.addClass( 'image_resized', figure );
122+
} else {
123+
viewWriter.removeStyle( 'width', figure );
124+
viewWriter.removeClass( 'image_resized', figure );
125+
}
126+
} )
127+
);
128+
129+
editor.conversion.for( 'upcast' )
130+
.attributeToAttribute( {
131+
view: {
132+
name: 'figure',
133+
styles: {
134+
width: /.+/
135+
}
136+
},
137+
model: {
138+
key: 'width',
139+
value: viewElement => viewElement.getStyle( 'width' )
140+
}
141+
} );
142+
}
143+
}
144+
145+
/**
146+
* The available options are `'px'` or `'%'`.
147+
*
148+
* Determines size unit applied to resized image.
149+
*
150+
* ```js
151+
* ClassicEditor
152+
* .create( editorElement, {
153+
* image: {
154+
* resizeUnit: 'px'
155+
* }
156+
* } )
157+
* .then( ... )
158+
* .catch( ... );
159+
* ```
160+
*
161+
* This option is used by the {@link module:image/imageresize~ImageResize} feature.
162+
*
163+
* @default '%'
164+
* @member {String} module:image/image~ImageConfig#resizeUnit
165+
*/

0 commit comments

Comments
 (0)