[FIX] web_editor: prevent deleteBackspace to move nodes
Before this commit, whenever the element that must be deleted by `deleteBackspace` matches `isMediaElement` or `isNotEditableNode` and the cursor was in the beginning of a `<p>` with inline content, the inline content moved to the parent and the `<p>` was deleted. Which is wrong. Now, whenever the element that must be deleted by `deleteBackspace` matches `isMediaElement` or `isNotEditableNode`, no inline content moves. Task-2781328 closes odoo/odoo#91233 X-original-commit: 34d06958d053b070b1e07541214899649602873a Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
@@ -15,6 +15,7 @@ import {
|
||||
isVisible,
|
||||
isVisibleStr,
|
||||
leftPos,
|
||||
rightPos,
|
||||
moveNodes,
|
||||
nodeSize,
|
||||
prepareUpdate,
|
||||
@@ -22,6 +23,8 @@ import {
|
||||
splitTextNode,
|
||||
isMediaElement,
|
||||
isVisibleEmpty,
|
||||
isNotEditableNode,
|
||||
createDOMPathGenerator,
|
||||
} from '../utils/utils.js';
|
||||
|
||||
Text.prototype.oDeleteBackward = function (offset, alreadyMoved = false) {
|
||||
@@ -65,6 +68,10 @@ Text.prototype.oDeleteBackward = function (offset, alreadyMoved = false) {
|
||||
setSelection(parentNode, firstSplitOffset);
|
||||
};
|
||||
|
||||
const isDeletable = (node) => {
|
||||
return isMediaElement(node) || isNotEditableNode(node);
|
||||
}
|
||||
|
||||
HTMLElement.prototype.oDeleteBackward = function (offset, alreadyMoved = false, offsetLimit) {
|
||||
const contentIsZWS = this.textContent === '\u200B';
|
||||
let moveDest;
|
||||
@@ -74,18 +81,11 @@ HTMLElement.prototype.oDeleteBackward = function (offset, alreadyMoved = false,
|
||||
throw UNREMOVABLE_ROLLBACK_CODE;
|
||||
}
|
||||
if (
|
||||
isMediaElement(leftNode) ||
|
||||
(leftNode.getAttribute &&
|
||||
typeof leftNode.getAttribute('contenteditable') === 'string' &&
|
||||
leftNode.getAttribute('contenteditable').toLowerCase() === 'false')
|
||||
isDeletable(leftNode)
|
||||
) {
|
||||
leftNode.remove();
|
||||
return;
|
||||
}
|
||||
if (leftNode.getAttribute && leftNode.getAttribute('contenteditable') === 'false') {
|
||||
leftNode.remove();
|
||||
return;
|
||||
}
|
||||
if (!isBlock(leftNode) || isVisibleEmpty(leftNode)) {
|
||||
/**
|
||||
* Backspace just after an inline node, convert to backspace at the
|
||||
@@ -162,6 +162,16 @@ HTMLElement.prototype.oDeleteBackward = function (offset, alreadyMoved = false,
|
||||
moveDest = leftPos(this);
|
||||
}
|
||||
|
||||
const domPathGenerator = createDOMPathGenerator(DIRECTIONS.LEFT, {
|
||||
leafOnly: true,
|
||||
stopTraverseFunction: isDeletable,
|
||||
});
|
||||
const domPath = domPathGenerator(this, offset)
|
||||
const leftNode = domPath.next().value;
|
||||
if (leftNode && isDeletable(leftNode)) {
|
||||
const [parent, offset] = rightPos(leftNode);
|
||||
return parent.oDeleteBackward(offset, alreadyMoved);
|
||||
}
|
||||
let node = this.childNodes[offset];
|
||||
const nextSibling = this.nextSibling;
|
||||
let currentNodeIndex = offset;
|
||||
|
||||
@@ -1358,6 +1358,33 @@ X[]
|
||||
contentAfter: `<div>[]def</div>`,
|
||||
});
|
||||
});
|
||||
it('should remove contenteditable="false" at the beggining of a P', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
contentBefore: `<p>abc</p><div contenteditable="false">def</div><p>[]ghi</p>`,
|
||||
stepFunction: async editor => {
|
||||
await deleteBackward(editor);
|
||||
},
|
||||
contentAfter: `<p>abc</p><p>[]ghi</p>`,
|
||||
});
|
||||
});
|
||||
it('should remove a fontawesome', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
contentBefore: `<p>abc</p><span class="fa"></span><p>[]def</p>`,
|
||||
stepFunction: async editor => {
|
||||
await deleteBackward(editor);
|
||||
},
|
||||
contentAfter: `<p>abc</p><p>[]def</p>`,
|
||||
});
|
||||
});
|
||||
it('should remove a media element', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
contentBefore: `<p>abc</p><div class="o_image"></div><p>[]def</p>`,
|
||||
stepFunction: async editor => {
|
||||
await deleteBackward(editor);
|
||||
},
|
||||
contentAfter: `<p>abc</p><p>[]def</p>`,
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('Line breaks', () => {
|
||||
describe('Single', () => {
|
||||
|
||||
Reference in New Issue
Block a user