diff --git a/addons/web_editor/static/lib/odoo-editor/src/commands/deleteBackward.js b/addons/web_editor/static/lib/odoo-editor/src/commands/deleteBackward.js index 0b8a01e2185..a0c24356be0 100644 --- a/addons/web_editor/static/lib/odoo-editor/src/commands/deleteBackward.js +++ b/addons/web_editor/static/lib/odoo-editor/src/commands/deleteBackward.js @@ -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; diff --git a/addons/web_editor/static/lib/odoo-editor/test/spec/editor.test.js b/addons/web_editor/static/lib/odoo-editor/test/spec/editor.test.js index fe799300391..b7ea65210f6 100644 --- a/addons/web_editor/static/lib/odoo-editor/test/spec/editor.test.js +++ b/addons/web_editor/static/lib/odoo-editor/test/spec/editor.test.js @@ -1358,6 +1358,33 @@ X[] contentAfter: `
[]def
`, }); }); + it('should remove contenteditable="false" at the beggining of a P', async () => { + await testEditor(BasicEditor, { + contentBefore: `

abc

def

[]ghi

`, + stepFunction: async editor => { + await deleteBackward(editor); + }, + contentAfter: `

abc

[]ghi

`, + }); + }); + it('should remove a fontawesome', async () => { + await testEditor(BasicEditor, { + contentBefore: `

abc

[]def

`, + stepFunction: async editor => { + await deleteBackward(editor); + }, + contentAfter: `

abc

[]def

`, + }); + }); + it('should remove a media element', async () => { + await testEditor(BasicEditor, { + contentBefore: `

abc

[]def

`, + stepFunction: async editor => { + await deleteBackward(editor); + }, + contentAfter: `

abc

[]def

`, + }); + }); }); describe('Line breaks', () => { describe('Single', () => {