[FIX] web, web_editor: adapt drag and drop to iframe snippets
SmoothScrollOnDrag and jquery-ui, the libraries used to handle the drag and drop of the snippets, are using the HTMLElement getBoundingClientRect method on the draggable/droppable elements to get their position, listen to mouseover events and trigger scroll while dragging. With the WebsiteEditorClientAction's iframe, the getBoundingClientRect method of elements inside the iframe was not taking into account a possible offset of the iframe. For example, in the "mobile preview" edition mode, the iframe was reduced in size and centered in the screen. This commit adds this offset to these libraries: - in SmoothScrollOnDrag, when the drag is started, to correctly trigger the scroll inside the iframe. - the insertion zones' getBoundingClientRect (used for the jquery-ui droppable) is patched. - the SnippetEditor.cover method is adapted to correctly display the handles over the snippets. See merge commit for more information. task-2687506
This commit is contained in:
@@ -254,6 +254,14 @@ const SmoothScrollOnDrag = Class.extend(mixins.ParentedMixin, {
|
||||
- this.options.offsetElementsManager.left(),
|
||||
};
|
||||
|
||||
if (this.iframeOffset) {
|
||||
const { x, y } = this.iframeOffset;
|
||||
visibleOffset.left -= x;
|
||||
visibleOffset.top -= y;
|
||||
visibleOffset.bottom += y;
|
||||
visibleOffset.right += x;
|
||||
}
|
||||
|
||||
// If this.$scrollTarget is the html tag, we need to take the scroll position in to account
|
||||
// as offsets positions are calculated relative to the document (thus <html>).
|
||||
if (this.scrollTargetIsDocument) {
|
||||
@@ -361,6 +369,8 @@ const SmoothScrollOnDrag = Class.extend(mixins.ParentedMixin, {
|
||||
*/
|
||||
_onSmoothDragStart(ev, ui, onDragStartCallBack) {
|
||||
this.scrollTargetIsDocument = this.$scrollTarget.is('html');
|
||||
const iframeEl = this.$scrollTarget[0].ownerDocument.defaultView.frameElement;
|
||||
this.iframeOffset = iframeEl && iframeEl.getBoundingClientRect();
|
||||
this.scrollTargetIsParent = this.$scrollTarget.get(0).contains(this.$element.get(0));
|
||||
this._updatePositionOptions(ui);
|
||||
this._startSmoothScroll(ui);
|
||||
|
||||
@@ -368,6 +368,16 @@ var SnippetEditor = Widget.extend({
|
||||
|
||||
// Now cover the element
|
||||
const offset = $target.offset();
|
||||
|
||||
// If the target is in an iframe, we need the iframe offset.
|
||||
const targetWindow = $target[0].ownerDocument.defaultView;
|
||||
const editorWindow = this.$el[0].ownerDocument.defaultView;
|
||||
if (targetWindow.frameElement && targetWindow !== editorWindow) {
|
||||
const { x, y } = targetWindow.frameElement.getBoundingClientRect();
|
||||
offset.left += x;
|
||||
offset.top += y;
|
||||
}
|
||||
|
||||
var manipulatorOffset = this.$el.parent().offset();
|
||||
offset.top -= manipulatorOffset.top;
|
||||
offset.left -= manipulatorOffset.left;
|
||||
@@ -1778,6 +1788,13 @@ var SnippetsMenu = Widget.extend({
|
||||
// Cleaning consecutive zone and up zones placed between floating or
|
||||
// inline elements. We do not like these kind of zones.
|
||||
$zones = this.getEditableArea().find('.oe_drop_zone:not(.oe_vertical)');
|
||||
|
||||
let iframeOffset;
|
||||
const bodyWindow = this.$body[0].ownerDocument.defaultView;
|
||||
if (bodyWindow.frameElement && bodyWindow !== this.ownerDocument.defaultView) {
|
||||
iframeOffset = bodyWindow.frameElement.getBoundingClientRect();
|
||||
}
|
||||
|
||||
$zones.each(function () {
|
||||
var zone = $(this);
|
||||
var prev = zone.prev();
|
||||
@@ -1798,6 +1815,20 @@ var SnippetsMenu = Widget.extend({
|
||||
&& dispPrev.indexOf('inline') >= 0 && dispNext.indexOf('inline') >= 0) {
|
||||
zone.remove();
|
||||
}
|
||||
|
||||
// In the case of the SnippetsMenu being instanciated in the global
|
||||
// document, with its editable content in an iframe, we want to
|
||||
// take the iframe's offset into account to compute the dropzones.
|
||||
if (iframeOffset) {
|
||||
this.oldGetBoundingClientRect = this.getBoundingClientRect;
|
||||
this.getBoundingClientRect = () => {
|
||||
const rect = this.oldGetBoundingClientRect();
|
||||
const { x, y } = iframeOffset;
|
||||
rect.x += x;
|
||||
rect.y += y;
|
||||
return rect;
|
||||
};
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user