From da22414233f8b6ddb4cacb701047e3d7ba97fcd5 Mon Sep 17 00:00:00 2001 From: Benjamin Vray Date: Thu, 15 Apr 2021 09:12:57 +0000 Subject: [PATCH] [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) --- addons/web/static/src/legacy/js/core/dom.js | 15 ++++++ .../src/js/content/snippets.animation.js | 54 +++++++++++++++++++ addons/website/static/src/scss/website.scss | 7 +++ .../static/src/legacy/public_livechat.js | 14 +++++ .../static/src/js/website_sale_comparison.js | 3 ++ .../static/src/xml/comparison.xml | 2 +- 6 files changed, 94 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/legacy/js/core/dom.js b/addons/web/static/src/legacy/js/core/dom.js index 4f1696b43ea..aa5b0ef4a74 100644 --- a/addons/web/static/src/legacy/js/core/dom.js +++ b/addons/web/static/src/legacy/js/core/dom.js @@ -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. diff --git a/addons/website/static/src/js/content/snippets.animation.js b/addons/website/static/src/js/content/snippets.animation.js index 07cc9c3fbb5..5eb0863019d 100644 --- a/addons/website/static/src/js/content/snippets.animation.js +++ b/addons/website/static/src/js/content/snippets.animation.js @@ -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, diff --git a/addons/website/static/src/scss/website.scss b/addons/website/static/src/scss/website.scss index ae4bed0d74a..e23ce3f0ef0 100644 --- a/addons/website/static/src/scss/website.scss +++ b/addons/website/static/src/scss/website.scss @@ -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; +} diff --git a/addons/website_livechat/static/src/legacy/public_livechat.js b/addons/website_livechat/static/src/legacy/public_livechat.js index 6bb1573564d..3cd2cc1d41d 100644 --- a/addons/website_livechat/static/src/legacy/public_livechat.js +++ b/addons/website_livechat/static/src/legacy/public_livechat.js @@ -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 diff --git a/addons/website_sale_comparison/static/src/js/website_sale_comparison.js b/addons/website_sale_comparison/static/src/js/website_sale_comparison.js index 6ab1fe1e25d..f384b43ab80 100644 --- a/addons/website_sale_comparison/static/src/js/website_sale_comparison.js +++ b/addons/website_sale_comparison/static/src/js/website_sale_comparison.js @@ -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(); diff --git a/addons/website_sale_comparison/static/src/xml/comparison.xml b/addons/website_sale_comparison/static/src/xml/comparison.xml index fe887dd3fa8..800cdddb04a 100644 --- a/addons/website_sale_comparison/static/src/xml/comparison.xml +++ b/addons/website_sale_comparison/static/src/xml/comparison.xml @@ -1,7 +1,7 @@ -
+