From e4d7fbfca85c869d3a04dc517a8ad522cb533a90 Mon Sep 17 00:00:00 2001 From: Younn Olivier Date: Wed, 17 Aug 2022 15:14:53 +0000 Subject: [PATCH] [FIX] web_editor, website: keep the text selection when changing columns It was decided with [1] to keep the text selection, if there was one, when changing a snippet's option. It was not working for the layout_column option: - Drop a text snippet, - Click on the first paragraph (the text is selected), - Change the number of columns, => The text selection is lost. To add some columns on snippets like the s_text_block which has no rows and columns, the layout_column option will first wrap its content into a set of row and column, which will remove the selection. To fix that, the selection is restored after wrapping the snippet's content. The same thing is done when removing all columns from a snippet (and unwrapping its content). Related to https://github.com/odoo/odoo/commit/31cc10b91dc7762e23b4bde9b945be0c4ce3fe3b [1]: https://github.com/odoo/odoo/commit/e8112e2865ca449c4df9cd6147e9e24c4c6dcd41 task-2687506 Part-of: odoo/odoo#98352 --- .../static/src/js/editor/snippets.options.js | 6 ++ .../tours/snippet_editor_panel_options.js | 78 ++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) 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 4ad0f8a2016..a886d3bc5c5 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -31,9 +31,11 @@ const { createDataURL, isGif, } = require('web_editor.image_processing'); +const OdooEditorLib = require('@web_editor/js/editor/odoo-editor/src/OdooEditor'); var qweb = core.qweb; var _t = core._t; +const preserveCursor = OdooEditorLib.preserveCursor; /** * @param {HTMLElement} el @@ -4624,7 +4626,9 @@ registry.layout_column = SnippetOptionWidget.extend({ const previousNbColumns = this.$('> .row').children().length; let $row = this.$('> .row'); if (!$row.length) { + const restoreCursor = preserveCursor(this.$target[0].ownerDocument); $row = this.$target.contents().wrapAll($('
')).parent().parent(); + restoreCursor(); } const nbColumns = parseInt(widgetValue); @@ -4634,7 +4638,9 @@ registry.layout_column = SnippetOptionWidget.extend({ // TODO: make this more generic in activate_snippet event handler. await new Promise(resolve => setTimeout(resolve)); if (nbColumns === 0) { + const restoreCursor = preserveCursor(this.$target[0].ownerDocument); $row.contents().unwrap().contents().unwrap(); + restoreCursor(); this.trigger_up('activate_snippet', {$snippet: this.$target}); } else if (previousNbColumns === 0) { this.trigger_up('activate_snippet', {$snippet: this.$('> .row').children().first()}); diff --git a/addons/website/static/tests/tours/snippet_editor_panel_options.js b/addons/website/static/tests/tours/snippet_editor_panel_options.js index 0045f7e02b5..0551a9cd29e 100644 --- a/addons/website/static/tests/tours/snippet_editor_panel_options.js +++ b/addons/website/static/tests/tours/snippet_editor_panel_options.js @@ -10,7 +10,9 @@ wTourUtils.registerEditionTour('snippet_editor_panel_options', { wTourUtils.dragNDrop({ id: 's_text_image', name: 'Text - Image', -}), { +}), +// Test keeping the text selection when using the width option. +{ content: "Click on the first paragraph.", trigger: 'iframe .s_text_image p', }, { @@ -42,7 +44,9 @@ wTourUtils.dragNDrop({ console.error("The paragraph text selection was lost."); } }, -}, { +}, +// Test the anchor option. +{ content: "Click on the anchor option", trigger: '#oe_snippets .snippet-option-anchor we-button', run() { @@ -73,4 +77,74 @@ wTourUtils.dragNDrop({ console.error('The anchor option does not target the correct snippet.'); } }, +}, +// Test keeping the text selection when adding columns to a snippet with none. +wTourUtils.goBackToBlocks(), +wTourUtils.dragNDrop({ + id: 's_text_block', + name: 'Text', +}), +{ + content: "Click on the first paragraph.", + trigger: 'iframe .s_text_block p', +}, { + content: "The text toolbar should be visible. The paragraph should be selected.", + trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', + run() { + const iframeDocument = document.querySelector('.o_iframe').contentDocument; + const pText = iframeDocument.querySelector('.s_text_block p').textContent; + const selection = iframeDocument.getSelection().toString(); + if (pText !== selection) { + console.error("The paragraph was not correctly selected."); + } + }, +}, { + content: "Click on the columns option.", + trigger: '.snippet-option-layout_column we-select', +}, +{ + content: "Change the number of columns.", + trigger: '.snippet-option-layout_column [data-select-count="3"]', +}, { + content: "The snippet should have the correct number of columns.", + trigger: 'iframe .s_text_block .container > .row', + run() { + if (this.$anchor[0].childElementCount !== 3) { + console.error("The snippet does not have the correct number of columns"); + } + }, +}, { + content: "The text toolbar should still be visible, and the text still selected.", + trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', + run() { + const iframeDocument = document.querySelector('.o_iframe').contentDocument; + const pText = iframeDocument.querySelector('.s_text_block p').textContent; + const selection = iframeDocument.getSelection().toString(); + if (pText !== selection) { + console.error("The paragraph text selection was lost."); + } + }, +}, +// Test keeping the text selection when removing all columns of a snippet. +{ + content: "Click on the columns option.", + trigger: '.snippet-option-layout_column we-select', +}, +{ + content: "Change the number of columns.", + trigger: '.snippet-option-layout_column [data-select-count="0"]', +}, { + content: "The snippet should have the correct number of columns.", + trigger: 'iframe .s_text_block .container:not(:has(.row))', +}, { + content: "The text toolbar should still be visible, and the text still selected.", + trigger: '#oe_snippets .o_we_customize_panel > #o_we_editor_toolbar_container', + run() { + const iframeDocument = document.querySelector('.o_iframe').contentDocument; + const pText = iframeDocument.querySelector('.s_text_block p').textContent; + const selection = iframeDocument.getSelection().toString(); + if (pText !== selection) { + console.error("The paragraph text selection was lost."); + } + }, }]);