From 492aff522a347b392c60bf547a62282ea484e439 Mon Sep 17 00:00:00 2001 From: "Guillaume (gdi)" Date: Wed, 25 Jan 2023 17:13:10 +0000 Subject: [PATCH] [FIX] website, web: handle device visibility on table of content By following these steps: - Drop a block table of content on a page - Disable the visibility of the block in desktop view => A traceback is displayed. This is because for scrollspy to work properly, the elements that it handles must be visible (no display: none). Unfortunately, we put a display none when the block must be invisible for a certain device and the width of the screen is the one of this device. Since it is quite complex to prevent all the cases where the block could become invisible, we patch the scrollspy component of bootstrap so that it has a similar behavior as in version 4.X. (not cause an error if the navigation element is no longer in the DOM or is no longer visible). The error is only visible since [the migration from bootstrap 4 to bootstrap 5] because to add the class, bootstrap 4 did it with the JQuery addClass() function which does not cause an error if the element on which it is called does not exist. Now, bootstrap 5 does the same thing in pure JS with classList.add() on elements that meet the requirements (visible) which causes an error if the element on which it is called is not defined (this is the case before this commit because the TOC was not visible). [the migration from bootstrap 4 to bootstrap 5]: https://github.com/odoo/odoo/commit/c48f57ea2538ad51e00ac27d58f8e191781444f3 task-3116227 opw-3135927 X-original-commit: f2b86dda77133ed9c4f02394693e771758d18bad Part-of: odoo/odoo#113184 --- .../static/src/legacy/js/libs/bootstrap.js | 17 ++++++++ .../tests/tours/snippet_table_of_content.js | 42 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/addons/web/static/src/legacy/js/libs/bootstrap.js b/addons/web/static/src/legacy/js/libs/bootstrap.js index 48cb13c50fa..53027e2fde3 100644 --- a/addons/web/static/src/legacy/js/libs/bootstrap.js +++ b/addons/web/static/src/legacy/js/libs/bootstrap.js @@ -131,3 +131,20 @@ ScrollSpy.prototype._process = function () { this._activate(this._targets[0]); } }; + +/** + * With bootstrap 5, navigation elements must be in the DOM and be visible. + * Since in the website editor, the user can hide the table of content block in + * many different ways, it happens that the navigation element is no longer + * found by bootstrap. We don't want to dispose scrollspy everywhere the block + * could be hidden. So this patch imitates the behavior of bootstrap 4.X by not + * causing an error if the navigation element is not found. + */ +const bootstrapSpyActivateFunction = ScrollSpy.prototype._activate; +ScrollSpy.prototype._activate = function (target) { + const element = document.querySelector(`[href="${target}"]`); + if (!element || $(element).is(':hidden')) { + return; + } + bootstrapSpyActivateFunction.apply(this, arguments); +}; diff --git a/addons/website/static/tests/tours/snippet_table_of_content.js b/addons/website/static/tests/tours/snippet_table_of_content.js index 5bcc42f66ce..e1ef7e43ea0 100644 --- a/addons/website/static/tests/tours/snippet_table_of_content.js +++ b/addons/website/static/tests/tours/snippet_table_of_content.js @@ -38,4 +38,46 @@ wTourUtils.registerWebsitePreviewTour('snippet_table_of_content', { checkTOCNavBar(1, 0), scrollToHeading(3), checkTOCNavBar(1, 1), + wTourUtils.clickOnEdit(), + { + content: "Click on the first TOC's title", + trigger: 'iframe .s_table_of_content:eq(0) h1', + }, + { + content: "Hide the first TOC on mobile", + trigger: '[data-toggle-device-visibility="no_mobile"]', + }, + { + content: "Click on the second TOC's title", + trigger: 'iframe .s_table_of_content:eq(1) h1', + }, + { + content: "Hide the second TOC on desktop", + trigger: '[data-toggle-device-visibility="no_desktop"]', + }, + ...wTourUtils.clickOnSave(), + { + content: "Check that we have the good TOC on desktop", + trigger: 'iframe .s_table_of_content.o_snippet_mobile_invisible', + run: () => { + if ($(document.querySelector('iframe .s_table_of_content.o_snippet_desktop_invisible')) + .is(':visible')) { + console.error('The mobile TOC should not be visible on desktop'); + } + }, + }, + { + content: "Toggle the mobile view", + trigger: '.o_mobile_preview', + }, + { + content: "Check that we have the good TOC on mobile", + trigger: 'iframe .s_table_of_content.o_snippet_desktop_invisible', + run: () => { + if ($(document.querySelector('iframe .s_table_of_content.o_snippet_mobile_invisible')) + .is(':visible')) { + console.error('The desktop TOC should not be visible on mobile'); + } + }, + }, ]);