From 85531edd1be76287daeb54e1425cd3f59e1c138c Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Wed, 22 Jul 2020 10:04:17 +0000 Subject: [PATCH] [FIX] web_editor, *: restore editor UI for selected CSS variables *: website Commit [1] broke the UI for some options related to CSS variables when using Chrome. The commit made sure the string-value CSS variables are printed with quotes, so that the JS representation of the CSS values can distinguish them (strings = strings with surrounding quotes, others like colors, numbers, etc = strings without surrounding quotes). With chrome, the printed surrounding single quotes are read as double quotes for strange reasons though... so the value "a" was not considered equal to the value 'a'. This commit makes sure surrounding quotes are normalized. This is done through a new utility function to read CSS variables. This also makes sure the values are trimmed, and colors normalized. [1]: https://github.com/odoo/odoo/commit/3a34e39caa8544059dfb1888edc29c62c3efde31 closes odoo/odoo#54757 Signed-off-by: Quentin Smetz (qsm) --- .../web_editor/static/src/js/common/utils.js | 21 ++++++++++++ .../static/src/js/editor/snippets.options.js | 11 ++---- .../src/js/wysiwyg/widgets/color_palette.js | 12 +++---- .../static/src/js/editor/snippets.options.js | 34 ++++++------------- .../static/src/snippets/s_chart/000.js | 3 +- .../static/src/snippets/s_chart/options.js | 5 +-- .../static/src/snippets/s_countdown/000.js | 4 +-- 7 files changed, 48 insertions(+), 42 deletions(-) diff --git a/addons/web_editor/static/src/js/common/utils.js b/addons/web_editor/static/src/js/common/utils.js index 1ed08a80792..61e8f648ee8 100644 --- a/addons/web_editor/static/src/js/common/utils.js +++ b/addons/web_editor/static/src/js/common/utils.js @@ -167,6 +167,26 @@ function _computeColorClasses(colorNames, prefix = 'bg-') { } return classes; } +/** + * @param {string} key + * @param {CSSStyleDeclaration} [htmlStyle] if not provided, it is computed + * @returns {string} + */ +function _getCSSVariableValue(key, htmlStyle) { + if (htmlStyle === undefined) { + htmlStyle = window.getComputedStyle(document.documentElement); + } + // Get trimmed value from the HTML element + let value = htmlStyle.getPropertyValue(`--${key}`).trim(); + // If it is a color value, it needs to be normalized + value = ColorpickerWidget.normalizeCSSColor(value); + // Normally scss-string values are "printed" single-quoted. That way no + // magic conversation is needed when customizing a variable: either save it + // quoted for strings or non quoted for colors, numbers, etc. However, + // Chrome has the annoying behavior of changing the single-quotes to + // double-quotes when reading them through getPropertyValue... + return value.replace(/"/g, "'"); +} return { CSS_SHORTHANDS: CSS_SHORTHANDS, @@ -178,5 +198,6 @@ return { areCssValuesEqual: _areCssValuesEqual, isColorCombinationName: _isColorCombinationName, computeColorClasses: _computeColorClasses, + getCSSVariableValue: _getCSSVariableValue, }; }); diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index 285283f1fc8..daa53fb7dae 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -1198,9 +1198,7 @@ const ColorpickerUserValueWidget = SelectUserValueWidget.extend({ const cssCompatible = this.options.dataAttributes.hasOwnProperty('cssCompatible'); if ((useCssColor || cssCompatible) && !ColorpickerWidget.isCSSColor(value)) { if (useCssColor) { - const style = window.getComputedStyle(document.documentElement); - value = style.getPropertyValue(`--${value}`).trim(); - value = ColorpickerWidget.normalizeCSSColor(value); + value = weUtils.getCSSVariableValue(value); } else { value = `var(--${value})`; } @@ -1840,8 +1838,7 @@ const SnippetOptionWidget = Widget.extend({ // At this point, the widget value is either a property/color name or // an actual css property value. If it is a property/color name, we will // apply a css variable as style value. - const htmlStyle = window.getComputedStyle(document.documentElement); - const htmlPropValue = htmlStyle.getPropertyValue('--' + widgetValue); + const htmlPropValue = weUtils.getCSSVariableValue(widgetValue); if (htmlPropValue) { widgetValue = `var(--${widgetValue})`; } @@ -2999,9 +2996,7 @@ const ImageHandlerOption = SnippetOptionWidget.extend({ */ _normalizeColor(color) { if (!ColorpickerWidget.isCSSColor(color)) { - const style = window.getComputedStyle(document.documentElement); - color = style.getPropertyValue('--' + color).trim(); - color = ColorpickerWidget.normalizeCSSColor(color); + color = weUtils.getCSSVariableValue(color); } return color; }, diff --git a/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js b/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js index 5ed02d3a332..25e8dfa2835 100644 --- a/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js +++ b/addons/web_editor/static/src/js/wysiwyg/widgets/color_palette.js @@ -115,7 +115,7 @@ const ColorPaletteWidget = Widget.extend({ } this.colorNames.push(colorName); if (!isCCName && !elem.classList.contains('d-none')) { - const color = ColorpickerWidget.normalizeCSSColor(this.style.getPropertyValue('--' + colorName).trim()); + const color = weUtils.getCSSVariableValue(colorName, this.style); this.colorToColorNames[color] = colorName; } }); @@ -125,7 +125,7 @@ const ColorPaletteWidget = Widget.extend({ if (this.options.selectedColor) { let selectedColor = this.options.selectedColor; if (compatibilityColorNames.includes(selectedColor)) { - selectedColor = this.style.getPropertyValue('--' + selectedColor).trim() || selectedColor; + selectedColor = weUtils.getCSSVariableValue(selectedColor, this.style) || selectedColor; } selectedColor = ColorpickerWidget.normalizeCSSColor(selectedColor); if (selectedColor !== 'rgba(0, 0, 0, 0)') { @@ -138,7 +138,7 @@ const ColorPaletteWidget = Widget.extend({ // Colorpicker let defaultColor = this.selectedColor; if (defaultColor && !ColorpickerWidget.isCSSColor(defaultColor)) { - defaultColor = ColorpickerWidget.normalizeCSSColor(this.style.getPropertyValue('--' + defaultColor).trim()); + defaultColor = weUtils.getCSSVariableValue(defaultColor, this.style); } this.colorPicker = new ColorpickerWidget(this, { defaultColor: defaultColor, @@ -175,8 +175,8 @@ const ColorPaletteWidget = Widget.extend({ }); }, }); - this.style.getPropertyValue(`--custom-colors`).trim().split(' ').forEach(v => { - const color = this.style.getPropertyValue(`--${v.substring(1, v.length - 1)}`).trim(); + weUtils.getCSSVariableValue('custom-colors', this.style).split(' ').forEach(v => { + const color = weUtils.getCSSVariableValue(v.substring(1, v.length - 1), this.style); if (ColorpickerWidget.isCSSColor(color)) { this._addCustomColor(existingColors, color); } @@ -201,7 +201,7 @@ const ColorPaletteWidget = Widget.extend({ return; } if (!ColorpickerWidget.isCSSColor(color)) { - color = this.style.getPropertyValue('--' + color).trim(); + color = weUtils.getCSSVariableValue(color, this.style); } const normColor = ColorpickerWidget.normalizeCSSColor(color); if (!existingColors.has(normColor)) { diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 9c405641cc7..981ca05e387 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -78,8 +78,8 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ */ start: async function () { const style = window.getComputedStyle(document.documentElement); - const nbFonts = parseInt(style.getPropertyValue('--number-of-fonts')); - const googleFontsProperty = style.getPropertyValue('--google-fonts').trim(); + const nbFonts = parseInt(weUtils.getCSSVariableValue('number-of-fonts', style)); + const googleFontsProperty = weUtils.getCSSVariableValue('google-fonts', style); this.googleFonts = googleFontsProperty ? googleFontsProperty.split(/\s*,\s*/g) : []; this.googleFonts = this.googleFonts.map(font => font.substring(1, font.length - 1)); // Unquote @@ -93,7 +93,7 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ const fontEl = document.createElement('we-button'); fontEl.classList.add(`o_we_option_font_${realFontNb}`); fontEl.dataset.variable = variable; - fontEl.dataset[methodName] = style.getPropertyValue(`--font-number-${realFontNb}`).trim(); + fontEl.dataset[methodName] = weUtils.getCSSVariableValue(`font-number-${realFontNb}`, style); fontEl.dataset.font = realFontNb; fontEls.push(fontEl); this.menuEl.appendChild(fontEl); @@ -196,7 +196,7 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ const values = {}; const style = window.getComputedStyle(document.documentElement); _.each(FontFamilyPickerUserValueWidget.prototype.fontVariables, variable => { - const value = style.getPropertyValue(`--${variable}`).trim(); + const value = weUtils.getCSSVariableValue(variable, style); if (value.substring(1, value.length - 1) === googleFont) { // If an element is using the google font being removed, reset // it to the theme default. @@ -303,11 +303,10 @@ options.Class.include({ return mostXmlIDsStr; // Need to return the exact same string as in possibleValues } case 'customizeWebsiteVariable': { - const style = window.getComputedStyle(document.documentElement); - return style.getPropertyValue('--' + params.variable).trim(); + return weUtils.getCSSVariableValue(params.variable); } case 'customizeWebsiteColor': { - return this._getCSSColorFromName(params.color); + return weUtils.getCSSVariableValue(params.color); } } return this._super(...arguments); @@ -392,16 +391,6 @@ options.Class.include({ }, }); }, - /** - * @private - * @param {string} colorName - * @returns {string} - */ - _getCSSColorFromName: function (colorName) { - const style = window.getComputedStyle(document.documentElement); - const color = style.getPropertyValue('--' + colorName).trim(); - return ColorpickerWidget.normalizeCSSColor(color); - }, /** * @private */ @@ -632,8 +621,8 @@ options.registry.Theme = options.Class.extend({ start: async function () { // Checks for support of the old color system const style = window.getComputedStyle(document.documentElement); - const supportOldColorSystem = style.getPropertyValue('--support-13-0-color-system').trim() === 'true'; - const hasCustomizedOldColorSystem = style.getPropertyValue('--has-customized-13-0-color-system').trim() === 'true'; + const supportOldColorSystem = weUtils.getCSSVariableValue('support-13-0-color-system', style) === 'true'; + const hasCustomizedOldColorSystem = weUtils.getCSSVariableValue('has-customized-13-0-color-system', style) === 'true'; this._showOldColorSystemWarning = supportOldColorSystem && hasCustomizedOldColorSystem; return this._super(...arguments); @@ -777,8 +766,7 @@ options.registry.Theme = options.Class.extend({ for (const widget of widgets) { if (widget.getMethodsNames().includes('customizeWebsiteVariable') && widget.getMethodsParams('customizeWebsiteVariable').variable === 'color-palettes-number') { - const style = window.getComputedStyle(document.documentElement); - const hasCustomizedColors = style.getPropertyValue('--has-customized-colors').trim(); + const hasCustomizedColors = weUtils.getCSSVariableValue('has-customized-colors'); if (hasCustomizedColors && hasCustomizedColors !== 'false') { return _t("Changing the color palette will reset all your color customizations, are you sure you want to proceed?"); } @@ -859,7 +847,7 @@ options.registry.Theme = options.Class.extend({ async _renderCustomXML(uiFragment) { const paletteSelectorEl = uiFragment.querySelector('[data-variable="color-palettes-number"]'); const style = window.getComputedStyle(document.documentElement); - const nbPalettes = parseInt(style.getPropertyValue('--number-of-color-palettes')); + const nbPalettes = parseInt(weUtils.getCSSVariableValue('number-of-color-palettes', style)); for (let i = 1; i <= nbPalettes; i++) { const btnEl = document.createElement('we-button'); btnEl.classList.add('o_palette_color_preview_button'); @@ -867,7 +855,7 @@ options.registry.Theme = options.Class.extend({ for (let c = 1; c <= 5; c++) { const colorPreviewEl = document.createElement('span'); colorPreviewEl.classList.add('o_palette_color_preview'); - const color = style.getPropertyValue(`--o-palette-${i}-o-color-${c}`).trim(); + const color = weUtils.getCSSVariableValue(`o-palette-${i}-o-color-${c}`, style); colorPreviewEl.style.backgroundColor = color; btnEl.appendChild(colorPreviewEl); } diff --git a/addons/website/static/src/snippets/s_chart/000.js b/addons/website/static/src/snippets/s_chart/000.js index 865190fc81b..2c67bd03612 100644 --- a/addons/website/static/src/snippets/s_chart/000.js +++ b/addons/website/static/src/snippets/s_chart/000.js @@ -2,6 +2,7 @@ odoo.define('website.s_chart', function (require) { 'use strict'; const publicWidget = require('web.public.widget'); +const weUtils = require('web_editor.utils'); const ChartWidget = publicWidget.Widget.extend({ selector: '.s_chart', @@ -131,7 +132,7 @@ const ChartWidget = publicWidget.Widget.extend({ if (!color) { return 'transparent'; } - return this.style.getPropertyValue(`--${color}`).trim() || color; + return weUtils.getCSSVariableValue(color, this.style) || color; }, }); diff --git a/addons/website/static/src/snippets/s_chart/options.js b/addons/website/static/src/snippets/s_chart/options.js index 6dd654fdf8c..a76a0a71f31 100644 --- a/addons/website/static/src/snippets/s_chart/options.js +++ b/addons/website/static/src/snippets/s_chart/options.js @@ -4,6 +4,7 @@ odoo.define('website.s_chart_options', function (require) { var core = require('web.core'); const {ColorpickerWidget} = require('web.Colorpicker'); var options = require('web_editor.snippets.options'); +const weUtils = require('web_editor.utils'); var _t = core._t; @@ -81,7 +82,7 @@ options.registry.InnerChart = options.Class.extend({ const color = el.dataset.backgroundColor || el.dataset.borderColor; if (color) { el.style.border = '2px solid'; - el.style.borderColor = ColorpickerWidget.isCSSColor(color) ? color : this.style.getPropertyValue(`--${color}`).trim(); + el.style.borderColor = ColorpickerWidget.isCSSColor(color) ? color : weUtils.getCSSVariableValue(color, this.style); } }); }, @@ -368,7 +369,7 @@ options.registry.InnerChart = options.Class.extend({ } }); customColors = customColors.filter((el, i, array) => { - return !this.style.getPropertyValue(`--${el}`) && array.indexOf(el) === i && el !== ''; // unique non class not transparent + return !weUtils.getCSSVariableValue(el, this.style) && array.indexOf(el) === i && el !== ''; // unique non class not transparent }); ev.data.onSuccess(customColors); }, diff --git a/addons/website/static/src/snippets/s_countdown/000.js b/addons/website/static/src/snippets/s_countdown/000.js index cdee6a0fd8a..9959f6680a4 100644 --- a/addons/website/static/src/snippets/s_countdown/000.js +++ b/addons/website/static/src/snippets/s_countdown/000.js @@ -4,6 +4,7 @@ odoo.define('website.s_countdown', function (require) { const {ColorpickerWidget} = require('web.Colorpicker'); const core = require('web.core'); const publicWidget = require('web.public.widget'); +const weUtils = require('web_editor.utils'); const qweb = core.qweb; const _t = core._t; @@ -75,8 +76,7 @@ const CountdownWidget = publicWidget.Widget.extend({ if (ColorpickerWidget.isCSSColor(color)) { return color; } - const style = window.getComputedStyle(document.documentElement); - return style.getPropertyValue('--' + color).trim(); + return weUtils.getCSSVariableValue(color); }, /** * Gets the time difference in seconds between now and countdown due date.