diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index 5048df1bf0e..3aa283f28ed 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -384,6 +384,7 @@ export class Wysiwyg extends Component { return savedVideo; }; + const _getContentEditableAreas = this.options.getContentEditableAreas; this.odooEditor = new OdooEditor(this.$editable[0], Object.assign({ _t: _t, toolbar: this.toolbarEl, @@ -396,7 +397,15 @@ export class Wysiwyg extends Component { showEmptyElementHint: this.options.showEmptyElementHint, controlHistoryFromDocument: this.options.controlHistoryFromDocument, initialHistoryId: this._serverLastStepId, - getContentEditableAreas: this.options.getContentEditableAreas, + // TODO other places in this file call this.options.getContentEditableAreas + // without the extension here. It does not seem to be a problem (it + // was like that before o_editor_banner elements were considered + // here), but we might want to review that. + getContentEditableAreas: (...args) => { + const areaEls = _getContentEditableAreas?.(...args) || []; + const bannerEls = this.$editable[0].querySelectorAll('.o_editor_banner > div'); + return [...areaEls, ...bannerEls]; + }, getReadOnlyAreas: this.options.getReadOnlyAreas, getUnremovableElements: this.options.getUnremovableElements, defaultLinkAttributes: this.options.userGeneratedContent ? {rel: 'ugc' } : {}, @@ -2269,7 +2278,7 @@ export class Wysiwyg extends Component { const bannerElement = parseHTML(this.odooEditor.document, `
-
+


@@ -3311,12 +3320,14 @@ export class Wysiwyg extends Component { * @param {Node} node */ _onPostSanitize(node) { - // _fixLinkMutatedElements check to be removed after the new link edge soltion is merged. + // _fixLinkMutatedElements check to be removed after the new link edge + // solution is merged. if (node?.querySelectorAll && this.odooEditor && !this.odooEditor._fixLinkMutatedElements) { - for (const element of node.querySelectorAll('.o_editable, .o_not_editable')) { - const editable = element.classList.contains('o_editable'); - if (element.isContentEditable !== editable) { - element.contentEditable = editable; + // TODO rethink o_editable as a content-editable marker without + // breaking the o_editable behaviors (website, mass_mailing, ...) + for (const element of node.querySelectorAll('.o_not_editable')) { + if (element.isContentEditable !== false) { + element.contentEditable = false; } } } @@ -3552,7 +3563,7 @@ function isClientFirst(clientA, clientB) { } else { return clientA.startTime < clientB.startTime; } -}; +} export function stripHistoryIds(value) { return value && value.replace(/\sdata-last-history-steps="[^"]*?"/, '') || value; diff --git a/addons/web_editor/static/src/xml/commands.xml b/addons/web_editor/static/src/xml/commands.xml index 55f744f6507..591bdf036f7 100644 --- a/addons/web_editor/static/src/xml/commands.xml +++ b/addons/web_editor/static/src/xml/commands.xml @@ -1,5 +1,9 @@ +