-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9173 from ckeditor/i/9166-resizing-small-images
Fix (image): An image should never overflow the widget boundaries while changing its size. Closes #9166. Fix (image): The size label should be displayed above the image if it doesn't fit inside. See #9166. Fix (image): An Image caption placeholder text should not wrap or overflow. Closes #9162. Internal (widget): Renamed `Resizer#_sizeUI` to `Resizer#_sizeView` to better reflect the name of the class. Closes #9162.
- Loading branch information
Showing
5 changed files
with
255 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/** | ||
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
/** | ||
* @module widget/widgetresize/sizeview | ||
*/ | ||
|
||
import View from '@ckeditor/ckeditor5-ui/src/view'; | ||
|
||
/** | ||
* A view displaying the proposed new element size during the resizing. | ||
* | ||
* @protected | ||
* @extends {module:ui/view~View} | ||
*/ | ||
export default class SizeView extends View { | ||
constructor() { | ||
super(); | ||
|
||
/** | ||
* The visibility of the view defined based on the existence of the host proposed dimensions. | ||
* | ||
* @private | ||
* @observable | ||
* @readonly | ||
* @member {Boolean} #_isVisible | ||
*/ | ||
|
||
/** | ||
* The text that will be displayed in the `SizeView` child. | ||
* It can be formatted as the pixel values (e.g. 10x20) or the percentage value (e.g. 10%). | ||
* | ||
* @private | ||
* @observable | ||
* @readonly | ||
* @member {Boolean} #_label | ||
*/ | ||
|
||
/** | ||
* The position of the view defined based on the host size and active handle position. | ||
* | ||
* @private | ||
* @observable | ||
* @readonly | ||
* @member {String} #_viewPosition | ||
*/ | ||
|
||
const bind = this.bindTemplate; | ||
|
||
this.setTemplate( { | ||
tag: 'div', | ||
attributes: { | ||
class: [ | ||
'ck', | ||
'ck-size-view', | ||
bind.to( '_viewPosition', value => value ? `ck-orientation-${ value }` : '' ) | ||
], | ||
style: { | ||
display: bind.if( '_isVisible', 'none', visible => !visible ) | ||
} | ||
}, | ||
children: [ { | ||
text: bind.to( '_label' ) | ||
} ] | ||
} ); | ||
} | ||
|
||
/** | ||
* A method used for binding the `SizeView` instance properties to the `ResizeState` instance observable properties. | ||
* | ||
* @protected | ||
* @param {module:widget/widgetresize~ResizerOptions} options | ||
* An object defining the resizer options, used for setting the proper size label. | ||
* @param {module:widget/widgetresize/resizerstate~ResizeState} resizeState | ||
* The `ResizeState` class instance, used for keeping the `SizeView` state up to date. | ||
*/ | ||
_bindToState( options, resizeState ) { | ||
this.bind( '_isVisible' ).to( resizeState, 'proposedWidth', resizeState, 'proposedHeight', ( width, height ) => | ||
width !== null && height !== null ); | ||
|
||
this.bind( '_label' ).to( | ||
resizeState, 'proposedHandleHostWidth', | ||
resizeState, 'proposedHandleHostHeight', | ||
resizeState, 'proposedWidthPercents', | ||
( width, height, widthPercents ) => { | ||
if ( options.unit === 'px' ) { | ||
return `${ width }×${ height }`; | ||
} else { | ||
return `${ widthPercents }%`; | ||
} | ||
} | ||
); | ||
|
||
this.bind( '_viewPosition' ).to( | ||
resizeState, 'activeHandlePosition', | ||
resizeState, 'proposedHandleHostWidth', | ||
resizeState, 'proposedHandleHostHeight', | ||
// If the widget is too small to contain the size label, display the label above. | ||
( position, width, height ) => width < 50 || height < 50 ? 'above-center' : position | ||
); | ||
} | ||
|
||
/** | ||
* A method used for cleaning up. It removes the bindings and hides the view. | ||
* | ||
* @protected | ||
*/ | ||
_dismiss() { | ||
this.unbind(); | ||
this._isVisible = false; | ||
} | ||
} |
109 changes: 109 additions & 0 deletions
109
packages/ckeditor5-widget/tests/widgetresize/sizeview.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/** | ||
* @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved. | ||
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license | ||
*/ | ||
|
||
import SizeView from '../../src/widgetresize/sizeview'; | ||
import ResizerState from '../../src/widgetresize/resizerstate'; | ||
|
||
describe( 'SizeView', () => { | ||
let sizeView, state; | ||
|
||
beforeEach( () => { | ||
sizeView = new SizeView(); | ||
state = new ResizerState(); | ||
|
||
sizeView._bindToState( {}, state ); | ||
sizeView.render(); | ||
} ); | ||
|
||
describe( 'constructor()', () => { | ||
it( 'sets a proper template structure', () => { | ||
const template = sizeView.template; | ||
|
||
expect( template.tag ).to.equal( 'div' ); | ||
expect( template.attributes.class ).to.have.length( 3 ).and.include( 'ck', 'ck-size-view', '' ); | ||
expect( template.attributes.style[ 0 ] ).to.have.property( 'display' ); | ||
expect( template.children[ 0 ] ).to.have.property( 'text' ); | ||
} ); | ||
} ); | ||
|
||
describe( 'view label', () => { | ||
it( 'should have proper text if the resizing unit is not pixels', () => { | ||
state.update( { | ||
handleHostWidth: 50, | ||
handleHostHeight: 50, | ||
widthPercents: 20 | ||
} ); | ||
|
||
expect( sizeView.element.innerText ).to.equal( '20%' ); | ||
} ); | ||
|
||
it( 'should have proper text if the resizing unit is pixels', () => { | ||
sizeView._dismiss(); | ||
sizeView._bindToState( { unit: 'px' }, state ); | ||
|
||
state.update( { | ||
handleHostWidth: 50, | ||
handleHostHeight: 50, | ||
widthPercents: 20 | ||
} ); | ||
|
||
expect( sizeView.element.innerText ).to.equal( '50×50' ); | ||
} ); | ||
} ); | ||
|
||
describe( 'view visibility', () => { | ||
it( 'should not be visible if the state proposedHeight and proposedWidth are null', () => { | ||
state.update( { | ||
width: null, | ||
height: null | ||
} ); | ||
|
||
expect( sizeView.element.style.display ).to.equal( 'none' ); | ||
} ); | ||
|
||
it( 'should be visible if the state proposedHeight and proposedWidth are not null', () => { | ||
state.update( { | ||
width: 50, | ||
height: 50 | ||
} ); | ||
|
||
expect( sizeView.element.style.display ).to.equal( '' ); | ||
} ); | ||
} ); | ||
|
||
describe( 'view position', () => { | ||
it( 'should have a valid class if the widget width is less than 50px', () => { | ||
state.activeHandlePosition = 'top-right'; | ||
state.update( { | ||
handleHostWidth: 49, | ||
handleHostHeight: 200 | ||
} ); | ||
|
||
expect( sizeView.element.classList.contains( 'ck-orientation-above-center' ) ).to.be.true; | ||
} ); | ||
|
||
it( 'should have a valid class if the widget height is less than 50px', () => { | ||
state.activeHandlePosition = 'top-right'; | ||
state.update( { | ||
handleHostWidth: 200, | ||
handleHostHeight: 49 | ||
} ); | ||
|
||
expect( sizeView.element.classList.contains( 'ck-orientation-above-center' ) ).to.be.true; | ||
} ); | ||
|
||
it( 'should have a valid class if the widget dimensions are greater than 50px/50px', () => { | ||
const position = 'top-right'; | ||
|
||
state.activeHandlePosition = position; | ||
state.update( { | ||
handleHostWidth: 200, | ||
handleHostHeight: 200 | ||
} ); | ||
|
||
expect( sizeView.element.classList.contains( `ck-orientation-${ position }` ) ).to.be.true; | ||
} ); | ||
} ); | ||
} ); |
Oops, something went wrong.