[FIX] web_editor: delete behavior before table

Before this commit:

* A delete at the end of an empty block just before a table (unbreakable), nothing happened.

After this commit:

* A delete at the end of an empty block just before an unbreakable block, the empty paragraph should be removed and the selection put at the beginning of the unbreakable block.

task-3186679
task-3252775

closes odoo/odoo#125211

closes odoo/odoo#134327

X-original-commit: 70a03c931438fd549d167deb9ad500f3fc8b6024
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
Signed-off-by: Geelen Sébastien (sge) <sge@odoo.com>
This commit is contained in:
Sébastien Geelen (sge)
2023-09-06 05:53:48 +00:00
parent 8c481c7b8e
commit bfa3090be2
3 changed files with 45 additions and 3 deletions
@@ -24,6 +24,8 @@ import {
boundariesOut,
isEditorTab,
isVisible,
isUnbreakable,
isEmptyBlock,
isWhitespace,
isVisibleTextNode,
} from '../utils/utils.js';
@@ -201,6 +203,16 @@ HTMLElement.prototype.oDeleteForward = function (offset) {
filterFunc,
);
if (firstOutNode) {
// If next sibblings is an unbreadable node, and current node is empty, we
// delete the current node and put the selection at the beginning of the
// next sibbling.
if (nextSibling && isUnbreakable(nextSibling) && isEmptyBlock(this)) {
const restore = prepareUpdate(...boundariesOut(this));
this.remove();
restore();
setSelection(firstOutNode, 0);
return;
}
const [node, offset] = leftPos(firstOutNode);
// If the next node is a <LI> we call directly the htmlElement
// oDeleteBackward : because we don't want the special cases of
@@ -1309,7 +1309,7 @@ export function isUnbreakable(node) {
}
return (
isUnremovable(node) || // An unremovable node is always unbreakable.
['THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'SECTION', 'DIV'].includes(node.tagName) ||
['TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'SECTION', 'DIV'].includes(node.tagName) ||
node.hasAttribute('t') ||
(node.nodeType === Node.ELEMENT_NODE &&
(node.nodeName === 'T' ||
@@ -289,8 +289,8 @@ describe('Editor', () => {
`<div class="oe_unbreakable">abc</div></div></div></div>`,
stepFunction: deleteForward,
contentAfter: `<div class="oe_unbreakable"><div class="oe_unbreakable">` +
`<div class="oe_unbreakable"><div class="oe_unbreakable">[]<br></div>` +
`<div class="oe_unbreakable">abc</div></div></div></div>`,
`<div class="oe_unbreakable">` +
`<div class="oe_unbreakable">[]abc</div></div></div></div>`,
});
});
it('should remove empty unbreakable', async () => {
@@ -1899,6 +1899,36 @@ X[]
`</div>`,
});
});
it('should not merge p with an unbreakable.', async () => {
await testEditor(BasicEditor, {
contentBefore: `<p>ab[]</p><table><tbody><tr><td>cd</td></tr></tbody></table>`,
stepFunction: deleteForward,
contentAfter: `<p>ab[]</p><table><tbody><tr><td>cd</td></tr></tbody></table>`,
});
await testEditor(BasicEditor, {
contentBefore: `<p>ab[]</p><div class="oe_unbreakable">cd</div>`,
stepFunction: deleteForward,
contentAfter: `<p>ab[]</p><div class="oe_unbreakable">cd</div>`,
});
});
it('should delete empty p just before an unbreakable.', async () => {
await testEditor(BasicEditor, {
contentBefore: `<p>[]</p><table><tbody><tr><td>cd</td></tr></tbody></table>`,
stepFunction: deleteForward,
contentAfter: `<table><tbody><tr><td>[]cd</td></tr></tbody></table>`,
});
await testEditor(BasicEditor, {
contentBefore: `<p>[]</p><div class="oe_unbreakable">cd</div>`,
stepFunction: deleteForward,
contentAfter: `<div class="oe_unbreakable">[]cd</div>`,
});
await testEditor(BasicEditor, {
contentBefore: `<p class="oe_unbreakable no-class">[]<br></p><div class="oe_unbreakable class-name">cd</div>`,
stepFunction: deleteForward,
contentAfter: `<div class="oe_unbreakable class-name">[]cd</div>`,
});
});
it('should merge the following inline text node', async () => {
await testEditor(BasicEditor, {
contentBefore: '<p>abc</p>[]def',