From c91f5fdc4798e506a5366086e9be0d263b1eb8b2 Mon Sep 17 00:00:00 2001 From: "Guillaume (gdi)" Date: Mon, 18 Sep 2023 14:48:52 +0200 Subject: [PATCH] [IMP] web_editor: rebuild the text style dropdown This commit improves the text style dropdown by adding new styles with responsive font sizes. This will allow to solve the biggest responsive font-size problem we have right now: users add a cover snippet with a big font-size (it is currently hardcoded as 62px font size in snippets). On mobile, it stays 62 and it's too big. Using displayN classes of bootstrap will allow to solve that problem. Previous commit also changed the way custom font-sizes work, so after this commit, and after snippets are adapted every text will now be responsive. task-1958098 Part-of: odoo/odoo#129791 --- .../js/editor/odoo-editor/src/OdooEditor.js | 34 +++++++---- .../odoo-editor/src/commands/commands.js | 23 ++++++- .../js/editor/odoo-editor/src/utils/utils.js | 19 ++++-- addons/web_editor/static/src/xml/editor.xml | 60 ++++++++++++------- 4 files changed, 94 insertions(+), 42 deletions(-) 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 0d06cd5739f..65a663dc700 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 @@ -2023,7 +2023,9 @@ export class OdooEditor extends EventTarget { if (!this.isSelectionInEditable()) { this.historyResetLatestComputedSelection(true); } - this.execCommand(buttonEl.dataset.call, buttonEl.dataset.arg1); + const arg1 = buttonEl.dataset.arg1; + const args = arg1 && arg1.split(",") || []; + this.execCommand(buttonEl.dataset.call, ...args); ev.preventDefault(); this._updateToolbar(); @@ -3113,16 +3115,22 @@ export class OdooEditor extends EventTarget { const listUIClasses = {UL: 'fa-list-ul', OL: 'fa-list-ol', CL: 'fa-tasks'}; const block = closestBlock(sel.anchorNode); let activeLabel = undefined; - for (const [style, tag, isList] of [ - ['paragraph', 'P', false], - ['pre', 'PRE', false], - ['heading1', 'H1', false], - ['heading2', 'H2', false], - ['heading3', 'H3', false], - ['heading4', 'H4', false], - ['heading5', 'H5', false], - ['heading6', 'H6', false], - ['blockquote', 'BLOCKQUOTE', false], + for (const [style, cssSelector, isList] of [ + ['paragraph', 'p:not(.small, .lead)', false], + ['pre', 'pre', false], + ['heading1', 'h1:not(.display-1, .display-2, .display-3, .display-4)', false], + ['heading2', 'h2', false], + ['heading3', 'h3', false], + ['heading4', 'h4', false], + ['heading5', 'h5', false], + ['heading6', 'h6', false], + ['display-1', 'h1.display-1', false], + ['display-2', 'h1.display-2', false], + ['display-3', 'h1.display-3', false], + ['display-4', 'h1.display-4', false], + ['blockquote', 'blockquote', false], + ['small', '.small', false], + ['light', '.lead', false], ['unordered', 'UL', true], ['ordered', 'OL', true], ['checklist', 'CL', true], @@ -3132,8 +3140,8 @@ export class OdooEditor extends EventTarget { button.classList.toggle('active', false); } else if (button) { const isActive = isList - ? block.tagName === 'LI' && getListMode(block.parentElement) === tag - : block.tagName === tag; + ? block.tagName === 'LI' && getListMode(block.parentElement) === cssSelector + : block.matches(cssSelector); button.classList.toggle('active', isActive); if (!isList && isActive) { diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js index bff7f560336..0d25e024013 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/commands/commands.js @@ -51,6 +51,8 @@ import { resetOuids, firstLeaf, lastLeaf, + FONT_SIZE_CLASSES, + TEXT_STYLE_CLASSES, } from '../utils/utils.js'; const TEXT_CLASSES_REGEX = /\btext-[^\s]*\b/; @@ -322,7 +324,7 @@ export const editorCommands = { redo: editor => editor.historyRedo(), // Change tags - setTag(editor, tagName) { + setTag(editor, tagName, extraClass = "") { const range = getDeepRange(editor.editable, { correctTripleClick: true }); const selectedBlocks = [...new Set(getTraversedNodes(editor.editable, range).map(closestBlock))]; const deepestSelectedBlocks = selectedBlocks.filter(block => ( @@ -340,7 +342,24 @@ export const editorCommands = { if (inLI && tagName === "P") { inLI.oToggleList(0); } else { - setTagName(block, tagName); + const newEl = setTagName(block, tagName); + newEl.classList.remove( + ...FONT_SIZE_CLASSES, + ...TEXT_STYLE_CLASSES, + // We want to be able to edit the case `

` + // but in that case, we want to display "Header 2" and + // not "Header 3" as it is more important to display + // the semantic tag being used (especially for h1 ones). + // This is why those are not in `TEXT_STYLE_CLASSES`. + "h1", "h2", "h3", "h4", "h5", "h6" + ); + delete newEl.style.fontSize; + if (extraClass) { + newEl.classList.add(extraClass); + } + if (newEl.classList.length === 0) { + newEl.removeAttribute("class"); + } } } else { // eg do not change a
into a h1: insert the h1 diff --git a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js index d5c4225128f..e64b6b85cf4 100644 --- a/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js +++ b/addons/web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js @@ -67,6 +67,11 @@ export const PROTECTED_BLOCK_TAG = ['TR','TD','TABLE','TBODY','UL','OL','LI']; export const FONT_SIZE_CLASSES = ["display-1-fs", "display-2-fs", "display-3-fs", "display-4-fs", "h1-fs", "h2-fs", "h3-fs", "h4-fs", "h5-fs", "h6-fs", "base-fs", "small"]; +/** + * Array of all the classes used by the editor to change the text style. + */ +export const TEXT_STYLE_CLASSES = ["display-1", "display-2", "display-3", "display-4", "lead"]; + //------------------------------------------------------------------------------ // Position and sizes //------------------------------------------------------------------------------ @@ -964,7 +969,7 @@ const formatsSpecs = { .find(cls => node.classList.contains(cls)), addStyle: (node, props) => node.classList.add(props.className), removeStyle: (node) => { - node.classList.remove(...FONT_SIZE_CLASSES); + node.classList.remove(...FONT_SIZE_CLASSES, ...TEXT_STYLE_CLASSES); if (node.classList.length === 0) { node.removeAttribute("class"); } @@ -1828,10 +1833,12 @@ export function isColorGradient(value) { */ export function getFontSizeDisplayValue(sel, getCSSVariableValue, convertNumericToUnit) { const tagNameRelatedToFontSize = ["h1", "h2", "h3", "h4", "h5", "h6"]; + const styleClassesRelatedToFontSize = ["display-1", "display-2", "display-3", "display-4"]; const closestStartContainerEl = closestElement(sel.getRangeAt(0).startContainer); const closestFontSizedEl = closestStartContainerEl.closest(` [style*='font-size'], ${FONT_SIZE_CLASSES.map(className => `.${className}`)}, + ${styleClassesRelatedToFontSize.map(className => `.${className}`)}, ${tagNameRelatedToFontSize} `); let remValue; @@ -1851,13 +1858,15 @@ export function getFontSizeDisplayValue(sel, getCSSVariableValue, convertNumeric // the toolbar because it's responsive. const fontSizeClass = FONT_SIZE_CLASSES.find( className => closestFontSizedEl.classList.contains(className)); + let fsName; if (fontSizeClass) { - const fsName = fontSizeClass.substring(0, fontSizeClass.length - 3); // Without -fs - remValue = parseFloat(getCSSVariableValue(`${fsName}-font-size`)); + fsName = fontSizeClass.substring(0, fontSizeClass.length - 3); // Without -fs } else { - const tagName = closestFontSizedEl.tagName.toLowerCase(); - remValue = parseFloat(getCSSVariableValue(`${tagName}-font-size`)); + fsName = styleClassesRelatedToFontSize.find( + className => closestFontSizedEl.classList.contains(className)) + || closestFontSizedEl.tagName.toLowerCase(); } + remValue = parseFloat(getCSSVariableValue(`${fsName}-font-size`)); } // It's default font size (no font size class / style). if (remValue === undefined) { diff --git a/addons/web_editor/static/src/xml/editor.xml b/addons/web_editor/static/src/xml/editor.xml index 4ed62eb704e..13f0c9bbb4b 100644 --- a/addons/web_editor/static/src/xml/editor.xml +++ b/addons/web_editor/static/src/xml/editor.xml @@ -13,34 +13,50 @@ Normal