[FIX] website, *: always allow scroll for popup taller than window
*: web_editor Steps to reproduce: - Activate the cookie dialog from the website settings - Remove the backdrop from the cookie dialog - Add some blocks to the cookie dialog in the website editor until the dialog height is bigger than the page height. Result: The cookie dialog is not scrollable, so it's impossible to reach the "I agree" button and close the dialog, leaving the user stuck at the first page. I check if the popup content is higher than the window. If it is, I give priority to the popup scroll over the page one. I had to overwrite the _showElement method to call _setScrollbar after the content rendering, in this way I can get its correct height. I also try to update the scrollbar each time a block in the cookie bar has been changed and each time the window resize. This is optimize, so if the overflow isn't changed from the last time I tried to update the scrollbar no action will be taken. In this way you can always see the whole popup without refreshing the page. Also I have to set 'pointer-events' to none only if the popup is smaller than the page itself (to interact with and scroll the page behind), otherwise the popup won't be scrollable. I did this by adding a class "s_popup_overflow_page" if the popup is higher than the page and I adapted the pointer-events property accordingly. opw-2660786 closes odoo/odoo#83691 X-original-commit: 022a4486a99d855a3c6e2cef326bb3b0c5e66db9 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -2643,6 +2643,11 @@ var SnippetsMenu = Widget.extend({
|
||||
* @return {Promise}
|
||||
*/
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
return dom.scrollTo($el[0], {extraOffset: 50, $scrollable: $scrollable});
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -117,22 +117,63 @@ const PopupWidget = publicWidget.Widget.extend({
|
||||
|
||||
publicWidget.registry.popup = PopupWidget;
|
||||
|
||||
// Try to update the scrollbar based on the current context (modal state)
|
||||
// and only if the modal overflowing has changed
|
||||
|
||||
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;
|
||||
context._checkScrollbar();
|
||||
context._setScrollbar();
|
||||
if (context._element.classList.contains('s_popup_overflow_page')) {
|
||||
$(document.body).addClass('modal-open');
|
||||
} else {
|
||||
$(document.body).removeClass('modal-open');
|
||||
context._resetScrollbar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent bootstrap to prevent scrolling and to add the strange body
|
||||
// padding-right they add if the popup does not use a backdrop (especially
|
||||
// important for default cookie bar).
|
||||
|
||||
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 });
|
||||
};
|
||||
|
||||
const _baseHideModal = $.fn.modal.Constructor.prototype._hideModal;
|
||||
$.fn.modal.Constructor.prototype._hideModal = function () {
|
||||
_baseHideModal.apply(this, arguments);
|
||||
$(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')) {
|
||||
if (this._element.classList.contains('s_popup_no_backdrop') && !this._isOverflowingWindow) {
|
||||
this._element.classList.remove('s_popup_overflow_page');
|
||||
return;
|
||||
}
|
||||
return _baseSetScrollbar.apply(this, ...arguments);
|
||||
this._element.classList.add('s_popup_overflow_page');
|
||||
return _baseSetScrollbar.apply(this, arguments);
|
||||
};
|
||||
|
||||
const _baseGetScrollbarWidth = $.fn.modal.Constructor.prototype._getScrollbarWidth;
|
||||
$.fn.modal.Constructor.prototype._getScrollbarWidth = function () {
|
||||
if (this._element.classList.contains('s_popup_no_backdrop')) {
|
||||
if (this._element.classList.contains('s_popup_no_backdrop') && !this._isOverflowingWindow) {
|
||||
return 0;
|
||||
}
|
||||
return _baseGetScrollbarWidth.apply(this, ...arguments);
|
||||
return _baseGetScrollbarWidth.apply(this, arguments);
|
||||
};
|
||||
|
||||
return PopupWidget;
|
||||
|
||||
@@ -63,7 +63,12 @@
|
||||
|
||||
// No backdrop
|
||||
.s_popup_no_backdrop {
|
||||
pointer-events: none;
|
||||
// If the popup is taller than the page you should not be able to
|
||||
// interact with the elements behind, otherwise you should (when there
|
||||
// is no backdrop).
|
||||
&:not(.s_popup_overflow_page) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
pointer-events: auto;
|
||||
|
||||
@@ -79,6 +79,12 @@ options.registry.SnippetPopup = options.Class.extend({
|
||||
this.$target.modal('hide');
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
cleanForSave: function () {
|
||||
this.$target.removeClass("s_popup_overflow_page");
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Options
|
||||
|
||||
Reference in New Issue
Block a user