From 463fd81486324ba7d95c8a2f4c2b663a3acf1bae Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Tue, 29 Sep 2020 13:51:30 +0000 Subject: [PATCH] [FIX] web_tour: shield tips design from external css rules As the tips can be put anywhere in the DOM, external css rules may target them by mistake. This was for instance discovered on the frontend where the boxed layout does something like this: ``` #wrapwrap > * { width: XXX; } ``` which does breaks the tips which would be placed in the #wrapwrap. This commit solves the problem by forcing rules with !important flags. closes odoo/odoo#58874 X-original-commit: 5084ea9b4d24c41a8171f5c9ad92f903f1067705 Signed-off-by: Quentin Smetz (qsm) --- addons/web_tour/static/src/js/tip.js | 42 +++++++++++----------- addons/web_tour/static/src/scss/tip.scss | 45 +++++++++++++----------- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/addons/web_tour/static/src/js/tip.js b/addons/web_tour/static/src/js/tip.js index 3f94b17bde2..c7900ac5dd2 100644 --- a/addons/web_tour/static/src/js/tip.js +++ b/addons/web_tour/static/src/js/tip.js @@ -1,4 +1,4 @@ -odoo.define('web_tour.Tip', function(require) { +odoo.define('web_tour.Tip', function (require) { "use strict"; var config = require('web.config'); @@ -71,7 +71,7 @@ var Tip = Widget.extend({ // to compute its dimensions and reposition it if required. return this.appendTo(document.body); }, - start: function() { + start() { this.$tooltip_overlay = this.$(".o_tooltip_overlay"); this.$tooltip_content = this.$(".o_tooltip_content"); this.init_width = this.$el.innerWidth(); @@ -90,15 +90,15 @@ var Tip = Widget.extend({ height: "100%", }); - _.each(this.info.event_handlers, (function(data) { + _.each(this.info.event_handlers, data => { this.$tooltip_content.on(data.event, data.selector, data.handler); - }).bind(this)); + }); this._bind_anchor_events(); this._updatePosition(true); this.$el.toggleClass('d-none', !!this.info.hidden); - this.$el.css("opacity", 1); + this.el.style.setProperty('opacity', '1', 'important'); core.bus.on("resize", this, _.debounce(function () { if (this.tip_opened) { this._to_bubble_mode(true); @@ -285,9 +285,9 @@ var Tip = Widget.extend({ // Get the correct tip's position depending of the tip's state let $parent = this.$ideal_location; if ($parent.is('html,body') && this.viewPortState !== "in") { - this.$el.css({position: 'fixed'}); + this.el.style.setProperty('position', 'fixed', 'important'); } else { - this.$el.css({position: ''}); + this.el.style.removeProperty('position'); } if (this.viewPortState === 'in') { @@ -296,6 +296,10 @@ var Tip = Widget.extend({ at: appendAt, of: this.$anchor, collision: "none", + using: props => { + this.el.style.setProperty('top', `${props.top}px`, 'important'); + this.el.style.setProperty('left', `${props.left}px`, 'important'); + }, }); } else { const paddingTop = parseInt($parent.css('padding-top')); @@ -309,7 +313,8 @@ var Tip = Widget.extend({ } else { top = topPosition + $parent.innerHeight() - this.$el.innerHeight() * 2; } - this.$el.css({top: top, left: center}); + this.el.style.setProperty('top', `${top}px`, 'important'); + this.el.style.setProperty('left', `${center}px`, 'important'); } // Reverse overlay if direction is right to left @@ -422,7 +427,8 @@ var Tip = Widget.extend({ if (this.$el.parent()[0] !== this.$el[0].ownerDocument.body) { this.$el.detach(); - this.$el.css(offset); + this.el.style.setProperty('top', `${offset.top}px`, 'important'); + this.el.style.setProperty('left', `${offset.left}px`, 'important'); this.$el.appendTo(this.$el[0].ownerDocument.body); } @@ -448,12 +454,10 @@ var Tip = Widget.extend({ : [this.scrollContentWidth, this.scrollContentHeight]; this.$el.toggleClass("inverse", overflow); this.$el.removeClass("o_animated").addClass("active"); - this.$el.css({ - width: contentWidth, - height: contentHeight, - "margin-left": mbLeft, - "margin-top": mbTop, - }); + this.el.style.setProperty('width', `${contentWidth}px`, 'important'); + this.el.style.setProperty('height', `${contentHeight}px`, 'important'); + this.el.style.setProperty('margin-left', `${mbLeft}px`, 'important'); + this.el.style.setProperty('margin-top', `${mbTop}px`, 'important'); this._transitionEndTimer = setTimeout(() => this._onTransitionEnd(), 400); }, @@ -480,11 +484,9 @@ var Tip = Widget.extend({ this.tip_opened = false; this.$el.removeClass("active").addClass("o_animated"); - this.$el.css({ - width: this.init_width, - height: this.init_height, - margin: 0, - }); + this.el.style.setProperty('width', `${this.init_width}px`, 'important'); + this.el.style.setProperty('height', `${this.init_height}px`, 'important'); + this.el.style.setProperty('margin', '0', 'important'); this._transitionEndTimer = setTimeout(() => this._onTransitionEnd(), 400); }, diff --git a/addons/web_tour/static/src/scss/tip.scss b/addons/web_tour/static/src/scss/tip.scss index 1e9a9e34a47..680b76229b6 100644 --- a/addons/web_tour/static/src/scss/tip.scss +++ b/addons/web_tour/static/src/scss/tip.scss @@ -1,6 +1,6 @@ .o_tooltip_parent { - position: relative!important; + position: relative !important; // Tooltips are placed in the element with z-index 1070 because this // is the only way to position them above everything else. However, for @@ -17,7 +17,7 @@ // home menu (this is especially useful in the website where most tooltips // are placed in the body and need to be placed above elements with z-index // like the navbar). - opacity: 0.999; + opacity: 0.999 !important; } .o_tooltip { @@ -48,35 +48,38 @@ $o-tip-arrow-duration-out: floor($o-tip-duration-out / 2); $o-tip-arrow-delay-out: floor($o-tip-duration-out / 2); - box-sizing: content-box; + box-sizing: content-box !important; /*rtl:begin:ignore*/ - @include o-position-absolute($top: 50%, $left: 50%); + position: absolute !important; + top: 50% !important; + left: 50% !important; /*rtl:end:ignore*/ - opacity: 0; - width: $o-tip-size; - height: $o-tip-size; - border: $o-tip-border-width solid $o-tip-color; - border-radius: 50%; - padding: 0; // ! Cannot be changed ! Javascript rely on this. - z-index: $zindex-tooltip; // See comment on 'o_tooltip_parent' class - background-color: $o-tip-color; - box-shadow: 0 2px 2px 1px rgba(150, 150, 150, 0.3); + opacity: 0 !important; + width: $o-tip-size !important; + height: $o-tip-size !important; + margin: 0 !important; + border: $o-tip-border-width solid $o-tip-color !important; + border-radius: 50% !important; + padding: 0 !important; // ! Cannot be changed ! Javascript rely on this. + z-index: $zindex-tooltip !important; // See comment on 'o_tooltip_parent' class + background-color: $o-tip-color !important; + box-shadow: 0 2px 2px 1px rgba(150, 150, 150, 0.3) !important; transition: width $o-tip-size-duration-out ease $o-tip-size-delay-out, height $o-tip-size-duration-out ease $o-tip-size-delay-out, margin $o-tip-size-duration-out ease $o-tip-size-delay-out, - border-radius $o-tip-border-radius-duration-out ease $o-tip-border-radius-delay-out; + border-radius $o-tip-border-radius-duration-out ease $o-tip-border-radius-delay-out !important; &.o_animated { - animation: move-bottom-top 500ms ease-in 0ms infinite alternate; + animation: move-bottom-top 500ms ease-in 0ms infinite alternate !important; &.right, &.left { - animation-name: move-left-right; + animation-name: move-left-right !important; } } &.o_tooltip_fixed { - position: fixed; + position: fixed !important; } &::before { @@ -152,15 +155,15 @@ } &.active { - border-radius: 0; - background-color: white; + border-radius: 0 !important; + background-color: white !important; transition: width $o-tip-size-duration-in ease $o-tip-size-delay-in, height $o-tip-size-duration-in ease $o-tip-size-delay-in, margin $o-tip-size-duration-in ease $o-tip-size-delay-in, border-radius $o-tip-border-radius-duration-in ease $o-tip-border-radius-delay-in, - background-color $o-tip-bg-color-duration-in ease $o-tip-bg-color-delay-in; + background-color $o-tip-bg-color-duration-in ease $o-tip-bg-color-delay-in !important; &::before { transition: all $o-tip-arrow-duration-in ease $o-tip-arrow-delay-in; @@ -251,6 +254,6 @@ @media print { .o_tooltip { - display: none; + display: none !important; } }