diff --git a/addons/web_editor/static/src/js/editor/editor.js b/addons/web_editor/static/src/js/editor/editor.js index c3a2e3de444..ea00a05af26 100644 --- a/addons/web_editor/static/src/js/editor/editor.js +++ b/addons/web_editor/static/src/js/editor/editor.js @@ -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 { 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 e63d87e54b2..913d35575ab 100644 --- a/addons/web_editor/static/src/js/editor/rte.summernote.js +++ b/addons/web_editor/static/src/js/editor/rte.summernote.js @@ -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('' + data + ''); -}); - // 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 = "
" + _t("Theme colors") + "
" + _.map(groups, function ($group) { - var $row = $("
", {"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("") + "
" + _t("Common colors") + "
"; - 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($('
', {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('