[FIX] web_editor: fix isolated link
Sometimes the link isolation was broken when the editor rollbacked some browser behavior : the content editable was reset on the all editable. And thus the cursor was able to get out of the isolated link creating issues. task-2957000 X-original-commit: 0a04ef6c2617741b90c151c367c1731ed180ad70 Part-of: odoo/odoo#105066
This commit is contained in:
committed by
David Monjoie
parent
6c0488d9dc
commit
1176e0cab0
@@ -1238,7 +1238,9 @@ export class OdooEditor extends EventTarget {
|
||||
}
|
||||
}
|
||||
if (sideEffect) {
|
||||
this._activateContenteditable();
|
||||
if (!this._fixLinkMutatedElements) {
|
||||
this._activateContenteditable();
|
||||
}
|
||||
this.historySetSelection(step);
|
||||
this.dispatchEvent(new Event('historyRevert'));
|
||||
}
|
||||
@@ -2047,6 +2049,7 @@ export class OdooEditor extends EventTarget {
|
||||
for (const element of this._fixLinkMutatedElements.wasContenteditableNull) {
|
||||
element.removeAttribute('contenteditable');
|
||||
}
|
||||
delete this._fixLinkMutatedElements;
|
||||
}
|
||||
}
|
||||
_activateContenteditable() {
|
||||
@@ -3419,6 +3422,7 @@ export class OdooEditor extends EventTarget {
|
||||
|
||||
clean() {
|
||||
this.observerUnactive();
|
||||
this.resetContenteditableLink();
|
||||
this.cleanForSave();
|
||||
this.observerActive();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { URL_REGEX, URL_REGEX_WITH_INFOS } from '../../src/OdooEditor.js';
|
||||
import {
|
||||
BasicEditor,
|
||||
click,
|
||||
deleteBackward,
|
||||
insertText,
|
||||
insertParagraphBreak,
|
||||
insertLineBreak,
|
||||
@@ -369,6 +370,71 @@ describe('Link', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('isolated link', () => {
|
||||
const clickOnLink = async editor => {
|
||||
const a = editor.editable.querySelector('a');
|
||||
await click(a, { clientX: a.getBoundingClientRect().left + 5 });
|
||||
return a;
|
||||
};
|
||||
it('should restrict editing to link when clicked', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
contentBefore: '<p>a<a href="#/"><span>b</span></a></p>',
|
||||
stepFunction: async editor => {
|
||||
const a = await clickOnLink(editor);
|
||||
window.chai.expect(a.isContentEditable).to.be.equal(true);
|
||||
},
|
||||
contentAfter: '<p>a<a href="#/"><span>b</span></a></p>',
|
||||
});
|
||||
// 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: '<p>a<a href="#/"><span>b</span></a></p>',
|
||||
stepFunction: async editor => {
|
||||
const a = await clickOnLink(editor);
|
||||
window.chai.expect(a.isContentEditable).to.be.equal(false);
|
||||
},
|
||||
contentAfter: '<p>a<a href="#/"><span contenteditable="true">b</span></a></p>',
|
||||
}, {
|
||||
isRootEditable: false,
|
||||
getContentEditableAreas: function (editor) {
|
||||
return editor.editable.querySelectorAll('a span');
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should keep isolated link after a keyboard delete', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
contentBefore: '<p>a<a href="#/">b[]</a>c</p>',
|
||||
stepFunction: async editor => {
|
||||
const a = await clickOnLink(editor);
|
||||
console.log(a.closest('.odoo-editor-editable').outerHTML);
|
||||
await deleteBackward(editor);
|
||||
console.log(a.closest('.odoo-editor-editable').outerHTML);
|
||||
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
|
||||
},
|
||||
contentAfterEdit: '<p>a<a href="#/" contenteditable="true" data-oe-zws-empty-inline="">[]\u200B</a>c</p>',
|
||||
contentAfter: '<p>a[]c</p>',
|
||||
});
|
||||
});
|
||||
it('should keep isolated link after a delete and typing', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
contentBefore: '<p>a<a href="#/">b[]</a>c</p>',
|
||||
stepFunction: async editor => {
|
||||
const a = await clickOnLink(editor);
|
||||
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
|
||||
await deleteBackward(editor);
|
||||
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
|
||||
await insertText(editor, '1');
|
||||
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
|
||||
await insertText(editor, '2');
|
||||
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
|
||||
await insertText(editor, '3');
|
||||
window.chai.expect(a.parentElement.isContentEditable).to.be.equal(false);
|
||||
},
|
||||
contentAfter: '<p>a<a href="#/">123[]</a>c</p>',
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('existing link', () => {
|
||||
it('should parse correctly a span inside a Link', async () => {
|
||||
await testEditor(BasicEditor, {
|
||||
@@ -472,32 +538,6 @@ describe('Link', () => {
|
||||
contentAfter: '<p>a<a href="exist">b</a></p><p>c[]d</p>',
|
||||
});
|
||||
});
|
||||
it('should restrict editing to link when clicked', async () => {
|
||||
const initialContent = '<p>a<a href="#/"><span>b</span></a></p>';
|
||||
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: '<p>a<a href="#/" contenteditable="true"><span>b</span></a></p>',
|
||||
});
|
||||
// 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: '<p>a<a href="#/"><span contenteditable="true">b</span></a></p>',
|
||||
}, {
|
||||
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: '<div><p>[]123</p><p><a href="#">abc</a></p></div>',
|
||||
|
||||
Reference in New Issue
Block a user