[FIX] web_editor: toolbar position update on scroll
Before this commit the floating toolbar position was not being updated on scroll events in certain scenarios. The problem resulted from adding the event listener to the incorrect scroll container, which was calculated only once in the Wysiwyg life cycle, on start. The calculated scrollable container could be incorrect due to: - changes in the web client resulting from the swich from read to edit mode taking place after the Wysiwyg was started, - changes in the web client resulting from a window resize (particularly when, in the form view, the chatter switches position from right to bottom and vice-versa), - the editor being mounted inside an iframe and the scroll container being an element in the top document. - the editor being mounter inside an iframe and the scroll container being the iframe's root element. This commit solves the issue by detecting scroll events anywhere in the document (and in the iframe's document when it applies) and updating the toolbar position when the editable is a descendant of the scrolled element. task-3263463 X-original-commit: 5382c995eecfe2fcea39d9456860b48704645c99 Part-of: odoo/odoo#133459
This commit is contained in:
@@ -273,6 +273,7 @@ export class Wysiwyg extends Component {
|
||||
this.colorpickers = {};
|
||||
this._onDocumentMousedown = this._onDocumentMousedown.bind(this);
|
||||
this._onBlur = this._onBlur.bind(this);
|
||||
this._onScroll = this._onScroll.bind(this);
|
||||
this.customizableLinksSelector = 'a'
|
||||
+ ':not([data-bs-toggle="tab"])'
|
||||
+ ':not([data-bs-toggle="collapse"])'
|
||||
@@ -947,6 +948,7 @@ export class Wysiwyg extends Component {
|
||||
for (const timeout of this.tooltipTimeouts) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
document.removeEventListener('scroll', this._onScroll, true);
|
||||
}
|
||||
/**
|
||||
* @override
|
||||
@@ -1919,18 +1921,10 @@ export class Wysiwyg extends Component {
|
||||
}
|
||||
this._updateFaResizeButtons();
|
||||
});
|
||||
// we need the Timeout to be sure the editable content is loaded
|
||||
// before calculating the scrollParent() element.
|
||||
setTimeout(() => {
|
||||
const scrollableContainer = this.$el.scrollParent();
|
||||
if (!options.snippets && scrollableContainer.length) {
|
||||
this.odooEditor.addDomListener(
|
||||
scrollableContainer[0],
|
||||
'scroll',
|
||||
this.odooEditor.updateToolbarPosition.bind(this.odooEditor),
|
||||
);
|
||||
}
|
||||
}, 0);
|
||||
if (!options.snippets) {
|
||||
// Scroll event does not bubble.
|
||||
document.addEventListener('scroll', this._onScroll, true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
@@ -2764,6 +2758,11 @@ export class Wysiwyg extends Component {
|
||||
this.options.onWysiwygBlur && this.options.onWysiwygBlur();
|
||||
}
|
||||
}
|
||||
_onScroll(ev) {
|
||||
if (ev.target.contains(this.$editable[0])) {
|
||||
this.odooEditor.updateToolbarPosition();
|
||||
}
|
||||
}
|
||||
_signalOffline() {
|
||||
if (!this._isOnline) {
|
||||
return;
|
||||
|
||||
@@ -38,6 +38,16 @@ patch(Wysiwyg.prototype, {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
**/
|
||||
destroy() {
|
||||
if (this.options.inIframe) {
|
||||
this.$iframe?.[0].contentDocument.removeEventListener('scroll', this._onScroll, true);
|
||||
}
|
||||
super.destroy();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -180,6 +190,37 @@ patch(Wysiwyg.prototype, {
|
||||
this.$iframe[0].contentWindow.addEventListener('blur', this._onBlur);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When the editable is inside an iframe, we want to update the toolbar
|
||||
* position in 2 scenarios:
|
||||
* 1. scroll event in the top document, if the iframe is a descendant of
|
||||
* the scroll container.
|
||||
* 2. scroll event in the iframe's document.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_onScroll(ev) {
|
||||
if (this.options.inIframe) {
|
||||
const iframeDocument = this.$iframe[0].contentDocument;
|
||||
const scrollInIframe = ev.target === iframeDocument || ev.target.ownerDocument === iframeDocument;
|
||||
if (ev.target.contains(this.$iframe[0]) || scrollInIframe) {
|
||||
this.odooEditor.updateToolbarPosition();
|
||||
}
|
||||
} else {
|
||||
return super._onScroll(...arguments);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_configureToolbar(options) {
|
||||
super._configureToolbar(...arguments);
|
||||
if (this.options.inIframe && !options.snippets) {
|
||||
this.$iframe[0].contentDocument.addEventListener('scroll', this._onScroll, true);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function getWysiwygIframeContent(params) {
|
||||
|
||||
Reference in New Issue
Block a user