[FIX] web_editor: select and fix button after linktool

When the user create a button in the website builder through the
powerbox command "/button":
- call the editor fix for the link
- select the link

task-2704540

closes odoo/odoo#88010

X-original-commit: 92fcd5e15cf3fec96cdd2565157cd41ffd39a084
Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
Nicolas Bayet
2022-04-05 17:17:30 +02:00
parent e045e76e35
commit 1211a63489
2 changed files with 37 additions and 25 deletions
@@ -1227,6 +1227,27 @@ export class OdooEditor extends EventTarget {
}
}
setContenteditableLink(link) {
const editableChildren = link.querySelectorAll('[contenteditable=true]');
this._stopContenteditable();
this._fixLinkMutatedElements = {
wasContenteditableTrue: [...editableChildren],
wasContenteditableFalse: [],
wasContenteditableNull: [],
};
const contentEditableAttribute = link.getAttribute('contenteditable');
if (contentEditableAttribute === 'true') {
this._fixLinkMutatedElements.wasContenteditableTrue.push(link);
} else if (contentEditableAttribute === 'false') {
this._fixLinkMutatedElements.wasContenteditableFalse.push(link);
} else {
this._fixLinkMutatedElements.wasContenteditableNull.push(link);
}
[...editableChildren, link].forEach(node => node.setAttribute('contenteditable', true));
}
/**
* Same as @see _applyCommand, except that also simulates all the
* contenteditable behaviors we let happen, e.g. the backspace handling
@@ -1567,7 +1588,7 @@ export class OdooEditor extends EventTarget {
}
}
}
_resetContenteditableLinks() {
resetContenteditableLink() {
if (this._fixLinkMutatedElements) {
for (const element of this._fixLinkMutatedElements.wasContenteditableTrue) {
element.setAttribute('contenteditable', 'true');
@@ -2747,31 +2768,14 @@ export class OdooEditor extends EventTarget {
// except the link. Then when cliking outside the link, reset the
// editable zones.
const link = closestElement(ev.target, 'a');
this._resetContenteditableLinks();
this.resetContenteditableLink();
if (
link &&
!link.querySelector('div') &&
!closestElement(ev.target, '.o_not_editable') &&
link.getAttribute('contenteditable') !== 'false'
) {
const editableChildren = link.querySelectorAll('[contenteditable=true]');
this._stopContenteditable();
this._fixLinkMutatedElements = {
wasContenteditableTrue: [...editableChildren],
wasContenteditableFalse: [],
wasContenteditableNull: [],
};
const contentEditableAttribute = link.getAttribute('contenteditable');
if (contentEditableAttribute === 'true') {
this._fixLinkMutatedElements.wasContenteditableTrue.push(link);
} else if (contentEditableAttribute === 'false') {
this._fixLinkMutatedElements.wasContenteditableFalse.push(link);
} else {
this._fixLinkMutatedElements.wasContenteditableNull.push(link);
}
[...editableChildren, link].forEach(node => node.setAttribute('contenteditable', true));
this.setContenteditableLink(link);
} else {
this._activateContenteditable();
}
@@ -29,6 +29,7 @@ const isBlock = OdooEditorLib.isBlock;
const rgbToHex = OdooEditorLib.rgbToHex;
const preserveCursor = OdooEditorLib.preserveCursor;
const closestElement = OdooEditorLib.closestElement;
const setSelection = OdooEditorLib.setSelection;
var id = 0;
const faZoomClassRegex = RegExp('fa-[0-9]x');
@@ -1059,6 +1060,7 @@ const Wysiwyg = Widget.extend({
this.linkTools = undefined;
}
} else {
let link;
const linkDialog = new weWidgets.LinkDialog(this, {
forceNewWindow: this.options.linkForceNewWindow,
wysiwyg: this,
@@ -1081,11 +1083,17 @@ const Wysiwyg = Widget.extend({
}
linkWidget.applyLinkToDom(data);
this.odooEditor.historyStep();
// At this point, the dialog is still open and prevents the
// focus in the editable, even though that is where the
// selection is. This waits so the dialog is destroyed when we
// set the focus.
setTimeout(() => this.odooEditor.document.getSelection().collapseToEnd(), 0);
link = linkWidget.$link[0];
this.odooEditor.setContenteditableLink(linkWidget.$link[0]);
setSelection(link, 0, link, link.childNodes.length, false);
// Focus the link after the dialog element is removed because
// if the dialog element is still in the DOM at the time of
// doing link.focus(), because there is the attribute tabindex
// on the dialog element, the focus cannot occurs.
// Using a microtask to set the focus is hackish and might break
// if another microtask wich focus an elemen in the dom occurs
// at the same time (but this case seems unlikely).
Promise.resolve().then(() => link.focus());
});
linkDialog.on('closed', this, function () {
// If the linkDialog content has been saved