[FIX] website, *: restore unconventional dialogs opening + review scroll

*: web_editor

Commit [1] was not coded defensively enough: after it, dialogs not using
a proper bootstrap structure triggered a traceback once they were opened
(this was discovered on odoo.com where such unconventional dialogs do
exist). Bad luck: there was actually a check to allow unconventional
dialogs but it was not done at the right location.

However, fixing this, it was found that more than this was not ok. There
is actually no need to consider the modal-content element at all. Just
using our `hasScrollableContent` method is enough and requires no extra
search in the DOM. This actually also properly computes if the modal
overflows or not while it was not the case before as it did not consider
the modal-dialog element's paddings.

Finally, the whole customized behavior of the modal scrollbar here was
only designed to affect our Odoo modals with the s_popup_no_backdrop
class (see original commit [2]). Indeed, only in that case we want to be
able to switch between body scrolling and modal scrolling while the
modal is opened. In custom cases and other Odoo cases, we want the
standard Boostrap behavior of only being able to interact with the modal
while opened. This commit cleans the code to restore that spirit
(hopefully this does not cause stability issues as [1] was introduced
only a week ago). Sorry for any inconvenience.

[1]: https://github.com/odoo/odoo/commit/8f1dd6d6087ad8252d6e7b22d13aad2c4a3f19c6
[2]: https://github.com/odoo/odoo/commit/e5a5f98819b3a70b3e2564fb91722cab415ceea9

X-original-commit: a2363337355ccf4363249657000cd85bfcb3ab4e
Part-of: odoo/odoo#84139
This commit is contained in:
qsm-odoo
2022-02-08 00:07:22 +00:00
parent e9b3671a7b
commit a0ddaa8931
2 changed files with 32 additions and 17 deletions
@@ -2645,7 +2645,8 @@ var SnippetsMenu = Widget.extend({
async _scrollToSnippet($el, $scrollable) {
// Don't scroll if $el is added to a visible popup that does not fill
// the page (otherwise the page would scroll to a random location).
if ($el.closest('div.modal:not(.s_popup_overflow_page)').length) {
const modalEl = $el[0].closest('.modal');
if (modalEl && !dom.hasScrollableContent(modalEl)) {
return;
}
return dom.scrollTo($el[0], {extraOffset: 50, $scrollable: $scrollable});
@@ -2,6 +2,7 @@ odoo.define('website.s_popup', function (require) {
'use strict';
const config = require('web.config');
const dom = require('web.dom');
const publicWidget = require('web.public.widget');
const utils = require('web.utils');
@@ -122,16 +123,15 @@ publicWidget.registry.popup = PopupWidget;
function _updateScrollbar(ev) {
const context = ev.data;
const modalContent = context._element.querySelector('.modal-content');
const currentOverflow = modalContent.offsetHeight >= window.innerHeight;
if (modalContent && context._isOverflowingWindow !== currentOverflow) {
context._isOverflowingWindow = currentOverflow;
const isOverflowing = dom.hasScrollableContent(context._element);
if (context._isOverflowingWindow !== isOverflowing) {
context._isOverflowingWindow = isOverflowing;
context._checkScrollbar();
context._setScrollbar();
if (context._element.classList.contains('s_popup_overflow_page')) {
$(document.body).addClass('modal-open');
if (isOverflowing) {
document.body.classList.add('modal-open');
} else {
$(document.body).removeClass('modal-open');
document.body.classList.remove('modal-open');
context._resetScrollbar();
}
}
@@ -144,27 +144,41 @@ function _updateScrollbar(ev) {
const _baseShowElement = $.fn.modal.Constructor.prototype._showElement;
$.fn.modal.Constructor.prototype._showElement = function () {
_baseShowElement.apply(this, arguments);
// Update the scrollbar if the content changes or if the window has been
// resized
$(this._element).on('content_changed.update_scrollbar', this, _updateScrollbar);
$(window).on('resize.update_scrollbar', this, _updateScrollbar);
_updateScrollbar({ data: this });
if (this._element.classList.contains('s_popup_no_backdrop')) {
// Update the scrollbar if the content changes or if the window has been
// resized. Note this could technically be done for all modals and not
// only the ones with the s_popup_no_backdrop class but that would be
// useless as allowing content scroll while a modal with that class is
// opened is a very specific Odoo behavior.
$(this._element).on('content_changed.update_scrollbar', this, _updateScrollbar);
$(window).on('resize.update_scrollbar', this, _updateScrollbar);
_updateScrollbar({ data: this });
}
};
const _baseHideModal = $.fn.modal.Constructor.prototype._hideModal;
$.fn.modal.Constructor.prototype._hideModal = function () {
_baseHideModal.apply(this, arguments);
// Note: do this in all cases, not only for popup with the
// s_popup_no_backdrop class, as the modal may have lost that class during
// edition before being closed.
this._element.classList.remove('s_popup_overflow_page');
$(this._element).off('content_changed.update_scrollbar');
$(window).off('resize.update_scrollbar');
};
const _baseSetScrollbar = $.fn.modal.Constructor.prototype._setScrollbar;
$.fn.modal.Constructor.prototype._setScrollbar = function () {
if (this._element.classList.contains('s_popup_no_backdrop') && !this._isOverflowingWindow) {
this._element.classList.remove('s_popup_overflow_page');
return;
if (this._element.classList.contains('s_popup_no_backdrop')) {
this._element.classList.toggle('s_popup_overflow_page', !!this._isOverflowingWindow);
if (!this._isOverflowingWindow) {
return;
}
}
this._element.classList.add('s_popup_overflow_page');
return _baseSetScrollbar.apply(this, arguments);
};