diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js index ff1c8fd2a11..b6c210d8349 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/OdooEditor.js @@ -307,7 +307,182 @@ export class OdooEditor extends EventTarget { this._pluginCall('sanitizeElement', [editable]); - this._createPowerbox(); + // Create the Powerbox's table picker. + this.powerboxTablePicker = new TablePicker({ + document: this.document, + floating: true, + }); + document.body.appendChild(this.powerboxTablePicker.el); + this.powerboxTablePicker.addEventListener('cell-selected', ev => { + this.execCommand('insertTable', { + rowNumber: ev.detail.rowNumber, + colNumber: ev.detail.colNumber, + }); + }); + // Initialize the Powerbox. + let beforeStepIndex; + this.powerbox = new Powerbox({ + editable: this.editable, + getContextFromParentRect: this.options.getContextFromParentRect, + commandFilters: this.options.powerboxFilters, + onShow: () => { + this.powerboxTablePicker.hide(); + }, + onOpen: () => { + // Undo input '/'. + beforeStepIndex = this._historySteps.length - 2; + }, + beforeCommand: () => { + if (this._isPowerboxOpenOnInput) { + this._historyRevertUntil(beforeStepIndex); + this.historyStep(true); + this._historyStepsStates.set(peek(this._historySteps).id, 'consumed'); + setTimeout(() => { + ensureFocus(this.editable); + getDeepRange(this.editable, { select: true }); + }); + } + }, + afterCommand: () => { + this.historyStep(true); + this._isPowerboxOpenOnInput = false; + }, + categories: [ + { name: this.options._t('Structure'), priority: 70 }, + { name: this.options._t('Format'), priority: 60 }, + { name: this.options._t('Widgets'), priority: 30 }, + ...(this.options.categories || []), + ], + commands: [ + { + category: this.options._t('Structure'), + name: this.options._t('Bulleted list'), + priority: 110, + description: this.options._t('Create a simple bulleted list.'), + fontawesome: 'fa-list-ul', + callback: () => { + this.execCommand('toggleList', 'UL'); + }, + }, + { + category: this.options._t('Structure'), + name: this.options._t('Numbered list'), + priority: 100, + description: this.options._t('Create a list with numbering.'), + fontawesome: 'fa-list-ol', + callback: () => { + this.execCommand('toggleList', 'OL'); + }, + }, + { + category: this.options._t('Structure'), + name: this.options._t('Checklist'), + priority: 90, + description: this.options._t('Track tasks with a checklist.'), + fontawesome: 'fa-check-square-o', + callback: () => { + this.execCommand('toggleList', 'CL'); + }, + }, + { + category: this.options._t('Structure'), + name: this.options._t('Table'), + priority: 80, + description: this.options._t('Insert a table.'), + fontawesome: 'fa-table', + callback: () => { + this.powerboxTablePicker.show(); + }, + }, + { + category: this.options._t('Structure'), + name: this.options._t('Separator'), + priority: 40, + description: this.options._t('Insert an horizontal rule separator.'), + fontawesome: 'fa-minus', + callback: () => { + this.execCommand('insertHorizontalRule'); + }, + }, + { + category: this.options._t('Format'), + name: this.options._t('Heading 1'), + priority: 50, + description: this.options._t('Big section heading.'), + fontawesome: 'fa-header', + callback: () => { + this.execCommand('setTag', 'H1'); + }, + }, + { + category: this.options._t('Format'), + name: this.options._t('Heading 2'), + priority: 40, + description: this.options._t('Medium section heading.'), + fontawesome: 'fa-header', + callback: () => { + this.execCommand('setTag', 'H2'); + }, + }, + { + category: this.options._t('Format'), + name: this.options._t('Heading 3'), + priority: 30, + description: this.options._t('Small section heading.'), + fontawesome: 'fa-header', + callback: () => { + this.execCommand('setTag', 'H3'); + }, + }, + { + category: this.options._t('Format'), + name: this.options._t('Switch direction'), + priority: 20, + description: this.options._t('Switch the text\'s direction.'), + fontawesome: 'fa-exchange', + callback: () => { + this.execCommand('switchDirection'); + }, + }, + { + category: this.options._t('Format'), + name: this.options._t('Text'), + priority: 10, + description: this.options._t('Paragraph block.'), + fontawesome: 'fa-paragraph', + callback: () => { + this.execCommand('setTag', 'P'); + }, + }, + { + category: this.options._t('Widgets'), + name: this.options._t('3 Stars'), + priority: 20, + description: this.options._t('Insert a rating over 3 stars.'), + fontawesome: 'fa-star-o', + callback: () => { + let html = '\u200B'; + html += Array(3).fill().map(() => '').join(''); + html += ''; + this.execCommand('insertHTML', html); + }, + }, + { + category: this.options._t('Widgets'), + name: this.options._t('5 Stars'), + priority: 10, + description: this.options._t('Insert a rating over 5 stars.'), + fontawesome: 'fa-star', + callback: () => { + let html = '\u200B'; + html += Array(5).fill().map(() => '').join(''); + html += ''; + this.execCommand('insertHTML', html); + }, + }, + ...(this.options.commands || []), + ], + }); this.toolbarTablePicker = new TablePicker({ document: this.document }); this.toolbarTablePicker.addEventListener('cell-selected', ev => { @@ -1777,190 +1952,6 @@ export class OdooEditor extends EventTarget { } return -1; } - - // COMMAND BAR - // =========== - - _createPowerbox() { - this.powerboxTablePicker = new TablePicker({ - document: this.document, - floating: true, - }); - - document.body.appendChild(this.powerboxTablePicker.el); - - this.powerboxTablePicker.addEventListener('cell-selected', ev => { - this.execCommand('insertTable', { - rowNumber: ev.detail.rowNumber, - colNumber: ev.detail.colNumber, - }); - }); - - const mainCategories = [ - { name: this.options._t('Structure'), priority: 70 }, - { name: this.options._t('Format'), priority: 60 }, - { name: this.options._t('Widgets'), priority: 30 }, - ]; - const mainCommands = [ - { - category: this.options._t('Structure'), - name: this.options._t('Bulleted list'), - priority: 110, - description: this.options._t('Create a simple bulleted list.'), - fontawesome: 'fa-list-ul', - callback: () => { - this.execCommand('toggleList', 'UL'); - }, - }, - { - category: this.options._t('Structure'), - name: this.options._t('Numbered list'), - priority: 100, - description: this.options._t('Create a list with numbering.'), - fontawesome: 'fa-list-ol', - callback: () => { - this.execCommand('toggleList', 'OL'); - }, - }, - { - category: this.options._t('Structure'), - name: this.options._t('Checklist'), - priority: 90, - description: this.options._t('Track tasks with a checklist.'), - fontawesome: 'fa-check-square-o', - callback: () => { - this.execCommand('toggleList', 'CL'); - }, - }, - { - category: this.options._t('Structure'), - name: this.options._t('Table'), - priority: 80, - description: this.options._t('Insert a table.'), - fontawesome: 'fa-table', - callback: () => { - this.powerboxTablePicker.show(); - }, - }, - { - category: this.options._t('Structure'), - name: this.options._t('Separator'), - priority: 40, - description: this.options._t('Insert an horizontal rule separator.'), - fontawesome: 'fa-minus', - callback: () => { - this.execCommand('insertHorizontalRule'); - }, - }, - { - category: this.options._t('Format'), - name: this.options._t('Heading 1'), - priority: 50, - description: this.options._t('Big section heading.'), - fontawesome: 'fa-header', - callback: () => { - this.execCommand('setTag', 'H1'); - }, - }, - { - category: this.options._t('Format'), - name: this.options._t('Heading 2'), - priority: 40, - description: this.options._t('Medium section heading.'), - fontawesome: 'fa-header', - callback: () => { - this.execCommand('setTag', 'H2'); - }, - }, - { - category: this.options._t('Format'), - name: this.options._t('Heading 3'), - priority: 30, - description: this.options._t('Small section heading.'), - fontawesome: 'fa-header', - callback: () => { - this.execCommand('setTag', 'H3'); - }, - }, - { - category: this.options._t('Format'), - name: this.options._t('Switch direction'), - priority: 20, - description: this.options._t('Switch the text\'s direction.'), - fontawesome: 'fa-exchange', - callback: () => { - this.execCommand('switchDirection'); - }, - }, - { - category: this.options._t('Format'), - name: this.options._t('Text'), - priority: 10, - description: this.options._t('Paragraph block.'), - fontawesome: 'fa-paragraph', - callback: () => { - this.execCommand('setTag', 'P'); - }, - }, - { - category: this.options._t('Widgets'), - name: this.options._t('3 Stars'), - priority: 20, - description: this.options._t('Insert a rating over 3 stars.'), - fontawesome: 'fa-star-o', - callback: () => { - let html = '\u200B'; - html += Array(3).fill().map(() => '').join(''); - html += ''; - this.execCommand('insertHTML', html); - }, - }, - { - category: this.options._t('Widgets'), - name: this.options._t('5 Stars'), - priority: 10, - description: this.options._t('Insert a rating over 5 stars.'), - fontawesome: 'fa-star', - callback: () => { - let html = '\u200B'; - html += Array(5).fill().map(() => '').join(''); - html += ''; - this.execCommand('insertHTML', html); - }, - }, - ]; - let beforeStepIndex; - this.powerbox = new Powerbox({ - editable: this.editable, - getContextFromParentRect: this.options.getContextFromParentRect, - commandFilters: this.options.powerboxFilters, - onShow: () => { - this.powerboxTablePicker.hide(); - }, - onOpen: () => { - // Undo input '/'. - beforeStepIndex = this._historySteps.length - 2; - }, - beforeCommand: () => { - if (this._isPowerboxOpenOnInput) { - this._historyRevertUntil(beforeStepIndex); - this.historyStep(true); - this._historyStepsStates.set(peek(this._historySteps).id, 'consumed'); - setTimeout(() => { - ensureFocus(this.editable); - getDeepRange(this.editable, { select: true }); - }); - } - }, - afterCommand: () => { - this.historyStep(true); - this._isPowerboxOpenOnInput = false; - }, - categories: [...mainCategories, ...(this.options.categories || [])], - commands: [...mainCommands, ...(this.options.commands || [])], - }); - } - _historyRevertUntil (toStepIndex) { const lastStep = this._currentStep; this.historyRevert(lastStep);