From a8581ddca659938caed76ee6fe98cd7a9739adf6 Mon Sep 17 00:00:00 2001 From: Antoine Guenet Date: Mon, 13 Feb 2023 08:25:52 +0000 Subject: [PATCH] [FIX] web_editor: fix triple click on block followed by empty block Triple click correction failed whenever the triple-click-selected block was followed by an empty block. The reason is that `getDeepestPosition` prevents the selection from being placed within a line break (`
`) and therefore returns the block itself (`

[]

` will be expressed as `(p, 0)`), so the heuristic to determine if triple click correction in needed in `getDeepRange` would fail as it assumed the `end` node was a leaf where it wasn't. This fixes the issue by applying the heurstic to the first leaf of the `end` node instead, and making the correction for there as well. task-3180922 closes odoo/odoo#112637 X-original-commit: 81653c320a1e431e4b9ae831bf0b8522588368e6 Signed-off-by: David Monjoie (dmo) --- .../js/editor/odoo-editor/src/utils/utils.js | 11 +++--- .../odoo-editor/test/spec/editor.test.js | 34 +++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js index 62dc4064aef..c87c6c51086 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js @@ -763,17 +763,18 @@ export function getDeepRange(editable, { range, sel, splitText, select, correctT } } } - // A selection spanning multiple nodes and ending at position 0 of a - // node, like the one resulting from a triple click, are corrected so - // that it ends at the last position of the previous node instead. - const beforeEnd = end.previousSibling; + // A selection spanning multiple nodes and ending at position 0 of a node, + // like the one resulting from a triple click, is corrected so that it ends + // at the last position of the previous node instead. + const endLeaf = firstLeaf(end); + const beforeEnd = endLeaf.previousSibling; if ( correctTripleClick && !endOffset && (start !== end || startOffset !== endOffset) && (!beforeEnd || (beforeEnd.nodeType === Node.TEXT_NODE && !isVisibleStr(beforeEnd))) ) { - const previous = previousLeaf(end, editable, true); + const previous = previousLeaf(endLeaf, editable, true); if (previous && closestElement(previous).isContentEditable) { [end, endOffset] = [previous, nodeSize(previous)]; } diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js index 1db4573a8b1..427abd453e8 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/test/spec/editor.test.js @@ -1190,6 +1190,11 @@ X[] // JW cAfter: '

[]def

', contentAfter: '

[]

def

', }); + await testEditor(BasicEditor, { + contentBefore: '

[abc

]

def

', + stepFunction: deleteForward, + contentAfter: '

[]


def

', + }); }); it('should delete last character of paragraph, ignoring the selected paragraph break', async () => { await testEditor(BasicEditor, { @@ -2668,6 +2673,11 @@ X[] // JW cAfter: '

[]def

', contentAfter: '

[]

def

', }); + await testEditor(BasicEditor, { + contentBefore: '

[abc

]

def

', + stepFunction: deleteBackward, + contentAfter: '

[]


def

', + }); }); it('should delete last character of paragraph, ignoring the selected paragraph break', async () => { await testEditor(BasicEditor, { @@ -2678,6 +2688,14 @@ X[] stepFunction: deleteBackward, contentAfter: '

ab[]

def

', }); + await testEditor(BasicEditor, { + contentBefore: '

ab[c

]

def

', + // This type of selection (typically done with a triple + // click) is "corrected" before remove so triple clicking + // doesn't remove a paragraph break. + stepFunction: deleteBackward, + contentAfter: '

ab[]


def

', + }); }); it('should delete first character of paragraph, as well as selected paragraph break', async () => { await testEditor(BasicEditor, { @@ -2695,6 +2713,22 @@ X[] stepFunction: deleteBackward, contentAfter: '

ab[]

def

', }); + await testEditor(BasicEditor, { + contentBefore: '

ab[c

]

def

', + // This type of selection (typically done with a triple + // click) is "corrected" before remove so triple clicking + // doesn't remove a paragraph break. + stepFunction: deleteBackward, + contentAfter: '

ab[]


def

', + }); + await testEditor(BasicEditor, { + contentBefore: '

ab[c

]

def

', + // This type of selection (typically done with a triple + // click) is "corrected" before remove so triple clicking + // doesn't remove a paragraph break. + stepFunction: deleteBackward, + contentAfter: '

ab[]


def

', + }); }); it('should delete first character of unbreakable, ignoring selected paragraph break', async () => { await testEditor(BasicEditor, {