From 1211a6348926ffdc393e19c38ea138799a44a453 Mon Sep 17 00:00:00 2001 From: Nicolas Bayet Date: Mon, 6 Dec 2021 11:15:09 +0000 Subject: [PATCH] [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) --- .../static/lib/odoo-editor/src/OdooEditor.js | 44 ++++++++++--------- .../static/src/js/wysiwyg/wysiwyg.js | 18 +++++--- 2 files changed, 37 insertions(+), 25 deletions(-) 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 b88b95654b9..87486d9f73b 100644 --- a/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js +++ b/addons/web_editor/static/lib/odoo-editor/src/OdooEditor.js @@ -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(); } diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index 862c1b279f9..d2d7247bbc3 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -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