diff options
| author | qsm-odoo <qsm@odoo.com> | 2019-11-19 14:30:43 +0000 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2019-12-01 15:49:57 +0000 |
| commit | 216cf93b4dab381286991dcf650e859931bf1a43 (patch) | |
| tree | 27bf2eec4d0c3fa17e9f1726ff3f3413057e5812 /addons/web_editor/static/src | |
| parent | 702a0cd5c5caecb7ce747dc049f88f03182185ff (diff) | |
[REF] web, web_editor, *: review normalization of colors
* website
Review colorpicker methods to always allow to use normalized colors.
Also factorize some code in the color palette widget.
Part of https://github.com/odoo/odoo/pull/40282
In preparation of task-2122935 and other tasks
Diffstat (limited to 'addons/web_editor/static/src')
5 files changed, 84 insertions, 87 deletions
diff --git a/addons/web_editor/static/src/js/common/utils.js b/addons/web_editor/static/src/js/common/utils.js index f3373c7bad2..67267d670ee 100644 --- a/addons/web_editor/static/src/js/common/utils.js +++ b/addons/web_editor/static/src/js/common/utils.js @@ -1,6 +1,8 @@ odoo.define('web_editor.utils', function (require) { 'use strict'; +const ColorpickerDialog = require('web.ColorpickerDialog'); + /** * window.getComputedStyle cannot work properly with CSS shortcuts (like * 'border-width' which is a shortcut for the top + right + bottom + left border @@ -116,6 +118,10 @@ function _getNumericAndUnit(value) { * @returns {boolean} */ function _areCssValuesEqual(value1, value2, cssProp, $target) { + // If not colors, they will be left untouched + value1 = ColorpickerDialog.normalizeCSSColor(value1); + value2 = ColorpickerDialog.normalizeCSSColor(value2); + // String comparison first if (value1 === value2) { return true; diff --git a/addons/web_editor/static/src/js/editor/rte.js b/addons/web_editor/static/src/js/editor/rte.js index 7505e570626..b0c0891c1b6 100644 --- a/addons/web_editor/static/src/js/editor/rte.js +++ b/addons/web_editor/static/src/js/editor/rte.js @@ -767,6 +767,7 @@ return { odoo.define('web_editor.rte.summernote_custom_colors', function (require) { 'use strict'; +// These colors are already normalized as per normalizeCSSColor in web.ColorpickerDialog return [ ['#000000', '#424242', '#636363', '#9C9C94', '#CEC6CE', '#EFEFEF', '#F7F7F7', '#FFFFFF'], ['#FF0000', '#FF9C00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF', '#9C00FF', '#FF00FF'], diff --git a/addons/web_editor/static/src/js/editor/rte.summernote.js b/addons/web_editor/static/src/js/editor/rte.summernote.js index 84683eabf15..233a38edb8c 100644 --- a/addons/web_editor/static/src/js/editor/rte.summernote.js +++ b/addons/web_editor/static/src/js/editor/rte.summernote.js @@ -56,7 +56,7 @@ renderer.createPalette = function ($container, options) { selectedColor: $(targetElement).css(eventName === "foreColor" ? 'color' : 'backgroundColor'), targetClasses: [...targetElement.classList], }); - colorpicker.on('color_picked custom_color_picked', null, ev => applyColor(ev.data.target, eventName, ev.data.cssColor)); + colorpicker.on('color_picked', null, ev => applyColor(ev.data.target, eventName, ev.data.cssColor)); colorpicker.on('color_reset', null, ev => applyColor(ev.data.target, eventName, 'inherit')); return colorpicker.replace(hookEl).then(() => { if (oldColorpicker) { 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 7df4ff69ade..d4fd5c11e1b 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -3,6 +3,7 @@ odoo.define('web_editor.snippets.options', function (require) { var core = require('web.core'); const concurrency = require('web.concurrency'); +const ColorpickerDialog = require('web.ColorpickerDialog'); var Widget = require('web.Widget'); var ColorPaletteWidget = require('web_editor.ColorPalette').ColorPaletteWidget; const weUtils = require('web_editor.utils'); @@ -1193,6 +1194,15 @@ const SnippetOptionWidget = Widget.extend({ }; }, /** + * @param {*} + * @returns {string} + */ + _normalizeWidgetValue: function (value) { + value = `${value}`; // Force to string + value = ColorpickerDialog.normalizeCSSColor(value); // If is a css color, normalize it + return value; + }, + /** * @private * @param {string} widgetName * @param {UserValueWidget|this|null} parent @@ -1359,7 +1369,8 @@ const SnippetOptionWidget = Widget.extend({ const methodsNames = widget.getMethodsNames(); const proms = methodsNames.map(async methodName => { const value = await this._computeWidgetState(methodName, widget.getMethodsParams(methodName)); - widget.setValue(value, methodName); + const normalizedValue = this._normalizeWidgetValue(value); + widget.setValue(normalizedValue, methodName); }); await Promise.all(proms); @@ -1678,7 +1689,6 @@ registry.colorpicker = SnippetOptionWidget.extend({ xmlDependencies: ['/web_editor/static/src/xml/snippets.xml'], custom_events: { 'color_picked': '_onColorPicked', - 'custom_color_picked': '_onCustomColor', 'color_hover': '_onColorHovered', 'color_leave': '_onColorLeft', 'color_reset': '_onColorReset', @@ -1762,21 +1772,14 @@ registry.colorpicker = SnippetOptionWidget.extend({ * @private * @param {Event} ev */ - _onColorPicked: function () { + _onColorPicked: function (ev) { + this._changeTargetColor(ev.data.cssColor); this._updateUI().then(() => { this.$target.closest('.o_editable').trigger('content_changed'); this.$target.trigger('background-color-event', false); }); }, /** - * Called when a custom color is selected - * @param {*} ev - */ - _onCustomColor: function (ev) { - this._changeTargetColor(ev.data.cssColor); - this._onColorPicked(); - }, - /** * Called when a color button is entered -> preview the background color. * * @private 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 f73c88a3a25..38edef463b6 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 @@ -2,7 +2,7 @@ odoo.define('web_editor.ColorPalette', function (require) { 'use strict'; const core = require('web.core'); -const ColorPickerDialog = require('web.ColorpickerDialog'); +const ColorpickerDialog = require('web.ColorpickerDialog'); const Dialog = require('web.Dialog'); const Widget = require('web.Widget'); const summernoteCustomColors = require('web_editor.rte.summernote_custom_colors'); @@ -36,7 +36,7 @@ const ColorPaletteWidget = Widget.extend({ */ init: function (parent, options) { this._super.apply(this, arguments); - this.summernoteCustomColorsArray = [].concat(...summernoteCustomColors).map((color) => this._convertHexToCssRgba(color)); + this.summernoteCustomColorsArray = [].concat(...summernoteCustomColors); this.options = _.extend({ selectedColor: false, targetClasses: [], @@ -47,6 +47,11 @@ const ColorPaletteWidget = Widget.extend({ $editable: $(), }, options || {}); + const selectedColor = this.options.selectedColor; + if (selectedColor) { + this.options.selectedColor = ColorpickerDialog.normalizeCSSColor(selectedColor); + } + this.trigger_up('request_editable', {callback: val => this.options.$editable = val}); }, /** @@ -107,7 +112,7 @@ const ColorPaletteWidget = Widget.extend({ } // Render custom colors - this._buildCustomColor(); + this._buildCustomColors(); // TODO refactor in master // The primary and secondary are hardcoded here (but marked as hidden) @@ -143,7 +148,7 @@ const ColorPaletteWidget = Widget.extend({ * Reloads the color palette to get other custom colors on the page */ reloadColorPalette: function () { - this._buildCustomColor(); + this._buildCustomColors(); }, //-------------------------------------------------------------------------- @@ -153,41 +158,47 @@ const ColorPaletteWidget = Widget.extend({ /** * @private */ - _buildCustomColor: function () { - const existingColors = new Set(this.summernoteCustomColorsArray.concat(Array.from(this.el.querySelectorAll('.o_custom_color')).map(el => el.style.backgroundColor))); - if (!this.options.excluded.includes('custom')) { - Array.from(this.options.$editable.find('[style*="color"]')).forEach(el => { - for (const colorProp of ['color', 'backgroundColor']) { - const color = el.style[colorProp]; - if (color && !existingColors.has(color)) { - this._addCustomColorButton(color); - existingColors.add(color); - } - } - }); + _buildCustomColors: function () { + if (this.options.excluded.includes('custom')) { + return; } + const existingColors = new Set(this.summernoteCustomColorsArray.concat( + [...this.el.querySelectorAll('.o_custom_color')].map(el => { + return ColorpickerDialog.normalizeCSSColor(el.style.backgroundColor); + }) + )); + _.each(this.options.$editable.find('[style*="color"]'), el => { + for (const colorProp of ['color', 'backgroundColor']) { + const color = ColorpickerDialog.normalizeCSSColor(el.style[colorProp]); + if (color && !existingColors.has(color)) { + this._addCustomColorButton(color); + existingColors.add(color); + } + } + }); }, /** * Add a custom button in the coresponding section. * * @private - * @param {string} color Css rgb(a) string - * @param {Array<string>} classes Classes added to the button + * @param {string} color + * @param {string[]} classes - classes added to the button + * @returns {jQuery} */ _addCustomColorButton: function (color, classes = []) { classes.push('o_custom_color'); - this._createColorButton(color, classes).appendTo(this.$('.o_colorpicker_section[data-name="theme"]')); + const $themeSection = this.$('.o_colorpicker_section[data-name="theme"]'); + return this._createColorButton(color, classes).appendTo($themeSection); }, /** * Return a color button. * - * @param {string} color Css rgb(a) string - * @param {Array<string>} classes Classes added to the button + * @param {string} color + * @param {string[]} classes - classes added to the button + * @returns {jQuery} */ _createColorButton: function (color, classes) { - const cssColor = this._convertHexToCssRgba(color); - const selectedColor = this.options.selectedColor && this._convertHexToCssRgba(this.options.selectedColor); - if (selectedColor === cssColor) { + if (this.options.selectedColor === color) { // both colors are already normalized classes.push('selected'); } return $('<button/>', { @@ -196,33 +207,20 @@ const ColorPaletteWidget = Widget.extend({ }); }, /** - * Return the hexadecimal css color as an rgb(a) css color: rgb((r, g, b) | rgba(r, g, b, a) + * Gets normalized information about a color button. * * @private - * @param {string} hex Css hex string (#FFFFFF(FF)) + * @param {HTMLElement} buttonEl + * @returns {Object} */ - _convertHexToCssRgba: function (hex) { - if (!/^#([0-9A-F]{6}|[0-9A-F]{8})$/i.test(hex)) { - return hex; - } - - const red = parseInt(hex.substr(1, 2), 16); - const blue = parseInt(hex.substr(3, 2), 16); - const green = parseInt(hex.substr(5, 2), 16); - if (hex.length === 9) { - return _.str.sprintf('rgba(%s, %s, %s, %s)', - red, - blue, - green, - parseInt(hex.substr(7, 2), 16) - ); - } else { - return _.str.sprintf('rgb(%s, %s, %s)', - red, - blue, - green - ); - } + _getButtonInfo: function (buttonEl) { + const bgColor = buttonEl.style.backgroundColor; + const cssColor = bgColor ? ColorpickerDialog.normalizeCSSColor(bgColor) : (this.options.colorPrefix + buttonEl.dataset.color); + return { + cssColor: cssColor, + isClass: !!buttonEl.dataset.color, + target: buttonEl, + }; }, //-------------------------------------------------------------------------- @@ -236,14 +234,10 @@ const ColorPaletteWidget = Widget.extend({ * @param {Event} ev */ _onColorButtonClick: function (ev) { - const target = ev.currentTarget; + const buttonEl = ev.currentTarget; this.$('button.selected').removeClass('selected'); - $(target).addClass('selected'); - this.trigger_up('color_picked', { - cssColor: target.style.backgroundColor || this.options.colorPrefix + target.dataset.color, - isClass: !!target.dataset.color, - target: ev.target, - }); + $(buttonEl).addClass('selected'); + this.trigger_up('color_picked', this._getButtonInfo(buttonEl)); }, /** * Called when a color button is entered. @@ -253,12 +247,7 @@ const ColorPaletteWidget = Widget.extend({ */ _onColorButtonEnter: function (ev) { ev.stopPropagation(); - const target = ev.currentTarget; - this.trigger_up('color_hover', { - cssColor: target.style.backgroundColor || this.options.colorPrefix + target.dataset.color, - isClass: !!target.dataset.color, - target: ev.target, - }); + this.trigger_up('color_hover', this._getButtonInfo(ev.currentTarget)); }, /** * Called when a color button is left. @@ -268,19 +257,17 @@ const ColorPaletteWidget = Widget.extend({ */ _onColorButtonLeave: function (ev) { ev.stopPropagation(); - let params = { - cssColor: '', - isClass: false, - target: ev.target, - }; const selected = this.el.querySelector('button.selected'); + let params = null; if (selected) { + params = this._getButtonInfo(selected); + } else { params = { - cssColor: selected.style.backgroundColor || this.options.colorPrefix + selected.dataset.color, - isClass: !!selected.dataset.color, - target: ev.target, + cssColor: '', + isClass: false, }; } + params.target = ev.target; this.trigger_up('color_leave', params); }, /** @@ -302,17 +289,17 @@ const ColorPaletteWidget = Widget.extend({ * @param {Event} ev */ _onCustomColorButtonClick: async function (ev) { - const originalEvent = ev; - const $selected = this.$('button.selected'); - const colorpicker = new ColorPickerDialog(this, { + const target = ev.target; + const $selected = this.$('button.selected').removeClass('selected'); + const colorpicker = new ColorpickerDialog(this, { defaultColor: this.options.defaultColor || $selected.css('background-color'), }); colorpicker.on('colorpicker:saved', this, ev => { - $selected.removeClass('selected'); this._addCustomColorButton(ev.data.cssColor, ['selected']); - this.trigger_up('custom_color_picked', { + this.trigger_up('color_picked', { cssColor: ev.data.cssColor, - target: originalEvent.target, + isClass: false, + target: target, }); }); colorpicker.open(); |
