[FIX] web_editor: restore overlay position computation

While working in the current state of the website configuration, the
overlay computation was not working anymore in case the scrollbar is
moved out of the wrapwrap. Indeed, in that case, the position was wrong
by the amount of the page scrolling.

While we could include that scrolling value in the equation, this commit
chooses to restore the way it worked before the "website-in-backend"
merge at [1]: making the overlay be naturally positioned according to
the page scrolling wherever the scrollbar is. To do that, the overlay
had to be moved inside the content (the website iframe) which has the
disadvantage of risking the overlay design being broken by a theme. This
solution was chosen as it simplifies the code, and potentially allows
for performance improvements in the future: not forcing a position
recompute after each scroll (the animation should already be smoother /
more performant this way). This will actually be needed for another fix
/ improvement: the background image overlay has to be in the iframe too.

Note: a further commit will move back the scrollbar behavior out of the
`#wrapwrap`, this is thus especially needed.

[1]: https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b

closes odoo/odoo#102785

X-original-commit: 872bb20b3ac08cf82613e15e6634a2e7593ccf7a
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2022-10-09 18:52:49 +02:00
parent d134987f21
commit 2ae4e64341
6 changed files with 29 additions and 31 deletions
@@ -380,16 +380,9 @@ 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();
// The manipulator is supposed to follow the scroll of the content
// naturally without any JS recomputation.
const manipulatorOffset = this.$el.parent().offset();
offset.top -= manipulatorOffset.top;
offset.left -= manipulatorOffset.left;
this.$el.css({
@@ -929,7 +922,7 @@ var SnippetEditor = Widget.extend({
const rowEl = previousDropzoneEl.parentNode;
if (rowEl.classList.contains('o_grid_mode')) {
document.body.removeEventListener('mousemove', self.onDragMove, false);
self.$body[0].removeEventListener('mousemove', self.onDragMove, false);
const fromGridToGrid = currentDropzoneEl.classList.contains('oe_grid_zone');
if (fromGridToGrid) {
// If we went from a grid dropzone to an other grid one.
@@ -1204,7 +1197,7 @@ var SnippetEditor = Widget.extend({
self.dragState.dragHelperEl = dragHelperEl;
self.dragState.backgroundGridEl = backgroundGridEl;
self.onDragMove = self._onDragMove.bind(self);
document.body.addEventListener('mousemove', self.onDragMove, false);
self.$body[0].addEventListener('mousemove', self.onDragMove, false);
}
},
out: function () {
@@ -1220,7 +1213,7 @@ var SnippetEditor = Widget.extend({
if (sameDropzoneAsCurrent) {
if (rowEl.classList.contains('o_grid_mode')) {
// Removing the listener + cleaning.
document.body.removeEventListener('mousemove', self.onDragMove, false);
self.$body[0].removeEventListener('mousemove', self.onDragMove, false);
gridUtils._gridCleanUp(rowEl, self.$target[0]);
self.$target[0].style.removeProperty('z-index');
@@ -1269,7 +1262,7 @@ var SnippetEditor = Widget.extend({
// Case when dropping the column in a grid.
// Removing the event listener.
document.body.removeEventListener('mousemove', this.onDragMove, false);
this.$body[0].removeEventListener('mousemove', this.onDragMove, false);
// Defining the column grid area with its position.
const gridProp = gridUtils._getGridProperties(rowEl);
@@ -1303,7 +1296,7 @@ var SnippetEditor = Widget.extend({
// TODO lot of this is duplicated code of the d&d feature of snippets
if (!this.dropped) {
const { nearest } = this.$body[0].ownerDocument.defaultView.$;
let $el = nearest({x: ui.position.left, y: ui.position.top}, '.oe_drop_zone', {container: document.body}).first();
let $el = nearest({x: ui.position.left, y: ui.position.top}, '.oe_drop_zone', {container: this.$body[0]}).first();
// Some drop zones might have been disabled.
$el = $el.filter(this.$dropZones);
if ($el.length) {
@@ -1569,7 +1562,7 @@ var SnippetEditor = Widget.extend({
const rowEl = columnEl.parentNode;
// Computing the rowEl position.
const rowElTop = rowEl.getBoundingClientRect().top + document.documentElement.scrollTop;
const rowElTop = rowEl.getBoundingClientRect().top;
const rowElLeft = rowEl.getBoundingClientRect().left;
// Getting the column dimensions.
@@ -1809,7 +1802,8 @@ var SnippetsMenu = Widget.extend({
// Prepare snippets editor environment
this.$snippetEditorArea = $('<div/>', {
id: 'oe_manipulators',
}).insertAfter(this.$el);
});
this.$body.prepend(this.$snippetEditorArea);
// Active snippet editor on click in the page
this.$document.on('click.snippets_menu', '*', this._onClick);
@@ -7232,7 +7232,7 @@ registry.BackgroundPosition = SnippetOptionWidget.extend({
_onDragBackgroundStart: function (ev) {
ev.preventDefault();
this.$bgDragger.addClass('o_we_grabbing');
const $document = $(document);
const $document = $(this.$target[0].ownerDocument);
$document.on('mousemove.bgposition', this._onDragBackgroundMove.bind(this));
$document.one('mouseup', () => {
this.$bgDragger.removeClass('o_we_grabbing');
@@ -18,13 +18,6 @@ body.editor_enable.editor_has_snippets {
background-color: rgba(66, 66, 66, 0.4);
}
}
.editor_has_snippets {
> .oe_overlay.ui-draggable {
.o_handles {
display: none;
}
}
}
// Mobile fix for mass mailing
@include media-breakpoint-down(lg) {
@@ -2291,7 +2284,6 @@ body.editor_enable.editor_has_snippets {
&.o_we_background_position_overlay {
background-color: rgba(0,0,0,.7);
pointer-events: auto;
bottom: 0;
.o_we_overlay_content {
@include o-grab-cursor;
@@ -2301,6 +2293,15 @@ body.editor_enable.editor_has_snippets {
}
}
.o_we_overlay_buttons {
.btn-primary {
@include button-variant($o-brand-primary, $o-brand-primary);
}
.btn-secondary {
@include button-variant($o-we-color-danger, $o-we-color-danger);
}
}
.o_overlay_background > * {
display: block !important;
top: 0 !important;
@@ -2314,6 +2315,9 @@ body.editor_enable.editor_has_snippets {
}
}
}
.oe_overlay.ui-draggable-dragging .o_handles {
display: none;
}
.s-resize-important * {
cursor: s-resize !important;
@@ -68,7 +68,7 @@ function selectColorPalette(position = "left") {
function changeColumnSize(position = "right") {
return {
trigger: `.oe_overlay.ui-draggable.o_we_overlay_sticky.oe_active .o_handle.e`,
trigger: `iframe .oe_overlay.ui-draggable.o_we_overlay_sticky.oe_active .o_handle.e`,
content: Markup(_t("<b>Slide</b> this button to change the column size.")),
position: position,
};
@@ -131,7 +131,7 @@ function changePaddingSize(direction) {
position = "bottom";
}
return {
trigger: `.oe_overlay.ui-draggable.o_we_overlay_sticky.oe_active .o_handle.${paddingDirection}`,
trigger: `iframe .oe_overlay.ui-draggable.o_we_overlay_sticky.oe_active .o_handle.${paddingDirection}`,
content: Markup(_.str.sprintf(_t("<b>Slide</b> this button to change the %s padding"), direction)),
consumeEvent: 'mousedown',
position: position,
@@ -15,7 +15,7 @@ wTourUtils.registerWebsitePreviewTour("carousel_content_removal", {
trigger: "iframe .carousel .carousel-item.active .carousel-content",
content: "Select the active carousel item.",
}, {
trigger: ".oe_overlay.oe_active .oe_snippet_remove",
trigger: "iframe .oe_overlay.oe_active .oe_snippet_remove",
content: "Remove the active carousel item.",
},
{
@@ -31,8 +31,8 @@ function clickAndCheck(blockID, expected) {
}, {
content: 'Once the related overlays are enabled/disabled, check that the focus/blur calls have been correct.',
trigger: blockID
? `.oe_overlay.ui-draggable:eq(${blockData.overlayIndex}).oe_active`
: `#oe_manipulators:not(:has(.oe_active))`,
? `iframe .oe_overlay.ui-draggable:eq(${blockData.overlayIndex}).oe_active`
: `iframe #oe_manipulators:not(:has(.oe_active))`,
run: function (actions) {
const result = window.focusBlurSnippetsResult;
window.focusBlurSnippetsResult = [];