diff --git a/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js b/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js index c85d4e0aebe..103a49ee9ce 100644 --- a/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js +++ b/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js @@ -1606,7 +1606,7 @@ export class OdooEditor extends EventTarget { this.observerUnactive('_activateContenteditable'); this.editable.setAttribute('contenteditable', this.options.isRootEditable); - for (const node of this.options.getContentEditableAreas()) { + for (const node of this.options.getContentEditableAreas(this)) { if (!node.isContentEditable) { node.setAttribute('contenteditable', true); } @@ -1618,7 +1618,7 @@ export class OdooEditor extends EventTarget { if (this.options.isRootEditable) { this.editable.setAttribute('contenteditable', !this.options.isRootEditable); } - for (const node of this.options.getContentEditableAreas()) { + for (const node of this.options.getContentEditableAreas(this)) { if (node.getAttribute('contenteditable') === 'true') { node.setAttribute('contenteditable', false); } @@ -2771,10 +2771,9 @@ export class OdooEditor extends EventTarget { const link = closestElement(ev.target, 'a'); this.resetContenteditableLink(); if ( - link && + link && link.isContentEditable && !link.querySelector('div') && - !closestElement(ev.target, '.o_not_editable') && - link.getAttribute('contenteditable') !== 'false' + !closestElement(ev.target, '.o_not_editable') ) { this.setContenteditableLink(link); } else { diff --git a/addons/web_editor/static/lib/odoo-editor/test/spec/link.test.js b/addons/web_editor/static/lib/odoo-editor/test/spec/link.test.js index ca7b8958a31..88d0f8fdd49 100644 --- a/addons/web_editor/static/lib/odoo-editor/test/spec/link.test.js +++ b/addons/web_editor/static/lib/odoo-editor/test/spec/link.test.js @@ -1,5 +1,6 @@ import { BasicEditor, + click, insertText, insertParagraphBreak, insertLineBreak, @@ -320,6 +321,32 @@ describe('Link', () => { contentAfter: '

ab

c[]d

', }); }); + it('should restrict editing to link when clicked', async () => { + const initialContent = '

ab

'; + const editFunction = editableLink => async editor => { + const a = editor.editable.querySelector('a'); + await click(a, { clientX: a.getBoundingClientRect().left + 5 }); + window.chai.expect(a.isContentEditable).to.be.equal(editableLink); + }; + await testEditor(BasicEditor, { + contentBefore: initialContent, + stepFunction: editFunction(true), + contentAfter: '

ab

', + }); + // The following is a regression test, checking that the link + // remains non-editable whenever the editable zone is contained by + // the link. + await testEditor(BasicEditor, { + contentBefore: initialContent, + stepFunction: editFunction(false), + contentAfter: '

ab

', + }, { + isRootEditable: false, + getContentEditableAreas: function (editor) { + return editor.editable.querySelectorAll('a span'); + } + }); + }); // it('should select and replace all text and add the next char in bold', async () => { // await testEditor(BasicEditor, { // contentBefore: '

[]123

abc

', diff --git a/addons/web_editor/static/lib/odoo-editor/test/utils.js b/addons/web_editor/static/lib/odoo-editor/test/utils.js index f6119488c36..16006651136 100644 --- a/addons/web_editor/static/lib/odoo-editor/test/utils.js +++ b/addons/web_editor/static/lib/odoo-editor/test/utils.js @@ -267,7 +267,7 @@ export function customErrorMessage(assertLocation, value, expected) { return `[${assertLocation}]\nactual : '${value}'\nexpected: '${expected}'\n\nStackTrace `; } -export async function testEditor(Editor = OdooEditor, spec) { +export async function testEditor(Editor = OdooEditor, spec, options = {}) { const testNode = document.createElement('div'); document.querySelector('#editor-test-container').innerHTML = ''; document.querySelector('#editor-test-container').appendChild(testNode); @@ -278,7 +278,7 @@ export async function testEditor(Editor = OdooEditor, spec) { testNode.innerHTML = spec.contentBefore; const selection = parseTextualSelection(testNode); - const editor = new Editor(testNode, { toSanitize: false }); + const editor = new Editor(testNode, Object.assign({ toSanitize: false }, options)); editor.keyboardType = 'PHYSICAL'; editor.testMode = true; if (selection) {