diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js index 0ce3b2b266e..a1dc75e0981 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -1811,6 +1811,33 @@ var SnippetsMenu = Widget.extend({ this._checkEditorToolbarVisibilityCallback = this._checkEditorToolbarVisibility.bind(this); $(this.options.wysiwyg.odooEditor.document.body).on('click', this._checkEditorToolbarVisibilityCallback); + // Add tooltips on we-title elements whose text overflows and on all + // elements with available tooltip text. Note that the tooltips of the + // blocks should not be taken into account here because they have + // tooltips with a particular behavior (see _showSnippetTooltip). + this.tooltips = new Tooltip(this.el, { + selector: 'we-title, [title]:not(.oe_snippet)', + placement: 'bottom', + delay: 100, + // Ensure the tooltips have a good position when in iframe. + container: this.el, + // Prevent horizontal scroll when tooltip is displayed. + boundary: this.el.ownerDocument.body, + title: function () { + const el = this; + if (el.tagName !== 'WE-TITLE') { + return el.title; + } + // On Firefox, el.scrollWidth is equal to el.clientWidth when + // overflow: hidden, so we need to update the style before to + // get the right values. + el.style.setProperty('overflow', 'scroll', 'important'); + const tipContent = el.scrollWidth > el.clientWidth ? el.innerHTML : ''; + el.style.removeProperty('overflow'); + return tipContent; + }, + }); + if (this.options.enableTranslation) { // Load the sidebar with the style tab only. await this._loadSnippetsTemplates(); @@ -1948,30 +1975,6 @@ var SnippetsMenu = Widget.extend({ const $autoFocusEls = $('.o_we_snippet_autofocus'); this._activateSnippet($autoFocusEls.length ? $autoFocusEls.first() : false); - // Add tooltips on we-title elements whose text overflows - new Tooltip(this.el, { - selector: 'we-title', - placement: 'bottom', - delay: 100, - // Ensure the tooltips have a good position when in iframe. - container: this.el, - // Prevent horizontal scroll when tooltip is displayed. - boundary: this.el.ownerDocument.body, - title: function () { - const el = this; - if (el.tagName !== 'WE-TITLE') { - return el.title; - } - // On Firefox, el.scrollWidth is equal to el.clientWidth when - // overflow: hidden, so we need to update the style before to - // get the right values. - el.style.setProperty('overflow', 'scroll', 'important'); - const tipContent = el.scrollWidth > el.clientWidth ? el.innerHTML : ''; - el.style.removeProperty('overflow'); - return tipContent; - }, - }); - return Promise.all(defs).then(() => { const $undoButton = this.$('.o_we_external_history_buttons button[data-action="undo"]'); const $redoButton = this.$('.o_we_external_history_buttons button[data-action="redo"]'); @@ -2019,6 +2022,8 @@ var SnippetsMenu = Widget.extend({ core.bus.off('deactivate_snippet', this, this._onDeactivateSnippet); $(document.body).off('click', this._checkEditorToolbarVisibilityCallback); this.el.ownerDocument.body.classList.remove('editor_has_snippets'); + // Dispose BS tooltips. + this.tooltips.dispose(); }, //-------------------------------------------------------------------------- @@ -3310,6 +3315,7 @@ var SnippetsMenu = Widget.extend({ * @param {this.tabs.VALUE} [tab='blocks'] - the tab to select */ _updateRightPanelContent: function ({content, tab, ...options}) { + this._hideActiveTooltip(); this._closeWidgets(); this._currentTab = tab || this.tabs.BLOCKS; @@ -3433,6 +3439,28 @@ var SnippetsMenu = Widget.extend({ forceEmptyTab: true, }); }, + /** + * Hides the active tooltip. + * + * @private + */ + _hideActiveTooltip() { + // The BS documentation says that "Tooltips that use delegation (which + // are created using the selector option) cannot be individually + // destroyed on descendant trigger elements". So we remove the active + // tooltips manually. + // For instance, without this, clicking on "Hide in Desktop" on a + // snippet will leave the tooltip "forever" visible even if the "Hide in + // Desktop" button is gone. + const tooltipClass = 'aria-describedby'; + const tooltippedEl = this.el.querySelector(`[${tooltipClass}^="tooltip"]`); + if (tooltippedEl) { + const tooltipEl = document.getElementById(tooltippedEl.getAttribute(tooltipClass)); + if (tooltipEl) { + Tooltip.getInstance(tooltipEl).hide(); + } + } + }, //-------------------------------------------------------------------------- // Handlers @@ -4200,6 +4228,9 @@ var SnippetsMenu = Widget.extend({ } this._buttonAction = true; let removeLoadingEffect; + // Remove the tooltip now, because the button will be disabled and so, + // the tooltip will not be removable (see BS doc). + this._hideActiveTooltip(); if (addLoadingEffect) { removeLoadingEffect = dom.addButtonLoadingEffect(button); } diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js b/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js index 9787fdf2909..40a5ccb1efa 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js @@ -782,7 +782,6 @@ const ColorPaletteWidget = Widget.extend({ * @param {Event} ev */ _onColorButtonEnter: function (ev) { - ev.stopPropagation(); this.trigger_up('color_hover', Object.assign(this.getSelectedColors(), this._getButtonInfo(ev.currentTarget))); }, /** @@ -792,7 +791,6 @@ const ColorPaletteWidget = Widget.extend({ * @param {Event} ev */ _onColorButtonLeave: function (ev) { - ev.stopPropagation(); this.trigger_up('color_leave', Object.assign(this.getSelectedColors(), { target: ev.target, })); diff --git a/addons/web_editor/static/src/xml/editor.xml b/addons/web_editor/static/src/xml/editor.xml index afda59e56d8..8fd9e9c54d2 100644 --- a/addons/web_editor/static/src/xml/editor.xml +++ b/addons/web_editor/static/src/xml/editor.xml @@ -9,9 +9,8 @@