[IMP] web_editor, website: generalize colorpicker
Currently we have: - a colorpicker for background color of snippets - a colorpicker for foreground and background text (topbar) - a colorpicker for menu/footer/navbar/etc These 3 are separate colorpickers with different options. After this Commit All 3 will use the same color palette wich allow you to select theme color, common colors, custom color and transparent filter. Part of https://github.com/odoo/odoo/pull/38959 maintask-2066614 task-2087383
This commit is contained in:
@@ -18,6 +18,7 @@ var EditorMenuBar = Widget.extend({
|
||||
'click button[data-action=cancel]': '_onCancelClick',
|
||||
},
|
||||
custom_events: {
|
||||
request_editable: '_onRequestEditable',
|
||||
request_history_undo_record: '_onHistoryUndoRecordRequest',
|
||||
request_save: '_onSaveRequest',
|
||||
},
|
||||
@@ -324,6 +325,13 @@ var EditorMenuBar = Widget.extend({
|
||||
ev.stopPropagation();
|
||||
this.save(ev.data.reload).then(ev.data.onSuccess, ev.data.onFailure);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {OdooEvent} ev
|
||||
*/
|
||||
_onRequestEditable: function (ev) {
|
||||
ev.data.callback(this.rte.editable());
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,30 +1,17 @@
|
||||
odoo.define('web_editor.rte.summernote', function (require) {
|
||||
'use strict';
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
var Class = require('web.Class');
|
||||
const concurrency = require('web.concurrency');
|
||||
var core = require('web.core');
|
||||
var ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
var ColorPaletteWidget = require('web_editor.ColorPalette').ColorPaletteWidget;
|
||||
var mixins = require('web.mixins');
|
||||
var fonts = require('wysiwyg.fonts');
|
||||
var weContext = require('web_editor.context');
|
||||
var rte = require('web_editor.rte');
|
||||
var weWidgets = require('wysiwyg.widgets');
|
||||
|
||||
var QWeb = core.qweb;
|
||||
var _t = core._t;
|
||||
|
||||
ajax.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||
'model': 'ir.ui.view',
|
||||
'method': 'read_template',
|
||||
'args': ['web_editor.colorpicker'],
|
||||
'kwargs': {
|
||||
'context': weContext.get(),
|
||||
}
|
||||
}).then(function (data) {
|
||||
QWeb.add_template('<templates>' + data + '</templates>');
|
||||
});
|
||||
|
||||
// Summernote Lib (neek change to make accessible: method and object)
|
||||
var dom = $.summernote.core.dom;
|
||||
var range = $.summernote.core.range;
|
||||
@@ -35,106 +22,53 @@ var tplButton = renderer.getTemplate().button;
|
||||
var tplIconButton = renderer.getTemplate().iconButton;
|
||||
var tplDropdown = renderer.getTemplate().dropdown;
|
||||
|
||||
function _rgbToHex(cssColor) {
|
||||
var rgba = cssColor.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
|
||||
if (!rgba) {
|
||||
return cssColor;
|
||||
}
|
||||
if (rgba[4]) {
|
||||
return cssColor;
|
||||
}
|
||||
var hex = ColorpickerDialog.convertRgbToHex(
|
||||
parseInt(rgba[1]),
|
||||
parseInt(rgba[2]),
|
||||
parseInt(rgba[3])
|
||||
);
|
||||
if (!hex) {
|
||||
return cssColor; // TODO handle error
|
||||
}
|
||||
return hex.hex.toUpperCase();
|
||||
}
|
||||
var applyColor = function (target, eventName, color) {
|
||||
var layoutInfo = dom.makeLayoutInfo(target);
|
||||
$.summernote.pluginEvents[eventName](undefined, eventHandler.modules.editor, layoutInfo, color);
|
||||
};
|
||||
|
||||
// Update and change the popovers content, and add history button
|
||||
var fn_createPalette = renderer.createPalette;
|
||||
renderer.createPalette = function ($container, options) {
|
||||
fn_createPalette.call(this, $container, options);
|
||||
const $dropdownContent = $container.find(".colorPalette");
|
||||
// The editor's root widget can be website or web's root widget and cannot be properly retrieved...
|
||||
const parent = odoo.__DEBUG__.services['root.widget'];
|
||||
_.each($dropdownContent, elem => {
|
||||
const eventName = elem.dataset.eventName;
|
||||
let colorpicker = null;
|
||||
const mutex = new concurrency.MutexedDropPrevious();
|
||||
const $dropdown = $(elem).closest('.btn-group, .dropdown');
|
||||
let manualOpening = false;
|
||||
$dropdown.on('show.bs.dropdown', () => {
|
||||
if (manualOpening) {
|
||||
return true;
|
||||
}
|
||||
mutex.exec(() => {
|
||||
const oldColorpicker = colorpicker;
|
||||
const hookEl = oldColorpicker ? oldColorpicker.el : elem;
|
||||
|
||||
if (!QWeb.has_template('web_editor.colorpicker')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $clpicker = $(QWeb.render('web_editor.colorpicker'));
|
||||
|
||||
var groups;
|
||||
if ($clpicker.is("colorpicker")) {
|
||||
groups = _.map($clpicker.find('[data-name="theme"]'), function (el) {
|
||||
return $(el).find("button").empty();
|
||||
const r = range.create();
|
||||
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 custom_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) {
|
||||
oldColorpicker.destroy();
|
||||
}
|
||||
manualOpening = true;
|
||||
$dropdown.children('.dropdown-toggle').dropdown('show');
|
||||
manualOpening = false;
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
groups = [$clpicker.find("button").empty()];
|
||||
}
|
||||
|
||||
var html = "<h6 class='mt-2'>" + _t("Theme colors") + "</h6>" + _.map(groups, function ($group) {
|
||||
var $row = $("<div/>", {"class": "note-color-row mb8"}).append($group);
|
||||
var $after_breaks = $row.find(".o_small + :not(.o_small)");
|
||||
if ($after_breaks.length === 0) {
|
||||
$after_breaks = $row.find(":nth-child(8n+9)");
|
||||
}
|
||||
$after_breaks.addClass("o_clear");
|
||||
return $row[0].outerHTML;
|
||||
}).join("") + "<h6 class='mt-2'>" + _t("Common colors") + "</h6>";
|
||||
var $palettes = $container.find(".note-color .note-color-palette");
|
||||
$palettes.prepend(html);
|
||||
|
||||
// Find the custom colors which are used in the page and add them to the color palette
|
||||
var colors = [];
|
||||
var $editable = window.__EditorMenuBar_$editable || $();
|
||||
_.each($editable.find('[style*="color"]'), function (element) {
|
||||
if (element.style.color) {
|
||||
colors.push(element.style.color);
|
||||
}
|
||||
if (element.style.backgroundColor) {
|
||||
colors.push(element.style.backgroundColor);
|
||||
}
|
||||
});
|
||||
|
||||
var $customColorPalettes = $container.find('.note-color .note-custom-color-palette').append($('<div/>', {class: "note-color-row"}));
|
||||
var $customColorRows = $customColorPalettes.find('.note-color-row');
|
||||
_.each(_.uniq(colors), function (color) {
|
||||
var hexColor = _rgbToHex(color);
|
||||
if (_.indexOf(_.flatten(options.colors), hexColor) < 0) {
|
||||
// Create button for used custom color for backColor and foreColor both and add them into palette
|
||||
$customColorRows.append('<button type="button" class="o_custom_color" data-color="' + color + '" style="background-color:' + color + ';" />');
|
||||
}
|
||||
});
|
||||
|
||||
$palettes.push.apply($palettes, $customColorPalettes);
|
||||
|
||||
var $forePalette = $palettes.filter(":even").closest('li').addClass('note-palette');
|
||||
var $bgPalette = $palettes.filter(":odd").closest('li').addClass('note-palette');
|
||||
|
||||
$forePalette.add($bgPalette).find('.note-color-reset').remove();
|
||||
$forePalette.children().each(function () {
|
||||
var $reset = $('<div class="note-color-reset" data-event="foreColor" data-value="inherit"></div>').text(_t('Reset to default'));
|
||||
$(this).prepend($reset);
|
||||
})
|
||||
$bgPalette.children().each(function () {
|
||||
var $reset = $('<div class="note-color-reset" data-event="backColor" data-value="inherit"></div>').text(_t('Reset to default'));
|
||||
$(this).prepend($reset);
|
||||
})
|
||||
|
||||
var $fore = $forePalette.find("button:not(.note-color-btn)").addClass("note-color-btn");
|
||||
$fore.each(function () {
|
||||
var $el = $(this);
|
||||
var className = $el.hasClass('o_custom_color') ? $el.data('color') : 'text-' + $el.data('color');
|
||||
$el.attr('data-event', 'foreColor').attr('data-value', className).addClass($el.hasClass('o_custom_color') ? '' : 'bg-' + $el.data('color'));
|
||||
});
|
||||
|
||||
var $bg = $bgPalette.find("button:not(.note-color-btn)").addClass("note-color-btn");
|
||||
$bg.each(function () {
|
||||
var $el = $(this);
|
||||
var className = $el.hasClass('o_custom_color') ? $el.data('color') : 'bg-' + $el.data('color');
|
||||
$el.attr('data-event', 'backColor').attr('data-value', className).addClass($el.hasClass('o_custom_color') ? '' : className);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -291,8 +225,6 @@ eventHandler.modules.popover.button.update = function ($container, oStyle) {
|
||||
$(oStyle.image).addClass('o_we_selected_image');
|
||||
|
||||
if (dom.isImgFont(oStyle.image)) {
|
||||
$container.find('[data-event="customColor"][data-value="foreColor"]').attr('data-color', $(oStyle.image).css('color'));
|
||||
$container.find('[data-event="customColor"][data-value="backColor"]').attr('data-color', $(oStyle.image).css('background-color'));
|
||||
$container.find('.note-fore-color-preview > button').css('border-bottom-color', $(oStyle.image).css('color'));
|
||||
$container.find('.note-back-color-preview > button').css('border-bottom-color', $(oStyle.image).css('background-color'));
|
||||
|
||||
@@ -335,8 +267,6 @@ eventHandler.modules.popover.button.update = function ($container, oStyle) {
|
||||
|
||||
$(oStyle.image).trigger('attributes_change');
|
||||
} else {
|
||||
$container.find('[data-event="customColor"][data-value="foreColor"]').attr('data-color', oStyle.color);
|
||||
$container.find('[data-event="customColor"][data-value="backColor"]').attr('data-color', oStyle['background-color']);
|
||||
$container.find('.note-fore-color-preview > button').css('border-bottom-color', oStyle.color);
|
||||
$container.find('.note-back-color-preview > button').css('border-bottom-color', oStyle['background-color']);
|
||||
}
|
||||
@@ -505,25 +435,6 @@ $.summernote.pluginEvents.alt = function (event, editor, layoutInfo, sorted) {
|
||||
media: $selection.data('target'),
|
||||
});
|
||||
};
|
||||
$.summernote.pluginEvents.customColor = function (event, editor, layoutInfo, customColor) {
|
||||
var defaultColor = event.target.dataset.color;
|
||||
core.bus.trigger('color_picker_dialog_demand', {
|
||||
color: defaultColor === 'rgba(0, 0, 0, 0)' ? 'rgb(255, 0, 0)' : defaultColor,
|
||||
onSave: function (color) {
|
||||
var $palettes = $(event.currentTarget).find('.note-custom-color-palette > .note-color-row')
|
||||
.append(('<button type="button" class="note-color-btn" data-value="' + color + '" style="background-color:' + color + ';" />'));
|
||||
$palettes.filter(':odd').find('button:not([data-event])').attr('data-event', 'backColor');
|
||||
$palettes.filter(':even').find('button:not([data-event])').attr('data-event', 'foreColor');
|
||||
if (customColor === 'foreColor') {
|
||||
$(event.currentTarget).find('.note-fore-color-preview > button').css('border-bottom-color', color);
|
||||
$.summernote.pluginEvents.foreColor(event, editor, layoutInfo, color);
|
||||
} else {
|
||||
$(event.currentTarget).find('.note-back-color-preview > button').css('border-bottom-color', color);
|
||||
$.summernote.pluginEvents.backColor(event, editor, layoutInfo, color);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
$.summernote.pluginEvents.cropImage = function (event, editor, layoutInfo, sorted) {
|
||||
var $editable = layoutInfo.editable();
|
||||
var $selection = layoutInfo.handle().find('.note-control-selection');
|
||||
@@ -1142,7 +1053,6 @@ var SummernoteManager = Class.extend(mixins.EventDispatcherMixin, {
|
||||
this.setParent(parent);
|
||||
|
||||
core.bus.on('alt_dialog_demand', this, this._onAltDialogDemand);
|
||||
core.bus.on('color_picker_dialog_demand', this, this._onColorPickerDialogDemand);
|
||||
core.bus.on('crop_image_dialog_demand', this, this._onCropImageDialogDemand);
|
||||
core.bus.on('link_dialog_demand', this, this._onLinkDialogDemand);
|
||||
core.bus.on('media_dialog_demand', this, this._onMediaDialogDemand);
|
||||
@@ -1154,7 +1064,6 @@ var SummernoteManager = Class.extend(mixins.EventDispatcherMixin, {
|
||||
mixins.EventDispatcherMixin.destroy.call(this);
|
||||
|
||||
core.bus.off('alt_dialog_demand', this, this._onAltDialogDemand);
|
||||
core.bus.off('color_picker_dialog_demand', this, this._onColorPickerDialogDemand);
|
||||
core.bus.off('crop_image_dialog_demand', this, this._onCropImageDialogDemand);
|
||||
core.bus.off('link_dialog_demand', this, this._onLinkDialogDemand);
|
||||
core.bus.off('media_dialog_demand', this, this._onMediaDialogDemand);
|
||||
@@ -1187,27 +1096,6 @@ var SummernoteManager = Class.extend(mixins.EventDispatcherMixin, {
|
||||
}
|
||||
altDialog.open();
|
||||
},
|
||||
/**
|
||||
* Called when a demand to open a color picker dialog is received on the bus.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} data
|
||||
*/
|
||||
_onColorPickerDialogDemand: function (data) {
|
||||
if (data.__alreadyDone) {
|
||||
return;
|
||||
}
|
||||
data.__alreadyDone = true;
|
||||
var colorpicker = new ColorpickerDialog(this, {
|
||||
defaultColor: data.color,
|
||||
});
|
||||
if (data.onSave) {
|
||||
colorpicker.on('colorpicker:saved', this, function (ev) {
|
||||
data.onSave(ev.data.cssColor);
|
||||
});
|
||||
}
|
||||
colorpicker.open();
|
||||
},
|
||||
/**
|
||||
* Called when a demand to open a crop dialog is received on the bus.
|
||||
*
|
||||
|
||||
@@ -2,10 +2,11 @@ odoo.define('web_editor.snippets.options', function (require) {
|
||||
'use strict';
|
||||
|
||||
var core = require('web.core');
|
||||
var ColorPaletteWidget = require('web_editor.ColorPalette').ColorPaletteWidget;
|
||||
var Dialog = require('web.Dialog');
|
||||
var rte = require('web_editor.rte');
|
||||
var Widget = require('web.Widget');
|
||||
var weWidgets = require('wysiwyg.widgets');
|
||||
var summernoteCustomColors = require('web_editor.rte.summernote_custom_colors');
|
||||
|
||||
var qweb = core.qweb;
|
||||
var _t = core._t;
|
||||
@@ -1146,93 +1147,57 @@ registry['sizing_y'] = registry.sizing.extend({
|
||||
*/
|
||||
registry.colorpicker = SnippetOption.extend({
|
||||
xmlDependencies: ['/web_editor/static/src/xml/snippets.xml'],
|
||||
events: _.extend({}, SnippetOption.prototype.events || {}, {
|
||||
'click .colorpicker button': '_onColorButtonClick',
|
||||
'mouseenter .colorpicker button': '_onColorButtonEnter',
|
||||
'mouseleave .colorpicker button': '_onColorButtonLeave',
|
||||
'click .note-color-reset': '_onColorResetButtonClick',
|
||||
}),
|
||||
colorPrefix: 'bg-',
|
||||
custom_events: {
|
||||
color_picked: '_onColorPicked',
|
||||
custom_color_picked: '_onCustomColor',
|
||||
color_hover: '_onColorHovered',
|
||||
color_leave: '_onColorLeft',
|
||||
color_reset: '_onColorReset',
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
var self = this;
|
||||
var res = this._super.apply(this, arguments);
|
||||
|
||||
const options = {
|
||||
selectedColor: this.$target.css('background-color'),
|
||||
targetClasses: [...this.$target[0].classList],
|
||||
};
|
||||
const proms = [this._super(...arguments)];
|
||||
if (this.data.paletteExclude) {
|
||||
options.excluded = this.data.paletteExclude.replace(/ /g, '').split(',');
|
||||
}
|
||||
if (this.data.colorPrefix) {
|
||||
this.colorPrefix = this.data.colorPrefix;
|
||||
options.colorPrefix = this.data.colorPrefix;
|
||||
}
|
||||
this.colorPalette = new ColorPaletteWidget(this, options);
|
||||
proms.push(this.colorPalette.appendTo(this.$el.find('we-collapse')));
|
||||
|
||||
if (!this.$el.find('.colorpicker').length) {
|
||||
// TODO remove old UI's code that survived
|
||||
var $pt = $(qweb.render('web_editor.snippet.option.colorpicker'));
|
||||
var $clpicker = $(qweb.render('web_editor.colorpicker'));
|
||||
return Promise.all(proms);
|
||||
},
|
||||
|
||||
_.each($clpicker.find('.o_colorpicker_section'), function (elem) {
|
||||
$(elem).prepend("<div>" + elem.dataset.display + "</div>");
|
||||
});
|
||||
onFocus: function () {
|
||||
this.colorPalette.reloadColorPalette();
|
||||
},
|
||||
|
||||
// Retrieve excluded palettes list
|
||||
var excluded = [];
|
||||
if (this.data.paletteExclude) {
|
||||
excluded = this.data.paletteExclude.replace(/ /g, '').split(',');
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Remove excluded palettes
|
||||
_.each(excluded, function (exc) {
|
||||
$clpicker.find('[data-name="' + exc + '"]').remove();
|
||||
});
|
||||
|
||||
// Add common colors to palettes if not excluded
|
||||
if (!('common' in excluded)) {
|
||||
var $commonColorSection = $clpicker.find('[data-name="common"]');
|
||||
_.each(summernoteCustomColors, function (colorRow, i) {
|
||||
var $div = $('<div/>', {class: 'clearfix'}).appendTo($commonColorSection);
|
||||
if (i === 0) {
|
||||
// Ignore the summernote gray palette and use ours
|
||||
return;
|
||||
}
|
||||
_.each(colorRow, function (color) {
|
||||
$div.append('<button class="o_custom_color" style="background-color: ' + color + '" />');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$pt.find('.o_colorpicker_section_tabs').append($clpicker);
|
||||
this.$el.find('we-collapse').append($pt);
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
// TODO refactor in master
|
||||
// The primary and secondary are hardcoded here (but marked as hidden)
|
||||
// so they can be removed from snippets when selecting another color.
|
||||
// Normally, the chosable colors do not contain them, which prevents
|
||||
// them to be removed. Indeed, normally, the 'alpha' and 'beta' colors
|
||||
// (which are the same) are displayed instead... but not for all themes.
|
||||
var $colorpicker = this.$el.find('.colorpicker');
|
||||
$colorpicker.append($('<button/>', {'class': 'd-none', 'data-color': 'primary'}));
|
||||
$colorpicker.append($('<button/>', {'class': 'd-none', 'data-color': 'secondary'}));
|
||||
|
||||
var classes = [];
|
||||
this.$el.find('.colorpicker button').each(function () {
|
||||
var $color = $(this);
|
||||
var color = $color.data('color');
|
||||
if (!color) {
|
||||
return;
|
||||
}
|
||||
|
||||
$color.addClass('bg-' + color);
|
||||
var className = self.colorPrefix + color;
|
||||
if (self.$target.hasClass(className)) {
|
||||
$color.addClass('selected');
|
||||
}
|
||||
classes.push(className);
|
||||
});
|
||||
this.classes = classes.join(' ');
|
||||
|
||||
return res;
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -1245,28 +1210,26 @@ registry.colorpicker = SnippetOption.extend({
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorButtonClick: function (ev) {
|
||||
this.$el.find('.colorpicker button.selected').removeClass('selected');
|
||||
$(ev.currentTarget).addClass('selected');
|
||||
_onColorPicked: function () {
|
||||
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
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorButtonEnter: function (ev) {
|
||||
this.$target.removeClass(this.classes);
|
||||
var color = $(ev.currentTarget).data('color');
|
||||
if (color) {
|
||||
this.$target.addClass(this.colorPrefix + color);
|
||||
} else if ($(ev.target).hasClass('o_custom_color')) {
|
||||
this.$target
|
||||
.removeClass(this.classes)
|
||||
.css('background-color', ev.currentTarget.style.backgroundColor);
|
||||
}
|
||||
_onColorHovered: function (ev) {
|
||||
this._changeTargetColor(ev.data.cssColor, ev.data.isClass);
|
||||
this.$target.trigger('background-color-event', true);
|
||||
},
|
||||
/**
|
||||
@@ -1275,17 +1238,8 @@ registry.colorpicker = SnippetOption.extend({
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorButtonLeave: function (ev) {
|
||||
this.$target.removeClass(this.classes);
|
||||
this.$target.css('background-color', '');
|
||||
var $selected = this.$el.find('.colorpicker button.selected');
|
||||
if ($selected.length) {
|
||||
if ($selected.data('color')) {
|
||||
this.$target.addClass(this.colorPrefix + $selected.data('color'));
|
||||
} else if ($selected.hasClass('o_custom_color')) {
|
||||
this.$target.css('background-color', $selected.css('background-color'));
|
||||
}
|
||||
}
|
||||
_onColorLeft: function (ev) {
|
||||
this._changeTargetColor(ev.data.cssColor, ev.data.isClass);
|
||||
this.$target.trigger('background-color-event', 'reset');
|
||||
},
|
||||
/**
|
||||
@@ -1294,10 +1248,9 @@ registry.colorpicker = SnippetOption.extend({
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_onColorResetButtonClick: function () {
|
||||
this.$target.removeClass(this.classes).css('background-color', '');
|
||||
_onColorReset: function () {
|
||||
this._targetColorChange('');
|
||||
this.$target.trigger('content_changed');
|
||||
this.$el.find('.colorpicker button.selected').removeClass('selected');
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -983,33 +983,15 @@ renderer.tplButtonInfo.color = function (lang, options) {
|
||||
event: 'color',
|
||||
value: '{"backColor":"#B35E9B"}'
|
||||
});
|
||||
var foreColorItems = [
|
||||
'<li><div class="btn-group flex-column">',
|
||||
'<div class="note-color-palette" data-target-event="foreColor"></div>',
|
||||
'<h6 class="note-custom-color mt8" data-event="customColor" data-value="foreColor" title="' + lang.color.custom + '">',
|
||||
lang.color.custom + '</h6>',
|
||||
'<div class="note-custom-color-palette" data-target-event="foreColor"></div>',
|
||||
'</div></li>',
|
||||
];
|
||||
var backColorItems = [
|
||||
'<li><div class="btn-group flex-column">',
|
||||
'<div class="note-color-reset" data-event="backColor" data-value="inherit" title="' + lang.color.transparent + '">',
|
||||
lang.color.setTransparent + '</div>',
|
||||
'<div class="note-color-palette" data-target-event="backColor"></div>',
|
||||
'<h6 class="note-custom-color mt8" data-event="customColor" data-value="backColor" title="' + lang.color.custom + '">',
|
||||
lang.color.custom + '</h6>',
|
||||
'<div class="note-custom-color-palette" data-target-event="backColor"></div>',
|
||||
'</div></li>',
|
||||
];
|
||||
var foreColorButton = renderer.getTemplate().button(foreColorButtonLabel, {
|
||||
className: 'note-fore-color-preview mx-1',
|
||||
title: lang.color.foreground,
|
||||
dropdown: renderer.getTemplate().dropdown(foreColorItems)
|
||||
dropdown: renderer.getTemplate().dropdown('<li><div data-event-name="foreColor" class="colorPalette"/></li>'),
|
||||
});
|
||||
var backColorButton = renderer.getTemplate().button(backColorButtonLabel, {
|
||||
className: 'note-back-color-preview mx-1',
|
||||
title: lang.color.background,
|
||||
dropdown: renderer.getTemplate().dropdown(backColorItems)
|
||||
dropdown: renderer.getTemplate().dropdown('<li><div data-event-name="backColor" class="colorPalette"/></li>'),
|
||||
});
|
||||
return recentColorButton + foreColorButton + backColorButton;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
odoo.define('web_editor.ColorPalette', function (require) {
|
||||
'use strict';
|
||||
|
||||
const core = require('web.core');
|
||||
const ColorPickerDialog = require('web.ColorpickerDialog');
|
||||
const Dialog = require('web.Dialog');
|
||||
const Widget = require('web.Widget');
|
||||
const summernoteCustomColors = require('web_editor.rte.summernote_custom_colors');
|
||||
|
||||
const qweb = core.qweb;
|
||||
const _t = core._t;
|
||||
|
||||
let templatePromise;
|
||||
|
||||
const ColorPaletteWidget = Widget.extend({
|
||||
xmlDependencies: ['/web_editor/static/src/xml/snippets.xml'],
|
||||
template: 'web_editor.snippet.option.colorpicker',
|
||||
events: {
|
||||
'click button': '_onColorButtonClick',
|
||||
'mouseenter button': '_onColorButtonEnter',
|
||||
'mouseleave button': '_onColorButtonLeave',
|
||||
'click .o_colorpicker_reset': '_onColorResetButtonClick',
|
||||
'click .o_add_custom_color': '_onCustomColorButtonClick',
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*
|
||||
* @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 {JQuery} [options.$editable=$()] Editable content from which the custom colors are retrieved.
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
this._super.apply(this, arguments);
|
||||
this.summernoteCustomColorsArray = [].concat(...summernoteCustomColors).map((color) => this._convertHexToCssRgba(color));
|
||||
this.options = _.extend({
|
||||
selectedColor: false,
|
||||
targetClasses: [],
|
||||
colorPrefix: 'bg-',
|
||||
resetButton: true,
|
||||
excluded: [],
|
||||
$editable: $(),
|
||||
}, options || {});
|
||||
|
||||
this.trigger_up('request_editable', {callback: val => this.options.$editable = val});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
willStart: async function () {
|
||||
const res = this._super.apply(this, arguments);
|
||||
// We can call the colorPalette multiple times but only need 1 rpc
|
||||
if (!templatePromise && !qweb.has_template('web_editor.colorpicker')) {
|
||||
templatePromise = this._rpc({
|
||||
model: 'ir.ui.view',
|
||||
method: 'read_template',
|
||||
args: ['web_editor.colorpicker'],
|
||||
}).then(template => {
|
||||
return qweb.add_template('<templates>' + template + '</templates>');
|
||||
});
|
||||
}
|
||||
await templatePromise;
|
||||
return res;
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
const res = this._super.apply(this, arguments);
|
||||
|
||||
const $wrapper = this.$('.o_colorpicker_section_tabs');
|
||||
$(qweb.render('web_editor.colorpicker')).appendTo($wrapper);
|
||||
|
||||
this.el.querySelectorAll('.o_colorpicker_section').forEach(elem => {
|
||||
$(elem).prepend('<div>' + (elem.dataset.display || '') + '</div>');
|
||||
});
|
||||
|
||||
if (this.options.resetButton) {
|
||||
this.$('.o_colorpicker_reset').removeClass('d-none');
|
||||
}
|
||||
|
||||
// Remove excluded palettes
|
||||
_.each(this.options.excluded, function (exc) {
|
||||
$wrapper.find('[data-name="' + exc + '"]').remove();
|
||||
});
|
||||
|
||||
// Render common colors
|
||||
if (!this.options.excluded.includes('common')) {
|
||||
const $commonColorSection = this.$('[data-name="common"]');
|
||||
summernoteCustomColors.forEach((colorRow, i) => {
|
||||
if (i === 0) {
|
||||
return; // Ignore the summernote gray palette and use ours
|
||||
}
|
||||
const $div = $('<div/>', {class: 'clearfix'}).appendTo($commonColorSection);
|
||||
colorRow.forEach(color => {
|
||||
$div.append(this._createColorButton(color, ['o_common_color']));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Render custom colors
|
||||
this._buildCustomColor();
|
||||
|
||||
// TODO refactor in master
|
||||
// The primary and secondary are hardcoded here (but marked as hidden)
|
||||
// so they can be removed from snippets when selecting another color.
|
||||
// Normally, the chosable colors do not contain them, which prevents
|
||||
// them to be removed. Indeed, normally, the 'alpha' and 'beta' colors
|
||||
// (which are the same) are displayed instead... but not for all themes.
|
||||
this.$el.append($('<button/>', {'class': 'd-none', 'data-color': 'primary'}));
|
||||
this.$el.append($('<button/>', {'class': 'd-none', 'data-color': 'secondary'}));
|
||||
|
||||
// Compute class colors
|
||||
this.classes = [];
|
||||
this.el.querySelectorAll('button[data-color]').forEach(elem => {
|
||||
const color = elem.dataset.color;
|
||||
const $color = $(elem);
|
||||
$color.addClass('bg-' + color);
|
||||
const className = this.options.colorPrefix + color;
|
||||
if (this.options.targetClasses.includes(className)) {
|
||||
$color.addClass('selected');
|
||||
}
|
||||
this.classes.push(className);
|
||||
});
|
||||
|
||||
return res;
|
||||
},
|
||||
/**
|
||||
* Return a list of the color classes 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._buildCustomColor();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @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 => {
|
||||
const color = el.style.color || el.style.backgroundColor;
|
||||
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
|
||||
*/
|
||||
_addCustomColorButton: function (color, classes = []) {
|
||||
classes.push('o_custom_color');
|
||||
this._createColorButton(color, classes).appendTo(this.$('.o_colorpicker_section[data-name="theme"]'));
|
||||
},
|
||||
/**
|
||||
* Return a color button.
|
||||
*
|
||||
* @param {string} color Css rgb(a) string
|
||||
* @param {Array<string>} classes Classes added to the button
|
||||
*/
|
||||
_createColorButton: function (color, classes) {
|
||||
const cssColor = this._convertHexToCssRgba(color);
|
||||
const selectedColor = this.options.selectedColor && this._convertHexToCssRgba(this.options.selectedColor);
|
||||
if (selectedColor === cssColor) {
|
||||
classes.push('selected');
|
||||
}
|
||||
return $('<button/>', {
|
||||
class: classes.join(' '),
|
||||
style: 'background-color:' + color + ';',
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Return the hexadecimal css color as an rgb(a) css color: rgb((r, g, b) | rgba(r, g, b, a)
|
||||
*
|
||||
* @private
|
||||
* @param {string} hex Css hex string (#FFFFFF(FF))
|
||||
*/
|
||||
_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
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Called when a color button is clicked.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorButtonClick: function (ev) {
|
||||
const target = 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,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Called when a color button is entered.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_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,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Called when a color button is left.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorButtonLeave: function (ev) {
|
||||
ev.stopPropagation();
|
||||
let params = {
|
||||
cssColor: '',
|
||||
isClass: false,
|
||||
target: ev.target,
|
||||
};
|
||||
const selected = this.el.querySelector('button.selected');
|
||||
if (selected) {
|
||||
params = {
|
||||
cssColor: selected.style.backgroundColor || this.options.colorPrefix + selected.dataset.color,
|
||||
isClass: !!selected.dataset.color,
|
||||
target: ev.target,
|
||||
};
|
||||
}
|
||||
this.trigger_up('color_leave', params);
|
||||
},
|
||||
/**
|
||||
* Called when the color reset button is clicked.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onColorResetButtonClick: function (ev) {
|
||||
this.$('button.selected').removeClass('selected');
|
||||
this.trigger_up('color_reset', {
|
||||
target: ev.target,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Called when the custom color button is clicked.
|
||||
*
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onCustomColorButtonClick: async function (ev) {
|
||||
const originalEvent = ev;
|
||||
const $selected = this.$('button.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', {
|
||||
cssColor: ev.data.cssColor,
|
||||
target: originalEvent.target,
|
||||
});
|
||||
});
|
||||
colorpicker.open();
|
||||
},
|
||||
});
|
||||
|
||||
const ColorPaletteDialog = Dialog.extend({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
this.options = options;
|
||||
this._super(parent, {
|
||||
size: 'small',
|
||||
title: _t('Pick a color'),
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
const proms = [this._super(...arguments)];
|
||||
const colorPalette = new ColorPaletteWidget(this, this.options);
|
||||
proms.push(colorPalette.appendTo(this.$el));
|
||||
return Promise.all(proms);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
ColorPaletteWidget: ColorPaletteWidget,
|
||||
ColorPaletteDialog: ColorPaletteDialog,
|
||||
};
|
||||
});
|
||||
@@ -303,12 +303,14 @@ $o-theme-color-palette-number: 1;
|
||||
|
||||
// Greyscale transparent colours
|
||||
$o-transparent-grays: (
|
||||
'black-15': rgba(black, 0.15),
|
||||
'black-25': rgba(black, 0.25),
|
||||
'black-50': rgba(black, 0.5),
|
||||
'black-75': rgba(black, 0.75),
|
||||
'white-25': rgba(white, 0.25),
|
||||
'white-50': rgba(white, 0.5),
|
||||
'white-75': rgba(white, 0.75),
|
||||
'white-85': rgba(white, 0.85),
|
||||
) !default;
|
||||
$o-gray-color-palettes: (
|
||||
(
|
||||
|
||||
@@ -479,7 +479,7 @@ body.editor_enable.editor_has_snippets {
|
||||
.o_colorpicker_section {
|
||||
|
||||
> :first-child {
|
||||
margin: 8px 0 4px;
|
||||
margin: 4px 0;
|
||||
}
|
||||
button {
|
||||
position: relative;
|
||||
@@ -508,11 +508,13 @@ body.editor_enable.editor_has_snippets {
|
||||
}
|
||||
}
|
||||
|
||||
&[data-name="transparent_grayscale"] button {
|
||||
@include o-alpha-button-preview;
|
||||
&[data-name="transparent_grayscale"], &[data-name="theme"] {
|
||||
button {
|
||||
@include o-alpha-button-preview;
|
||||
|
||||
&::before, &::after {
|
||||
box-shadow: inherit;
|
||||
&::before, &::after {
|
||||
box-shadow: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,12 +37,16 @@
|
||||
|
||||
<!-- options -->
|
||||
<div t-name="web_editor.snippet.option.colorpicker" class="colorpicker">
|
||||
<div class="btn-group palette-reset">
|
||||
<div class="note-color-reset" data-event="foreColor" data-value="inherit" title="None" role="img" aria-label="No color">
|
||||
<i class="fa fa-ban"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="o_colorpicker_sections px-1 pb8">
|
||||
<div class="o_colorpicker_section">
|
||||
<a class="btn w-50 float-left o_colorpicker_reset d-none">
|
||||
<i class="fa fa-ban"/> Reset
|
||||
</a>
|
||||
<a class="btn w-50 o_add_custom_color" data-name="custom">
|
||||
<i class="fa fa-plus"/> Custom
|
||||
</a>
|
||||
</div>
|
||||
<div class="tab-content o_colorpicker_section_tabs"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -150,12 +150,20 @@ QUnit.module('web_editor', {}, function () {
|
||||
assert.strictEqual(range.sc, pText,
|
||||
"should select the text");
|
||||
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button:first'));
|
||||
async function openColorpicker(selector) {
|
||||
const $colorpicker = $field.find(selector);
|
||||
const openingProm = new Promise(resolve => {
|
||||
$colorpicker.one('shown.bs.dropdown', () => resolve());
|
||||
});
|
||||
await testUtils.dom.click($colorpicker.find('button:first'));
|
||||
return openingProm;
|
||||
}
|
||||
|
||||
await openColorpicker('.note-toolbar .note-back-color-preview');
|
||||
assert.ok($field.find('.note-back-color-preview').hasClass('show'),
|
||||
"should display the color picker");
|
||||
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[data-value="#00FFFF"]'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[style="background-color:#00FFFF;"]'));
|
||||
|
||||
assert.ok(!$field.find('.note-back-color-preview').hasClass('show'),
|
||||
"should close the color picker");
|
||||
@@ -180,8 +188,8 @@ QUnit.module('web_editor', {}, function () {
|
||||
Wysiwyg.setRange(fontContent, 5, pText, 2);
|
||||
// text is selected
|
||||
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button:first'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[data-value="bg-gamma"]'));
|
||||
await openColorpicker('.note-toolbar .note-back-color-preview');
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button.bg-gamma'));
|
||||
|
||||
assert.strictEqual($field.find('.note-editable').html(),
|
||||
'<p>t<font style="background-color: rgb(0, 255, 255);">oto t</font><font style="" class="bg-gamma">oto </font><font class="bg-gamma" style="">to</font>to</p><p>tata</p>',
|
||||
@@ -329,7 +337,7 @@ QUnit.module('web_editor', {}, function () {
|
||||
// text is selected
|
||||
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button:first'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[data-value="bg-gamma"]'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button.bg-gamma'));
|
||||
|
||||
await testUtils.form.clickSave(form);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/media.js"/>
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/dialog.js"/>
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/alt_dialog.js"/>
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/color_palette.js"/>
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/crop_dialog.js"/>
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/link_dialog.js"/>
|
||||
<script type="text/javascript" src="/web_editor/static/src/js/wysiwyg/widgets/media_dialog.js"/>
|
||||
@@ -204,38 +205,41 @@
|
||||
|
||||
Sections should contain a set of button with a data-color attribute. When selecting such a button to
|
||||
edit style, the "bg-x" class or the "text-x" will be automatically added.
|
||||
|
||||
If a color is no longer used you need to add the d-none class to it and not remove it from this file !!
|
||||
Else you will no longer be able to use them.
|
||||
-->
|
||||
<template id="web_editor.colorpicker" name="Color-Picker">
|
||||
<colorpicker>
|
||||
<div class="o_colorpicker_section" data-name="theme" data-display="Theme Colors" data-icon-class="fa fa-flask">
|
||||
<div class="o_colorpicker_section" data-name="theme">
|
||||
<button data-color="alpha"></button>
|
||||
<button data-color="beta"></button>
|
||||
<button data-color="gamma"></button>
|
||||
<button data-color="delta"></button>
|
||||
<button data-color="epsilon"></button>
|
||||
</div>
|
||||
<div class="o_colorpicker_section" data-name="transparent_grayscale" data-display="Transparent Colors" data-icon-class="fa fa-eye-slash">
|
||||
<button class="o_btn_transparent"></button>
|
||||
<div class="o_colorpicker_section" data-name="common">
|
||||
<button data-color="black"></button>
|
||||
<button data-color="900"></button>
|
||||
<button data-color="800"></button>
|
||||
<button data-color="700" class="d-none"></button>
|
||||
<button data-color="600"></button>
|
||||
<button data-color="500" class="d-none"></button>
|
||||
<button data-color="400"></button>
|
||||
<button data-color="300" class="d-none"></button>
|
||||
<button data-color="200"></button>
|
||||
<button data-color="100"></button>
|
||||
<button data-color="white"></button>
|
||||
</div>
|
||||
<div class="o_colorpicker_section" data-name="transparent_grayscale" data-display="Opacity Filters" data-icon-class="fa fa-eye-slash">
|
||||
<button data-color="black-15"></button>
|
||||
<button data-color="black-25"></button>
|
||||
<button data-color="black-50"></button>
|
||||
<button data-color="black-75"></button>
|
||||
<button data-color="white-25"></button>
|
||||
<button data-color="white-50"></button>
|
||||
<button data-color="white-75"></button>
|
||||
</div>
|
||||
<div class="o_colorpicker_section" data-name="common" data-display="Common Colors" data-icon-class="fa fa-paint-brush">
|
||||
<button data-color="black"></button>
|
||||
<button data-color="white"></button>
|
||||
<div class="clearfix"/>
|
||||
<button data-color="900"></button>
|
||||
<button data-color="800"></button>
|
||||
<button data-color="700"></button>
|
||||
<button data-color="600"></button>
|
||||
<button data-color="500"></button>
|
||||
<button data-color="400" class="d-none"></button><!-- Hide this one to be able to use it but not display it -->
|
||||
<button data-color="300"></button>
|
||||
<button data-color="200"></button>
|
||||
<button data-color="100"></button>
|
||||
<button data-color="white-85"></button>
|
||||
</div>
|
||||
</colorpicker>
|
||||
</template>
|
||||
|
||||
@@ -6,8 +6,8 @@ var core = require('web.core');
|
||||
var Dialog = require('web.Dialog');
|
||||
var Widget = require('web.Widget');
|
||||
var weWidgets = require('wysiwyg.widgets');
|
||||
var ColorpickerDialog = require('web.ColorpickerDialog');
|
||||
var websiteNavbarData = require('website.navbar');
|
||||
var ColorPaletteDialog = require('web_editor.ColorPalette').ColorPaletteDialog;
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -515,13 +515,16 @@ var ThemeCustomizeDialog = Dialog.extend({
|
||||
var colorType = $color.data('colorType');
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var colorpicker = new ColorpickerDialog(self, {
|
||||
var colorpicker = new ColorPaletteDialog(self, {
|
||||
resetButton: false,
|
||||
defaultColor: $color.css('background-color'),
|
||||
excluded: ['transparent_grayscale'],
|
||||
});
|
||||
var chosenColor = undefined;
|
||||
colorpicker.on('colorpicker:saved', self, function (ev) {
|
||||
colorpicker.on('color_picked custom_color_picked', self, function (ev) {
|
||||
ev.stopPropagation();
|
||||
chosenColor = ev.data.cssColor;
|
||||
colorpicker.close();
|
||||
});
|
||||
colorpicker.on('closed', self, function (ev) {
|
||||
if (chosenColor === undefined) {
|
||||
|
||||
@@ -996,7 +996,7 @@
|
||||
data-selector=".s_hr"
|
||||
data-target="hr"
|
||||
data-color-prefix="border-"
|
||||
data-palette-exclude="transparent_grayscale, common">
|
||||
data-palette-exclude="transparent_grayscale, common, custom">
|
||||
<we-collapse-area>
|
||||
<we-toggler>Color</we-toggler>
|
||||
<we-collapse/>
|
||||
@@ -1276,7 +1276,7 @@
|
||||
<!-- FILTER | .s_parallax -->
|
||||
<div data-js="colorpicker"
|
||||
data-selector=".parallax"
|
||||
data-palette-exclude="common, theme"
|
||||
data-palette-exclude="common, theme, custom"
|
||||
data-palette-default="transparent_grayscale">
|
||||
<we-collapse-area>
|
||||
<we-toggler>Filter</we-toggler>
|
||||
@@ -1342,7 +1342,7 @@
|
||||
|
||||
<div data-js="topMenuColor"
|
||||
data-selector="[data-main-object^='website.page('] #wrapwrap > header"
|
||||
data-palette-exclude="theme,common"
|
||||
data-palette-exclude="theme,common, custom"
|
||||
data-palette-default="transparent_grayscale"
|
||||
data-no-check="true">
|
||||
<we-collapse-area>
|
||||
|
||||
Reference in New Issue
Block a user