diff --git a/addons/web/static/src/legacy/js/core/smooth_scroll_on_drag.js b/addons/web/static/src/legacy/js/core/smooth_scroll_on_drag.js index 37aae5f1f44..1e9eeb20f6f 100644 --- a/addons/web/static/src/legacy/js/core/smooth_scroll_on_drag.js +++ b/addons/web/static/src/legacy/js/core/smooth_scroll_on_drag.js @@ -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 ). 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); diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js index a324b4be5f3..cf5eb31e0b7 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -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; + }; + } }); }, /**