[FIX] web, website: prevent the submenus from overflowing the page

Since [this first commit], the elements that make up the submenu of the
navbar of a website can no longer overflow the page. Depending on
whether the content is too long, the elements are aligned to the left or
to the right. This was done with the public `menuDirection` widget which
looked at the available space on the left and right and depending on the
size of the submenu elements, aligned the submenu in an optimal way. It
has now been decided to get rid of all this widget because Bootstrap
(with Popper) knows how to position dropdowns dynamically. Unfortunately
Bootstrap has limited this dynamic positioning by disabling it on
dropdowns that are in a navbar. So this commit removes the public widget
and replaces it with a bootstrap patch so that dropdowns are dynamically
aligned in navbars too.

Note that if we had not made this patch in master, we would have had to
adapt the public widget to the migration to Bootstrap 5 (see original
commit).

[this first commit]: https://github.com/odoo/odoo/commit/392c91cda3133b921e9aca9a7b1c511231027438

task-2904507

X-original-commit: b6963dc21bad4b012aace16b9ea9264c33a0d618
Part-of: odoo/odoo#115607
This commit is contained in:
Guillaume (gdi)
2023-03-17 19:22:25 +01:00
parent 50219f2322
commit 8689241f86
2 changed files with 10 additions and 80 deletions
+10
View File
@@ -148,3 +148,13 @@ ScrollSpy.prototype._activate = function (target) {
}
bootstrapSpyActivateFunction.apply(this, arguments);
};
/**
* Bootstrap disables dynamic dropdown positioning when it is in a navbar. Here
* we make this patch to activate this dynamic navbar's dropdown positioning
* which is useful to avoid that the elements of the website sub-menus overflow
* the page.
*/
Dropdown.prototype._detectNavbar = function () {
return false;
};
@@ -501,86 +501,6 @@ publicWidget.registry.FadeOutHeader = BaseDisappearingHeader.extend({
},
});
/**
* Note: this works well with the affixMenu... by chance (menuDirection is
* called after alphabetically).
*
* @todo check bootstrap v4: maybe handled automatically now ?
*/
publicWidget.registry.menuDirection = publicWidget.Widget.extend({
selector: 'header .navbar .nav',
disabledInEditableMode: false,
events: {
'show.bs.dropdown': '_onDropdownShow',
},
/**
* @override
*/
start: function () {
this.defaultAlignment = this.$el.is('.ms-auto, .ms-auto ~ *') ? 'right' : 'left';
return this._super.apply(this, arguments);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @param {string} alignment - either 'left' or 'right'
* @param {integer} liOffset
* @param {integer} liWidth
* @param {integer} menuWidth
* @param {integer} pageWidth
* @returns {boolean}
*/
_checkOpening: function (alignment, liOffset, liWidth, menuWidth, pageWidth) {
if (alignment === 'left') {
// Check if ok to open the dropdown to the right (no window overflow)
return (liOffset + menuWidth <= pageWidth);
} else {
// Check if ok to open the dropdown to the left (no window overflow)
return (liOffset + liWidth - menuWidth >= 0);
}
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
*/
_onDropdownShow: function (ev) {
var $li = $(ev.target);
var $menu = $li.children('.dropdown-menu');
var liOffset = $li.offset().left;
var liWidth = $li.outerWidth();
var menuWidth = $menu.outerWidth();
var pageWidth = $('#wrapwrap').outerWidth();
$menu.removeClass('dropdown-menu-start dropdown-menu-end');
var alignment = this.defaultAlignment;
if ($li.nextAll(':visible').length === 0) {
// The dropdown is the last menu item, open to the left
alignment = 'right';
}
// If can't open in the current direction because it would overflow the
// page, change the direction. But if the other direction would do the
// same, change back the direction.
for (var i = 0; i < 2; i++) {
if (!this._checkOpening(alignment, liOffset, liWidth, menuWidth, pageWidth)) {
alignment = (alignment === 'left' ? 'right' : 'left');
}
}
$menu.addClass('dropdown-menu-' + alignment);
},
});
publicWidget.registry.hoverableDropdown = animations.Animation.extend({
selector: 'header.o_hoverable_dropdown',
disabledInEditableMode: false,