Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image jumps when resizing in container that has padding #16304

Merged
merged 9 commits into from
May 7, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 29 additions & 5 deletions packages/ckeditor5-widget/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,20 +453,35 @@ function addSelectionHandle( widgetElement: ViewContainerElement, writer: Downca
* Starting from a DOM resize host element (an element that receives dimensions as a result of resizing),
* this helper returns the width of the found ancestor element.
*
* **Note**: This helper searches up to 5 levels of ancestors only.
* * It searches up to 5 levels of ancestors only.
* It will skip search if passed element (or it's parent is contenteditable).
*
* @param domResizeHost Resize host DOM element that receives dimensions as a result of resizing.
* @returns Width of ancestor element in pixels or 0 if no ancestor with a computed width has been found.
*/
export function calculateResizeHostAncestorWidth( domResizeHost: HTMLElement ): number {
const getElementComputedWidth = ( element: HTMLElement ) => {
const { width, paddingLeft, paddingRight } = element.ownerDocument.defaultView!.getComputedStyle( element! );

return parseFloat( width ) - parseFloat( paddingLeft ) - parseFloat( paddingRight );
};

if ( isMaximumResizeHostAncestorElement( domResizeHost ) ) {
return getElementComputedWidth( domResizeHost );
}

const domResizeHostParent = domResizeHost.parentElement;

if ( !domResizeHostParent ) {
return 0;
}

// Need to use computed style as it properly excludes parent's paddings from the returned value.
let parentWidth = parseFloat( domResizeHostParent!.ownerDocument.defaultView!.getComputedStyle( domResizeHostParent! ).width );
let parentWidth = getElementComputedWidth( domResizeHostParent! );

if ( isMaximumResizeHostAncestorElement( domResizeHostParent ) ) {
Copy link
Member

@oleq oleq May 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, in my opinion, is only masking the actual root of the issue in ImageResizeHandles. Check out the current implementation at

and see what the output is for various combinations of editors (decoupled, classic) and images (block, inline).

Long story short, it returns paragraphs for inline images and editing roots for block images (that exist directly in a root). I think this is wrong. According to _getResizeHost() in Resizer class

Resize host is an object that receives dimensions which are the result of resizing.

/**
* Obtains the resize host.
*
* Resize host is an object that receives dimensions which are the result of resizing.
*/
private _getResizeHost(): HTMLElement {
const widgetWrapper = this._domResizerWrapper!.parentElement;
return this._options.getResizeHost( widgetWrapper! );
}

An editing root does not receive dimensions. <figure> does (block image) or <span> (inline image).

return parentWidth;
}

// Sometimes parent width cannot be accessed. If that happens we should go up in the elements tree
// and try to get width from next ancestor.
Expand All @@ -483,14 +498,23 @@ export function calculateResizeHostAncestorWidth( domResizeHost: HTMLElement ):
return 0;
}

parentWidth = parseFloat(
domResizeHostParent!.ownerDocument.defaultView!.getComputedStyle( checkedElement ).width
);
parentWidth = getElementComputedWidth( checkedElement );

if ( isMaximumResizeHostAncestorElement( checkedElement ) ) {
break;
}
}

return parentWidth;
}

/**
* Checks if passed HTML has `contenteditable` attribute.
*/
function isMaximumResizeHostAncestorElement( element: HTMLElement ) {
return element.getAttribute( 'contenteditable' ) === 'true' || element.classList.contains( 'ck-editor__editable' );
}

/**
* Calculates a relative width of a `domResizeHost` compared to its ancestor in percents.
*
Expand Down