diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index e84411cd4bc..410776226d5 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -5399,6 +5399,16 @@ registry.layout_column = SnippetOptionWidget.extend(ColumnLayoutMixin, { // Add the new column and update the grid height. rowEl.appendChild(newColumnEl); gridUtils._resizeGrid(rowEl); + + // Scroll to the new column if more than half of it is hidden (= out of + // the viewport or hidden by an other element). + const newColumnPosition = newColumnEl.getBoundingClientRect(); + const middleX = (newColumnPosition.left + newColumnPosition.right) / 2; + const middleY = (newColumnPosition.top + newColumnPosition.bottom) / 2; + const sameCoordinatesEl = this.ownerDocument.elementFromPoint(middleX, middleY); + if (!sameCoordinatesEl || !newColumnEl.contains(sameCoordinatesEl)) { + newColumnEl.scrollIntoView({behavior: "smooth", block: "center"}); + } this.trigger_up('activate_snippet', {$snippet: $(newColumnEl)}); }, /** diff --git a/addons/website/static/tests/tours/grid_layout.js b/addons/website/static/tests/tours/grid_layout.js index 83dfbe9c7d2..b1f3eb05c8e 100644 --- a/addons/website/static/tests/tours/grid_layout.js +++ b/addons/website/static/tests/tours/grid_layout.js @@ -42,3 +42,37 @@ wTourUtils.registerWebsitePreviewTour('website_replace_grid_image', { }, ...wTourUtils.clickOnSave() ]); + +wTourUtils.registerWebsitePreviewTour("scroll_to_new_grid_item", { + test: true, + url: "/", + edition: true, +}, () => [ + // Drop enough snippets to scroll. + wTourUtils.dragNDrop({id: "s_text_image", name: "Text - Image"}), + wTourUtils.dragNDrop({id: "s_image_text", name: "Image - Text"}), + wTourUtils.dragNDrop({id: "s_image_text", name: "Image - Text"}), + // Toggle the first snippet to grid mode. + wTourUtils.clickOnSnippet({id: "s_text_image", name: "Text - Image"}), + wTourUtils.changeOption("layout_column", 'we-button[data-name="grid_mode"]'), + // Add a new grid item. + wTourUtils.changeOption("layout_column", 'we-button[data-add-element="image"]'), + { + content: "Check that the page scrolled to the new grid item", + trigger: "iframe .s_text_image .o_grid_item:nth-child(3)", + run: function () { + // Leave some time to the page to scroll. + setTimeout(() => { + const newItemPosition = this.$anchor[0].getBoundingClientRect(); + if (newItemPosition.top < 0) { + console.error("The page did not scroll to the new grid item."); + } + document.body.classList.add("o_scrolled_to_grid_item"); + }, 500); + }, + }, { + content: "Make sure the scroll check is done", + trigger: ".o_scrolled_to_grid_item", + isCheck: true, + }, +]); diff --git a/addons/website/tests/test_grid_layout.py b/addons/website/tests/test_grid_layout.py index a032c6dc663..e9b9baea771 100644 --- a/addons/website/tests/test_grid_layout.py +++ b/addons/website/tests/test_grid_layout.py @@ -22,3 +22,6 @@ class TestWebsiteGridLayout(odoo.tests.HttpCase): 'datas': base64.b64encode(req.content), }) self.start_tour(self.env['website'].get_client_action_url('/'), 'website_replace_grid_image', login="admin") + + def test_02_scroll_to_new_grid_item(self): + self.start_tour(self.env['website'].get_client_action_url('/'), 'scroll_to_new_grid_item', login='admin')