[FIX] website, *: prevent bottom fixed elements from hiding buttons

*: web, website_livechat, website_sale_comparison

Before this commit, bottom fixed elements (e.g. the livechat button)
hid the buttons to go to the next step in website sale when these
buttons are located at the bottom of the page, on some screen sizes.

After this commit,

- A bottom fixed element is hidden if this element hides a button at
the bottom of the page.

- Bottom fixed elements are hidden if a modal is open
to prevent it to hide buttons or any important part of the modal.

task-2501400

closes odoo/odoo#74515

X-original-commit: a851db9495fe9d8c1951f218a71e4d4a427cf96d
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
Benjamin Vray
2021-07-30 17:24:48 +00:00
committed by qsm-odoo
parent 0d9e21dfe7
commit da22414233
6 changed files with 94 additions and 1 deletions
@@ -59,6 +59,21 @@ var dom = {
_notify(content, options.callbacks);
}
},
/**
* Detects if 2 elements are colliding.
*
* @param {Element} el1
* @param {Element} el2
* @returns {boolean}
*/
areColliding(el1, el2) {
const el1Rect = el1.getBoundingClientRect();
const el2Rect = el2.getBoundingClientRect();
return el1Rect.bottom > el2Rect.top
&& el1Rect.top < el2Rect.bottom
&& el1Rect.right > el2Rect.left
&& el1Rect.left < el2Rect.right;
},
/**
* Autoresize a $textarea node, by recomputing its height when necessary
* @param {number} [options.min_height] by default, 50.
@@ -1028,6 +1028,60 @@ registry.HeaderHamburgerFull = publicWidget.Widget.extend({
},
});
registry.BottomFixedElement = publicWidget.Widget.extend({
selector: '#wrapwrap',
/**
* @override
*/
async start() {
this.$scrollingElement = $().getScrollingElement();
this.__hideBottomFixedElements = _.debounce(() => this._hideBottomFixedElements(), 500);
this.$scrollingElement.on('scroll.bottom_fixed_element', this.__hideBottomFixedElements);
$(window).on('resize.bottom_fixed_element', this.__hideBottomFixedElements);
return this._super(...arguments);
},
/**
* @override
*/
destroy() {
this._super(...arguments);
this.$scrollingElement.off('.bottom_fixed_element');
$(window).off('.bottom_fixed_element');
$('.o_bottom_fixed_element').removeClass('o_bottom_fixed_element_hidden');
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Hides the elements that are fixed at the bottom of the screen if the
* scroll reaches the bottom of the page and if the elements hide a button.
*
* @private
*/
_hideBottomFixedElements() {
// Note: check in the whole DOM instead of #wrapwrap as unfortunately
// some things are still put outside of the #wrapwrap (like the livechat
// button which is the main reason of this code).
const $bottomFixedElements = $('.o_bottom_fixed_element');
if (!$bottomFixedElements.length) {
return;
}
$bottomFixedElements.removeClass('o_bottom_fixed_element_hidden');
if ((this.$scrollingElement[0].offsetHeight + this.$scrollingElement[0].scrollTop) >= (this.$scrollingElement[0].scrollHeight - 2)) {
const buttonEls = [...this.$('.btn:visible')];
for (const el of $bottomFixedElements) {
if (buttonEls.some(button => dom.areColliding(button, el))) {
el.classList.add('o_bottom_fixed_element_hidden');
}
}
}
},
});
return {
Widget: publicWidget.Widget,
Animation: Animation,
@@ -1422,3 +1422,10 @@ ul.o_checklist > li.o_checked::after {
left: - ($o-checklist-margin-left - $o-checklist-checkmark-width) - 1;
top: 0;
}
// Bottom fixed element (e.g. livechat button)
.modal-open .o_bottom_fixed_element, .o_bottom_fixed_element_hidden {
// Prevent bottom fixed elements from hidding buttons and
// hide them if a modal is open.
display: none !important;
}
@@ -7,6 +7,7 @@ var LivechatButton = require('im_livechat.legacy.im_livechat.im_livechat').Livec
LivechatButton.include({
className: `${LivechatButton.prototype.className} o_bottom_fixed_element`,
/**
* @override
@@ -22,6 +23,19 @@ LivechatButton.include({
}
return this._super();
},
/**
* @override
*/
start() {
// We trigger a resize to launch the event that checks if this element hides
// a button when the page is loaded.
$(window).trigger('resize');
return this._super(...arguments);
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @override
@@ -59,6 +59,9 @@ var ProductComparison = publicWidget.Widget.extend(VariantMixin, {
return $('#comparelist .o_product_panel_content').html();
}
});
// We trigger a resize to launch the event that checks if this element hides
// a button when the page is loaded.
$(window).trigger('resize');
$(document.body).on('click.product_comparaison_widget', '.comparator-popover .o_comparelist_products .o_remove', function (ev) {
ev.preventDefault();
@@ -1,7 +1,7 @@
<templates id="compare_products" xml:space="preserve">
<t t-name="product_comparison_template">
<div class="o_product_feature_panel d-none css_editable_mode_hidden">
<div class="o_product_feature_panel d-none css_editable_mode_hidden o_bottom_fixed_element">
<span class="o_product_panel" id="comparelist">
<span class="o_product_panel_header">
<span class="o_product_icon"><i class="fa fa-exchange" role="img" aria-label="Product" title="Product"></i></span>