[IMP] web_editor, *: add new user value colorpicker widget
* web, mass_mailing, website Introduced a new sub-widget for snippet options: we-colorpicker. This allows to retrieve a color value (either a normalized css color or a theme color name) to be used for a snippet option method. This commit replaces the old 'colorpicker' snippet option whose behavior is now simply achieved by defining an xml option using a we-colorpicker widget in combination with the 'selectStyle' standard method. This commit also adds the possibility to control the border-color of elements alongside their border-width. Again, just a we-colorpicker widget in combination with the 'selectStyle' standard method. Note: this commit reviewed what the colorpalette palette widget notifies. This is not a cssColor and a 'isClass' flag to say if it is a css class or not. The colorpalette always returns a color string which can be the name of a color like 'alpha'. This is up to the caller to check if the color string is a css color or not with isCSSColor. In the case it is not, the related code can read the actual color by reading the related css variable. Part of https://github.com/odoo/odoo/pull/40282 In preparation of task-2122935 and other tasks
This commit is contained in:
@@ -807,8 +807,12 @@
|
||||
data-selector=".note-editable > div:not(.o_layout), .note-editable .oe_structure > div, td, th"
|
||||
data-exclude=".o_mail_no_resize, .o_mail_no_options"/>
|
||||
|
||||
<div data-js="colorpicker" string="Background Color"
|
||||
data-selector=".note-editable > div:not(.o_layout), .note-editable .oe_structure > div, td, th"
|
||||
data-exclude=".o_mail_no_colorpicker, .o_mail_no_options"/>
|
||||
<div data-selector=".note-editable > div:not(.o_layout), .note-editable .oe_structure > div, td, th"
|
||||
data-exclude=".o_mail_no_colorpicker, .o_mail_no_options">
|
||||
<we-colorpicker string="Background Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"/>
|
||||
</div>
|
||||
</template>
|
||||
</odoo>
|
||||
|
||||
@@ -15,7 +15,7 @@ var ColorpickerDialog = Dialog.extend({
|
||||
'mousedown .o_color_pick_area': '_onMouseDownPicker',
|
||||
'mousedown .o_color_slider': '_onMouseDownSlider',
|
||||
'mousedown .o_opacity_slider': '_onMouseDownOpacitySlider',
|
||||
'change .o_color_picker_inputs' : '_onChangeInputs',
|
||||
'change .o_color_picker_inputs': '_onChangeInputs',
|
||||
}),
|
||||
|
||||
/**
|
||||
@@ -560,6 +560,9 @@ ColorpickerDialog.convertCSSColorToRgba = function (cssColor) {
|
||||
};
|
||||
}
|
||||
|
||||
// TODO maybe implement a support for receiving css color like 'red' or
|
||||
// 'transparent' (which are now considered non-css color by isCSSColor...)
|
||||
|
||||
return false;
|
||||
};
|
||||
/**
|
||||
@@ -580,6 +583,16 @@ ColorpickerDialog.normalizeCSSColor = function (cssColor) {
|
||||
}
|
||||
return ColorpickerDialog.convertRgbaToCSSColor(rgba.red, rgba.green, rgba.blue, rgba.opacity);
|
||||
};
|
||||
/**
|
||||
* Checks if a given string is a css color.
|
||||
*
|
||||
* @static
|
||||
* @param {string} cssColor
|
||||
* @returns {boolean}
|
||||
*/
|
||||
ColorpickerDialog.isCSSColor = function (cssColor) {
|
||||
return ColorpickerDialog.convertCSSColorToRgba(cssColor) !== false;
|
||||
};
|
||||
|
||||
return ColorpickerDialog;
|
||||
});
|
||||
|
||||
@@ -14,6 +14,7 @@ const ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
const CSS_SHORTHANDS = {
|
||||
'border-width': ['border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'],
|
||||
'border-radius': ['border-top-left-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius'],
|
||||
'border-color': ['border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color'],
|
||||
};
|
||||
/**
|
||||
* Key-value mapping to list converters from an unit A to an unit B.
|
||||
|
||||
@@ -4,6 +4,7 @@ odoo.define('web_editor.rte.summernote', function (require) {
|
||||
var Class = require('web.Class');
|
||||
const concurrency = require('web.concurrency');
|
||||
var core = require('web.core');
|
||||
const ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
var ColorPaletteWidget = require('web_editor.ColorPalette').ColorPaletteWidget;
|
||||
var mixins = require('web.mixins');
|
||||
var fonts = require('wysiwyg.fonts');
|
||||
@@ -50,13 +51,17 @@ renderer.createPalette = function ($container, options) {
|
||||
const targetNode = r.sc;
|
||||
const targetElement = targetNode.nodeType === Node.ELEMENT_NODE ? targetNode : targetNode.parentNode;
|
||||
colorpicker = new ColorPaletteWidget(parent, {
|
||||
colorPrefix: eventName === "foreColor" ? 'text-' : 'bg-',
|
||||
excluded: ['transparent_grayscale'],
|
||||
$editable: rte.Class.prototype.editable(), // Our parent is the root widget, we can't retrieve the editable section from it...
|
||||
selectedColor: $(targetElement).css(eventName === "foreColor" ? 'color' : 'backgroundColor'),
|
||||
targetClasses: [...targetElement.classList],
|
||||
});
|
||||
colorpicker.on('color_picked', null, ev => applyColor(ev.data.target, eventName, ev.data.cssColor));
|
||||
colorpicker.on('color_picked', null, ev => {
|
||||
let color = ev.data.color;
|
||||
if (!ColorpickerDialog.isCSSColor(color)) {
|
||||
color = (eventName === "foreColor" ? 'text-' : 'bg-') + color;
|
||||
}
|
||||
applyColor(ev.data.target, eventName, color);
|
||||
});
|
||||
colorpicker.on('color_reset', null, ev => applyColor(ev.data.target, eventName, 'inherit'));
|
||||
return colorpicker.replace(hookEl).then(() => {
|
||||
if (oldColorpicker) {
|
||||
|
||||
@@ -567,6 +567,7 @@ const SelectUserValueWidget = UserValueWidget.extend({
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -827,16 +828,169 @@ const MultiUserValueWidget = UserValueWidget.extend({
|
||||
},
|
||||
});
|
||||
|
||||
const ColorpickerUserValueWidget = SelectUserValueWidget.extend({ // FIXME should be reloaded on focus
|
||||
custom_events: {
|
||||
'color_picked': '_onColorPicked',
|
||||
'color_hover': '_onColorHovered',
|
||||
'color_leave': '_onColorLeft',
|
||||
'color_reset': '_onColorReset',
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function () {
|
||||
this._super(...arguments);
|
||||
if (!this.title) {
|
||||
this.title = ' ';
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: async function () {
|
||||
const _super = this._super.bind(this);
|
||||
const args = arguments;
|
||||
|
||||
this.el.classList.add('o_we_so_color_palette');
|
||||
|
||||
// Pre-instanciate the color palette widget
|
||||
await this._renderColorPalette();
|
||||
|
||||
// Build the select element with a custom span to hold the color preview
|
||||
this.colorPreviewEl = document.createElement('span');
|
||||
this.options.childNodes = [this.colorPalette.el];
|
||||
this.options.valueEl = this.colorPreviewEl;
|
||||
|
||||
return _super(...args);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getMethodsParams: function () {
|
||||
return _.extend(this._super(...arguments), {
|
||||
colorNames: this.colorPalette.getColorNames(),
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getValue: function (methodName) {
|
||||
return this._previewColor || this._super(...arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
isContainer: function () {
|
||||
return false;
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_renderColorPalette: function () {
|
||||
const options = {};
|
||||
options.selectedColor = this._value;
|
||||
if (this.options.dataAttributes.excluded) {
|
||||
options.excluded = this.options.dataAttributes.excluded.replace(/ /g, '').split(',');
|
||||
}
|
||||
const oldColorPalette = this.colorPalette;
|
||||
this.colorPalette = new ColorPaletteWidget(this, options);
|
||||
if (oldColorPalette) {
|
||||
return this.colorPalette.insertAfter(oldColorPalette.el).then(() => {
|
||||
oldColorPalette.destroy();
|
||||
});
|
||||
}
|
||||
return this.colorPalette.appendTo(document.createDocumentFragment());
|
||||
},
|
||||
/**
|
||||
* Updates the color preview + re-render the whole color palette widget.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_updateUI: async function (color) {
|
||||
await this._super(...arguments);
|
||||
|
||||
this.colorPreviewEl.classList.remove(...this.colorPalette.getColorNames().map(c => 'bg-' + c));
|
||||
this.colorPreviewEl.style.removeProperty('background-color');
|
||||
|
||||
if (this._value) {
|
||||
if (ColorpickerDialog.isCSSColor(this._value)) {
|
||||
this.colorPreviewEl.style.backgroundColor = this._value;
|
||||
} else {
|
||||
this.colorPreviewEl.classList.add('bg-' + this._value);
|
||||
}
|
||||
}
|
||||
|
||||
await this._renderColorPalette();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when a color button is clicked -> confirms the preview.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorPicked: function (ev) {
|
||||
this._previewColor = false;
|
||||
this._value = ev.data.color;
|
||||
this._notifyValueChange(false);
|
||||
},
|
||||
/**
|
||||
* Called when a color button is entered -> previews the background color.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorHovered: function (ev) {
|
||||
this._previewColor = ev.data.color;
|
||||
this._notifyValueChange(true);
|
||||
},
|
||||
/**
|
||||
* Called when a color button is left -> cancels the preview.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorLeft: function (ev) {
|
||||
this._previewColor = false;
|
||||
this._notifyValueChange('reset');
|
||||
},
|
||||
/**
|
||||
* Called when the color reset button is clicked -> removes all color
|
||||
* classes and color styles.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onColorReset: function () {
|
||||
this._value = '';
|
||||
this._notifyValueChange(false);
|
||||
},
|
||||
});
|
||||
|
||||
const userValueWidgetsRegistry = {
|
||||
'we-button': ButtonUserValueWidget,
|
||||
'we-checkbox': CheckboxUserValueWidget,
|
||||
'we-select': SelectUserValueWidget,
|
||||
'we-input': InputUserValueWidget,
|
||||
'we-multi': MultiUserValueWidget,
|
||||
'we-colorpicker': ColorpickerUserValueWidget,
|
||||
};
|
||||
|
||||
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
/**
|
||||
* Handles a set of options for one snippet. The registry returned by this
|
||||
* module contains the names of the specialized SnippetOptionWidget which can be
|
||||
@@ -1024,7 +1178,54 @@ const SnippetOptionWidget = Widget.extend({
|
||||
* @param {Object} params
|
||||
*/
|
||||
selectStyle: function (previewMode, widgetValue, params) {
|
||||
if (params.cssProperty === 'background-color') {
|
||||
this.$target.trigger('background-color-event', previewMode);
|
||||
}
|
||||
|
||||
const cssProps = weUtils.CSS_SHORTHANDS[params.cssProperty] || [params.cssProperty];
|
||||
for (const cssProp of cssProps) {
|
||||
// Always reset the inline style first to not put inline style on an
|
||||
// element which already have this style through css stylesheets.
|
||||
this.$target[0].style.setProperty(cssProp, '');
|
||||
}
|
||||
if (params.extraClass) {
|
||||
this.$target.removeClass(params.extraClass);
|
||||
}
|
||||
|
||||
// Only allow to use a color name as a className if we know about the
|
||||
// other potential color names (to remove) and if we know about a prefix
|
||||
// (otherwise we suppose that we should use the actual related color).
|
||||
if (params.colorNames && params.colorPrefix) {
|
||||
const classes = params.colorNames.map(c => params.colorPrefix + c);
|
||||
this.$target[0].classList.remove(...classes);
|
||||
|
||||
if (params.colorNames.includes(widgetValue)) {
|
||||
const originalCSSValue = window.getComputedStyle(this.$target[0])[cssProps[0]];
|
||||
const className = params.colorPrefix + widgetValue;
|
||||
this.$target[0].classList.add(className);
|
||||
if (originalCSSValue !== window.getComputedStyle(this.$target[0])[cssProps[0]]) {
|
||||
// If applying the class did indeed changed the css
|
||||
// property we are editing, nothing more has to be done.
|
||||
// (except adding the extra class)
|
||||
this.$target.addClass(params.extraClass);
|
||||
return;
|
||||
}
|
||||
// Otherwise, it means that class probably does not exist,
|
||||
// we remove it and continue. Especially useful for some
|
||||
// prefixes which only work with some color names but not all.
|
||||
this.$target[0].classList.remove(className);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (htmlPropValue) {
|
||||
widgetValue = `var(--${widgetValue})`;
|
||||
}
|
||||
|
||||
const values = widgetValue.split(/\s+/g);
|
||||
while (values.length < cssProps.length) {
|
||||
switch (values.length) {
|
||||
@@ -1043,15 +1244,6 @@ const SnippetOptionWidget = Widget.extend({
|
||||
}
|
||||
}
|
||||
|
||||
for (const cssProp of cssProps) {
|
||||
// Always reset the inline style first to not put inline style on an
|
||||
// element which already have this style through css stylesheets.
|
||||
this.$target[0].style.setProperty(cssProp, '');
|
||||
}
|
||||
if (params.extraClass) {
|
||||
this.$target.removeClass(params.extraClass);
|
||||
}
|
||||
|
||||
const styles = window.getComputedStyle(this.$target[0]);
|
||||
let hasUserValue = false;
|
||||
for (let i = cssProps.length - 1; i > 0; i--) {
|
||||
@@ -1160,6 +1352,14 @@ const SnippetOptionWidget = Widget.extend({
|
||||
return dataValue || params.attributeDefaultValue || '';
|
||||
}
|
||||
case 'selectStyle': {
|
||||
if (params.colorPrefix && params.colorNames) {
|
||||
for (const c of params.colorNames) {
|
||||
if (this.$target[0].classList.contains(params.colorPrefix + c)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const styles = window.getComputedStyle(this.$target[0]);
|
||||
const cssProps = weUtils.CSS_SHORTHANDS[params.cssProperty] || [params.cssProperty];
|
||||
const cssValues = cssProps.map(cssProp => {
|
||||
@@ -1198,7 +1398,7 @@ const SnippetOptionWidget = Widget.extend({
|
||||
* @returns {string}
|
||||
*/
|
||||
_normalizeWidgetValue: function (value) {
|
||||
value = `${value}`; // Force to string
|
||||
value = `${value}`.trim(); // Force to a trimmed string
|
||||
value = ColorpickerDialog.normalizeCSSColor(value); // If is a css color, normalize it
|
||||
return value;
|
||||
},
|
||||
@@ -1682,137 +1882,6 @@ registry['sizing_y'] = registry.sizing.extend({
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles the edition of snippet's background color classes.
|
||||
*/
|
||||
registry.colorpicker = SnippetOptionWidget.extend({
|
||||
xmlDependencies: ['/web_editor/static/src/xml/snippets.xml'],
|
||||
custom_events: {
|
||||
'color_picked': '_onColorPicked',
|
||||
'color_hover': '_onColorHovered',
|
||||
'color_leave': '_onColorLeft',
|
||||
'color_reset': '_onColorReset',
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: async function () {
|
||||
const _super = this._super.bind(this);
|
||||
const args = arguments;
|
||||
|
||||
// Pre-instanciate the color palette widget
|
||||
const options = {
|
||||
selectedColor: this.$target.css('background-color'),
|
||||
targetClasses: [...this.$target[0].classList],
|
||||
};
|
||||
if (this.data.paletteExclude) {
|
||||
options.excluded = this.data.paletteExclude.replace(/ /g, '').split(',');
|
||||
}
|
||||
if (this.data.colorPrefix) {
|
||||
options.colorPrefix = this.data.colorPrefix;
|
||||
}
|
||||
this.colorPalette = new ColorPaletteWidget(this, options);
|
||||
await this.colorPalette.appendTo(document.createDocumentFragment());
|
||||
|
||||
// Build the select element with a custom span to hold the color preview
|
||||
this.colorPreviewEl = document.createElement('span');
|
||||
const selectWidget = new SelectUserValueWidget(this, this.data.string, {
|
||||
classes: ['o_we_so_color_palette'],
|
||||
childNodes: [this.colorPalette.el],
|
||||
valueEl: this.colorPreviewEl,
|
||||
});
|
||||
await selectWidget.appendTo(document.createDocumentFragment());
|
||||
|
||||
// Replace the colorpicker UI with the select element
|
||||
this.$el.empty().append(selectWidget.el);
|
||||
return _super(...args);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
onFocus: function () {
|
||||
this.colorPalette.reloadColorPalette();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Change the color of the targeted background
|
||||
*
|
||||
* @private
|
||||
* @param {string} cssColor
|
||||
* @param {boolean} isClass
|
||||
*/
|
||||
_changeTargetColor: function (cssColor, isClass) {
|
||||
this.$target[0].classList.remove(...this.colorPalette.getClasses());
|
||||
if (isClass) {
|
||||
this.$target.addClass(cssColor);
|
||||
} else {
|
||||
this.$target.css('background-color', cssColor);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_updateUI: async function () {
|
||||
await this._super.apply(this, arguments);
|
||||
this.colorPreviewEl.style.backgroundColor = this.$target.css('background-color');
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when a color button is clicked -> confirm the preview.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_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 color button is entered -> preview the background color.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorHovered: function (ev) {
|
||||
this._changeTargetColor(ev.data.cssColor, ev.data.isClass);
|
||||
this.$target.trigger('background-color-event', true);
|
||||
},
|
||||
/**
|
||||
* Called when a color button is left -> cancel the preview.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorLeft: function (ev) {
|
||||
this._changeTargetColor(ev.data.cssColor, ev.data.isClass);
|
||||
this.$target.trigger('background-color-event', 'reset');
|
||||
},
|
||||
/**
|
||||
* Called when the color reset button is clicked -> remove all background
|
||||
* color classes.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onColorReset: function () {
|
||||
this._changeTargetColor('');
|
||||
this._updateUI().then(() => {
|
||||
this.$target.trigger('content_changed');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles the edition of snippet's background image.
|
||||
*/
|
||||
|
||||
@@ -27,8 +27,6 @@ const ColorPaletteWidget = Widget.extend({
|
||||
*
|
||||
* @param {Object} [options]
|
||||
* @param {string} [options.selectedColor] The class or css attribute color selected by default.
|
||||
* @param {string[]} [options.targetClasses]
|
||||
* @param {string} [options.colorPrefix='bg-'] Used for the class based colors (theme).
|
||||
* @param {boolean} [options.resetButton=true] Whether to display or not the reset button.
|
||||
* @param {string[]} [options.excluded=[]] Sections not to display.
|
||||
* @param {string[]} [options.excludeSectionOf] Extra section to exclude: the one containing the named color.
|
||||
@@ -39,8 +37,6 @@ const ColorPaletteWidget = Widget.extend({
|
||||
this.summernoteCustomColorsArray = [].concat(...summernoteCustomColors);
|
||||
this.options = _.extend({
|
||||
selectedColor: false,
|
||||
targetClasses: [],
|
||||
colorPrefix: 'bg-',
|
||||
resetButton: true,
|
||||
excluded: [],
|
||||
excludeSectionOf: null,
|
||||
@@ -124,31 +120,26 @@ const ColorPaletteWidget = Widget.extend({
|
||||
this.$el.append($('<button/>', {'class': 'd-none', 'data-color': 'secondary'}));
|
||||
|
||||
// Compute class colors
|
||||
this.classes = [];
|
||||
this.colorNames = [];
|
||||
const style = window.getComputedStyle(document.documentElement);
|
||||
this.el.querySelectorAll('button[data-color]').forEach(elem => {
|
||||
const color = elem.dataset.color;
|
||||
const colorName = elem.dataset.color;
|
||||
const color = ColorpickerDialog.normalizeCSSColor(style.getPropertyValue('--' + colorName).trim());
|
||||
const $color = $(elem);
|
||||
$color.addClass('bg-' + color);
|
||||
const className = this.options.colorPrefix + color;
|
||||
if (this.options.targetClasses.includes(className)) {
|
||||
$color.addClass('bg-' + colorName);
|
||||
if (this.options.selectedColor && (this.options.selectedColor === colorName || this.options.selectedColor === color)) {
|
||||
$color.addClass('selected');
|
||||
}
|
||||
this.classes.push(className);
|
||||
this.colorNames.push(colorName);
|
||||
});
|
||||
|
||||
return res;
|
||||
},
|
||||
/**
|
||||
* Return a list of the color classes used in the color palette
|
||||
* Return a list of the color names used in the color palette
|
||||
*/
|
||||
getClasses: function () {
|
||||
return this.classes;
|
||||
},
|
||||
/**
|
||||
* Reloads the color palette to get other custom colors on the page
|
||||
*/
|
||||
reloadColorPalette: function () {
|
||||
this._buildCustomColors();
|
||||
getColorNames: function () {
|
||||
return this.colorNames;
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -215,10 +206,9 @@ const ColorPaletteWidget = Widget.extend({
|
||||
*/
|
||||
_getButtonInfo: function (buttonEl) {
|
||||
const bgColor = buttonEl.style.backgroundColor;
|
||||
const cssColor = bgColor ? ColorpickerDialog.normalizeCSSColor(bgColor) : (this.options.colorPrefix + buttonEl.dataset.color);
|
||||
const color = bgColor ? ColorpickerDialog.normalizeCSSColor(bgColor) : buttonEl.dataset.color;
|
||||
return {
|
||||
cssColor: cssColor,
|
||||
isClass: !!buttonEl.dataset.color,
|
||||
color: color,
|
||||
target: buttonEl,
|
||||
};
|
||||
},
|
||||
@@ -263,8 +253,7 @@ const ColorPaletteWidget = Widget.extend({
|
||||
params = this._getButtonInfo(selected);
|
||||
} else {
|
||||
params = {
|
||||
cssColor: '',
|
||||
isClass: false,
|
||||
color: '',
|
||||
};
|
||||
}
|
||||
params.target = ev.target;
|
||||
@@ -297,8 +286,7 @@ const ColorPaletteWidget = Widget.extend({
|
||||
colorpicker.on('colorpicker:saved', this, ev => {
|
||||
this._addCustomColorButton(ev.data.cssColor, ['selected']);
|
||||
this.trigger_up('color_picked', {
|
||||
cssColor: ev.data.cssColor,
|
||||
isClass: false,
|
||||
color: ev.data.cssColor,
|
||||
target: target,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
/// This file regroups basic style rules for web_editor enable page edition and backend utils.
|
||||
///
|
||||
|
||||
:root {
|
||||
@each $color, $value in $grays {
|
||||
--#{$color}: #{$value};
|
||||
}
|
||||
}
|
||||
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -297,26 +297,6 @@ body.editor_enable.editor_has_snippets {
|
||||
@include we-icon-button('\f107');
|
||||
}
|
||||
|
||||
we-row {
|
||||
display: block;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * {
|
||||
flex: 1 1 auto;
|
||||
|
||||
+ * {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
> .fa, > .fas, > .fab, > .far {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
we-select {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -374,13 +354,8 @@ body.editor_enable.editor_has_snippets {
|
||||
}
|
||||
|
||||
we-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@extend we-row.o_we_inline;
|
||||
|
||||
> we-title {
|
||||
min-width: 60%;
|
||||
margin-right: 5%;
|
||||
}
|
||||
> input {
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
@@ -398,11 +373,47 @@ body.editor_enable.editor_has_snippets {
|
||||
}
|
||||
}
|
||||
|
||||
we-row we-input {
|
||||
flex-wrap: wrap;
|
||||
we-row {
|
||||
position: relative;
|
||||
display: block;
|
||||
|
||||
> we-title {
|
||||
min-width: 95%;
|
||||
> div {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * {
|
||||
flex: 1 1 auto;
|
||||
|
||||
+ * {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
> .fa, > .fas, > .fab, > .far {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_we_inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> we-title {
|
||||
min-width: 60%;
|
||||
margin-right: 5%;
|
||||
}
|
||||
}
|
||||
|
||||
we-select {
|
||||
position: static;
|
||||
}
|
||||
|
||||
we-input {
|
||||
flex-wrap: wrap;
|
||||
|
||||
> we-title {
|
||||
min-width: 95%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,9 @@ MockServer.include({
|
||||
' <div data-js="content" data-selector=".s_hr, .test_option_all" ' +
|
||||
'data-drop-in=".note-editable" data-drop-near="p, h1, h2, h3, blockquote, .s_hr"></div>' +
|
||||
' <div data-js="sizing_y" data-selector=".s_hr, .test_option_all"></div>' +
|
||||
' <div data-js="colorpicker" string="Background Color" data-selector=".test_option_all"></div>' +
|
||||
' <div data-selector=".test_option_all">' +
|
||||
' <we-colorpicker string="Background Color" data-select-style="true" data-css-property="background-color" data-color-prefix="bg-"/>' +
|
||||
' </div>' +
|
||||
' <div data-js="background" data-selector=".test_option_all">' +
|
||||
' <we-button data-choose-image="true" data-no-preview="true"><i class="far fa-image"/> Background Image</we-button>' +
|
||||
' </div>' +
|
||||
@@ -245,7 +247,9 @@ function wysiwygData(data) {
|
||||
' <div data-js="content" data-selector=".s_hr, .test_option_all" ' +
|
||||
'data-drop-in=".note-editable" data-drop-near="p, h1, h2, h3, blockquote, .s_hr"></div>' +
|
||||
' <div data-js="sizing_y" data-selector=".s_hr, .test_option_all"></div>' +
|
||||
' <div data-js="colorpicker" string="Background Color" data-selector=".test_option_all"></div>' +
|
||||
' <div data-selector=".test_option_all">' +
|
||||
' <we-colorpicker string="Background Color" data-select-style="true" data-css-property="background-color" data-color-prefix="bg-"/>' +
|
||||
' </div>' +
|
||||
' <div data-js="background" data-selector=".test_option_all">' +
|
||||
' <we-button data-choose-image="true" data-no-preview="true"><i class="far fa-image"/> Background Image</we-button>' +
|
||||
' </div>' +
|
||||
|
||||
@@ -1541,7 +1541,7 @@ options.registry.topMenuTransparency = options.Class.extend({
|
||||
},
|
||||
});
|
||||
|
||||
options.registry.topMenuColor = options.registry.colorpicker.extend({
|
||||
options.registry.topMenuColor = options.Class.extend({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,7 @@ var Widget = require('web.Widget');
|
||||
var weWidgets = require('wysiwyg.widgets');
|
||||
var websiteNavbarData = require('website.navbar');
|
||||
var ColorPaletteDialog = require('web_editor.ColorPalette').ColorPaletteDialog;
|
||||
const ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -518,13 +519,14 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
var colorpicker = new ColorPaletteDialog(self, {
|
||||
resetButton: false,
|
||||
defaultColor: $color.css('background-color'),
|
||||
excluded: ['transparent_grayscale'],
|
||||
excludeSectionOf: colorName,
|
||||
});
|
||||
var chosenColor = undefined;
|
||||
colorpicker.on('color_picked', self, function (ev) {
|
||||
ev.stopPropagation();
|
||||
chosenColor = ev.data.cssColor;
|
||||
chosenColor = ev.data.color;
|
||||
if (!ColorpickerDialog.isCSSColor(chosenColor)) {
|
||||
chosenColor = ColorpickerDialog.normalizeCSSColor(self.style.getPropertyValue('--' + chosenColor).trim());
|
||||
}
|
||||
colorpicker.close();
|
||||
});
|
||||
colorpicker.on('closed', self, function (ev) {
|
||||
|
||||
@@ -982,25 +982,39 @@
|
||||
<t t-call="web_editor.snippet_options"/>
|
||||
|
||||
<!-- COLOR | .s_three_columns | .s_comparisons -->
|
||||
<div data-js="colorpicker" string="Color"
|
||||
data-selector=".s_three_columns .row > div, .s_comparisons .row > div, .s_tabs .row > div"
|
||||
data-target=".card"/>
|
||||
<div data-selector=".s_three_columns .row > div, .s_comparisons .row > div, .s_tabs .row > div"
|
||||
data-target=".card">
|
||||
<we-colorpicker string="Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"/>
|
||||
</div>
|
||||
|
||||
<!-- COLOR | .s_hr -->
|
||||
<div data-js="colorpicker" string="Color"
|
||||
data-selector=".s_hr"
|
||||
data-target="hr"
|
||||
data-color-prefix="border-"
|
||||
data-palette-exclude="transparent_grayscale, common, custom"/>
|
||||
<div data-selector=".s_hr"
|
||||
data-target="hr">
|
||||
<we-colorpicker string="Color"
|
||||
data-select-style="true"
|
||||
data-css-property="border-color"
|
||||
data-color-prefix="border-"
|
||||
data-excluded="transparent_grayscale"/>
|
||||
</div>
|
||||
|
||||
<!-- COLOR | .s_cards -->
|
||||
<div data-js="colorpicker" string="Color"
|
||||
data-selector=".s_card, .accordion .card"/>
|
||||
<div data-selector=".s_card, .accordion .card">
|
||||
<we-colorpicker string="Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"/>
|
||||
</div>
|
||||
|
||||
<!-- COLOR | .s_alert -->
|
||||
<div data-js="colorpicker" string="Color"
|
||||
data-selector=".s_alert"
|
||||
data-color-prefix="alert-"/>
|
||||
<div data-selector=".s_alert">
|
||||
<we-colorpicker string="Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="alert-"/>
|
||||
</div>
|
||||
|
||||
<!-- STYLES | .s_title -->
|
||||
<div data-selector=".s_title" data-target="[class*='s_title_']">
|
||||
@@ -1259,25 +1273,39 @@
|
||||
</div>
|
||||
|
||||
<!-- Color | Section -->
|
||||
<div id="so_main_colorpicker" string="Background Color"
|
||||
data-js="colorpicker"
|
||||
data-selector="section, .carousel-item"
|
||||
data-exclude=".parallax, .o_gallery .carousel-item"/>
|
||||
<div id="so_main_colorpicker"
|
||||
data-selector="section, .carousel-item"
|
||||
data-exclude=".parallax, .o_gallery .carousel-item">
|
||||
<we-colorpicker string="Background Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"/>
|
||||
</div>
|
||||
|
||||
<!-- FILTER | .s_parallax -->
|
||||
<div data-js="colorpicker" string="Filter"
|
||||
data-selector=".parallax"
|
||||
data-palette-exclude="common, theme, custom"
|
||||
data-palette-default="transparent_grayscale"/>
|
||||
<div data-selector=".parallax">
|
||||
<we-colorpicker string="Filter"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"
|
||||
data-excluded="common, theme, custom"/>
|
||||
</div>
|
||||
|
||||
<!-- Color | Columns -->
|
||||
<div data-js="colorpicker" string="Background Color"
|
||||
data-selector="section .row > div"
|
||||
data-exclude=".s_col_no_bgcolor, .s_col_no_bgcolor.row > div, .o_gallery .row > div"/>
|
||||
<div data-selector="section .row > div"
|
||||
data-exclude=".s_col_no_bgcolor, .s_col_no_bgcolor.row > div, .o_gallery .row > div">
|
||||
<we-colorpicker string="Background Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"/>
|
||||
</div>
|
||||
|
||||
<div data-selector="section .row > div"
|
||||
data-exclude=".s_col_no_bgcolor, .s_col_no_bgcolor.row > div, .o_gallery .row > div">
|
||||
<we-input string="Border" data-select-style="0" data-css-property="border-width" data-unit="px" data-extra-class="border"/>
|
||||
<we-row string="Border" class="o_we_inline">
|
||||
<we-colorpicker data-select-style="true" data-css-property="border-color" data-color-prefix="border-"/>
|
||||
<we-input data-select-style="0" data-css-property="border-width" data-unit="px" data-extra-class="border"/>
|
||||
</we-row>
|
||||
<we-input string="Rounded" data-select-style="0" data-css-property="border-radius" data-unit="px" data-extra-class="rounded"/>
|
||||
<we-checkbox string="Shadow" data-select-class="shadow"/>
|
||||
</div>
|
||||
@@ -1321,11 +1349,14 @@
|
||||
<we-checkbox string="Transparent" data-transparent="true" data-no-preview="true"/>
|
||||
</div>
|
||||
|
||||
<div data-js="topMenuColor" string="Background Color"
|
||||
data-selector="[data-main-object^='website.page('] #wrapwrap > header"
|
||||
data-palette-exclude="theme,common, custom"
|
||||
data-palette-default="transparent_grayscale"
|
||||
data-no-check="true">
|
||||
<div data-js="topMenuColor"
|
||||
data-selector="[data-main-object^='website.page('] #wrapwrap > header"
|
||||
data-no-check="true">
|
||||
<we-colorpicker string="Background Color"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"
|
||||
data-excluded="theme, common, custom"/>
|
||||
</div>
|
||||
|
||||
<!-- Anchor Name -->
|
||||
|
||||
Reference in New Issue
Block a user