diff --git a/addons/website/static/src/js/content/menu.js b/addons/website/static/src/js/content/menu.js index e8147d7e984..aaf6883f76f 100644 --- a/addons/website/static/src/js/content/menu.js +++ b/addons/website/static/src/js/content/menu.js @@ -516,11 +516,24 @@ publicWidget.registry.hoverableDropdown = animations.Animation.extend({ * @override */ start: function () { + if (this.editableMode) { + this._onPageClick = this._onPageClick.bind(this); + this.el.closest('#wrapwrap').addEventListener('click', this._onPageClick, {capture: true}); + } this.$dropdownMenus = this.$el.find('.dropdown-menu'); this.$dropdownToggles = this.$el.find('.dropdown-toggle'); this._dropdownHover(); return this._super.apply(this, arguments); }, + /** + * @override + */ + destroy() { + if (this.editableMode) { + this.el.closest('#wrapwrap').removeEventListener('click', this._onPageClick, {capture: true}); + } + return this._super.apply(this, arguments); + }, //-------------------------------------------------------------------------- // Private @@ -539,6 +552,16 @@ publicWidget.registry.hoverableDropdown = animations.Animation.extend({ this.$dropdownMenus.css('top', ''); } }, + /** + * Hides all opened dropdowns. + * + * @private + */ + _hideDropdowns() { + for (const toggleEl of this.el.querySelectorAll('.dropdown-toggle.show')) { + Dropdown.getOrCreateInstance(toggleEl).hide(); + } + }, //-------------------------------------------------------------------------- // Handlers @@ -549,6 +572,12 @@ publicWidget.registry.hoverableDropdown = animations.Animation.extend({ * @param {Event} ev */ _onMouseEnter: function (ev) { + if (this.editableMode) { + // Do not handle hover if another dropdown is opened. + if (this.el.querySelector('.dropdown-toggle.show')) { + return; + } + } // The user must click on the dropdown if he is on mobile (no way to // hover) or if the dropdown is the (or in the) extra menu ('+'). if (config.device.size_class <= config.device.SIZES.SM || @@ -562,12 +591,29 @@ publicWidget.registry.hoverableDropdown = animations.Animation.extend({ * @param {Event} ev */ _onMouseLeave: function (ev) { + if (this.editableMode) { + // Cancel handling from view mode. + return; + } if (config.device.size_class <= config.device.SIZES.SM || ev.currentTarget.closest('.o_extra_menu_items')) { return; } Dropdown.getOrCreateInstance(ev.currentTarget.querySelector('.dropdown-toggle')).hide(); }, + /** + * Called when the page is clicked anywhere. + * Closes the shown dropdown if the click is outside of it. + * + * @private + * @param {Event} ev + */ + _onPageClick(ev) { + if (ev.target.closest('.dropdown-menu.show')) { + return; + } + this._hideDropdowns(); + }, }); publicWidget.registry.HeaderMainCollapse = publicWidget.Widget.extend({ diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index a29494515d2..5b5aae887a3 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -2232,6 +2232,15 @@ options.registry.HeaderNavbar = options.Class.extend({ // Public //-------------------------------------------------------------------------- + /** + * @override + */ + async start() { + await this._super(...arguments); + // TODO Remove in master. + const signInOptionEl = this.el.querySelector('[data-customize-website-views="portal.user_sign_in"]'); + signInOptionEl.dataset.noPreview = 'true'; + }, /** * @private */ diff --git a/addons/website/views/snippets/snippets.xml b/addons/website/views/snippets/snippets.xml index 340b341c03c..2e6712530d2 100644 --- a/addons/website/views/snippets/snippets.xml +++ b/addons/website/views/snippets/snippets.xml @@ -928,7 +928,7 @@ On Click - +