[IMP] web_editor: move icon and image tools to snippet option
Wherever there is a sidebar, this moves all icon and image options to their own section of it. This also enables previews. The "spin" option was deemed unnecessary and therefore removed. TODO: restore the link option for icons. It wasn't working properly before this and was removed until it is fixed so as not to do any unnecessary coding for a broken option. closes odoo/odoo#70952 Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
@@ -3010,7 +3010,9 @@ var SnippetsMenu = Widget.extend({
|
||||
const range = selection && selection.rangeCount && selection.getRangeAt(0);
|
||||
if (!range ||
|
||||
!$(range.commonAncestorContainer).parents('#wrapwrap, .iframe-editor-wrapper .o_editable').length ||
|
||||
$(range.commonAncestorContainer).parent('[data-oe-model]:not([data-oe-type="html"]):not([data-oe-field="arch"])').length
|
||||
$(range.commonAncestorContainer).parent('[data-oe-model]:not([data-oe-type="html"]):not([data-oe-field="arch"])').length ||
|
||||
(e && $(e.target).closest('.fa, img').length ||
|
||||
this.options.wysiwyg.lastMediaClicked && $(this.options.wysiwyg.lastMediaClicked).is('.fa, img'))
|
||||
) {
|
||||
$toolbarContainer.hide();
|
||||
} else {
|
||||
|
||||
@@ -4154,6 +4154,203 @@ registry.ReplaceMedia = SnippetOptionWidget.extend({
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* General options that are common to a font awesome icon and an image.
|
||||
*/
|
||||
registry.StaticMediaTools = SnippetOptionWidget.extend({
|
||||
currentShapes: {},
|
||||
alignments: {
|
||||
left: ['float-left'],
|
||||
center: ['d-block', 'mx-auto'],
|
||||
right: ['float-right'],
|
||||
},
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
toggleShapeRounded(previewMode) {
|
||||
this._toggleShape(previewMode, 'rounded');
|
||||
},
|
||||
toggleShapeCircle(previewMode) {
|
||||
this._toggleShape(previewMode, 'rounded-circle');
|
||||
},
|
||||
toggleShapeShadow(previewMode) {
|
||||
this._toggleShape(previewMode, 'shadow');
|
||||
},
|
||||
toggleShapeThumbnail(previewMode) {
|
||||
this._toggleShape(previewMode, 'img-thumbnail');
|
||||
},
|
||||
setPadding(previewMode, padding, params) {
|
||||
if (previewMode === true) {
|
||||
this.currentPadding = params.possibleValues.find(c => this.$target.hasClass(c)) || '';
|
||||
}
|
||||
for (const value of params.possibleValues) {
|
||||
if (previewMode === 'reset') {
|
||||
this.$target.toggleClass(value, value === this.currentPadding);
|
||||
} else {
|
||||
this.$target.toggleClass(value, value === padding)
|
||||
}
|
||||
}
|
||||
if (previewMode === false) {
|
||||
this.currentPadding = padding;
|
||||
}
|
||||
},
|
||||
align(previewMode, alignment, params) {
|
||||
if (previewMode === true) {
|
||||
this.currentAlignment = this._getAlignment();
|
||||
}
|
||||
const targetAlignment = previewMode === 'reset' ? this.currentAlignment : alignment;
|
||||
for (const value of params.possibleValues) {
|
||||
this.$target.toggleClass(this.alignments[value] || '', value === targetAlignment);
|
||||
}
|
||||
if (previewMode === false) {
|
||||
this.currentAlignment = alignment;
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_computeWidgetState(methodName, params) {
|
||||
if (['toggleShapeRounded', 'toggleShapeCircle', 'toggleShapeShadow', 'toggleShapeThumbnail'].includes(methodName)) {
|
||||
return params.possibleValues.find(c => this.$target.hasClass(c)) || '';
|
||||
} else if (methodName === 'setPadding') {
|
||||
return params.possibleValues.find(c => this.$target.hasClass(c)) || '';
|
||||
} else if (methodName === 'align') {
|
||||
return this._getAlignment();
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
_getAlignment() {
|
||||
for (const [alignment, [alignClass]] of Object.entries(this.alignments)) {
|
||||
if (this.$target.hasClass(alignClass)) {
|
||||
return alignment;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
},
|
||||
_toggleShape(previewMode, shape) {
|
||||
if (previewMode === true) {
|
||||
this.currentShapes[shape] = this.$target.hasClass(shape);
|
||||
this.$target.toggleClass(shape, true);
|
||||
} else if (previewMode === 'reset') {
|
||||
this.$target.toggleClass(shape, this.currentShapes[shape]);
|
||||
} else if (previewMode === false) {
|
||||
this.$target.toggleClass(shape, !this.currentShapes[shape]);
|
||||
this.currentShapes[shape] = this.$target.hasClass(shape);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* General options of a font awesome icon.
|
||||
*/
|
||||
registry.FontawesomeTools = SnippetOptionWidget.extend({
|
||||
setSize(previewMode, size, params) {
|
||||
if (previewMode === true) {
|
||||
this.currentSize = params.possibleValues.find(c => this.$target.hasClass(c)) || '';
|
||||
}
|
||||
for (const value of params.possibleValues) {
|
||||
if (previewMode === 'reset') {
|
||||
this.$target.toggleClass(value, value === this.currentSize);
|
||||
} else {
|
||||
this.$target.toggleClass(value, value === size)
|
||||
}
|
||||
}
|
||||
if (previewMode === false) {
|
||||
this.currentSize = size;
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_computeWidgetState(methodName, params) {
|
||||
if (methodName === 'setSize') {
|
||||
return params.possibleValues.find(c => this.$target.hasClass(c)) || '';
|
||||
} else if (methodName === 'align') {
|
||||
return this._getAlignment();
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* General options of an image.
|
||||
*/
|
||||
registry.ImageTools = SnippetOptionWidget.extend({
|
||||
setWidth(previewMode, width, params) {
|
||||
if (previewMode === true) {
|
||||
this.currentWidth = this.$target.css('width');
|
||||
}
|
||||
if (previewMode === 'reset') {
|
||||
this.$target.css('width', this.currentWidth);
|
||||
} else {
|
||||
this.$target.css('width', width);
|
||||
}
|
||||
if (previewMode === false) {
|
||||
this.currentWidth = width;
|
||||
}
|
||||
},
|
||||
setAlt(previewMode, alt) {
|
||||
this.$target.attr('alt', alt);
|
||||
},
|
||||
setTitle(previewMode, title) {
|
||||
this.$target.attr('title', title);
|
||||
},
|
||||
crop() {
|
||||
new weWidgets.ImageCropWidget(this, this.$target[0]).appendTo(this.options.wysiwyg.$editable);
|
||||
},
|
||||
transform() {
|
||||
if (this.$target.data('transfo-destroy')) {
|
||||
this.$target.removeData('transfo-destroy');
|
||||
return;
|
||||
}
|
||||
const document = this.$target[0].ownerDocument
|
||||
this.$target.transfo({ document });
|
||||
const mousedown = mousedownEvent => {
|
||||
if (!$(mousedownEvent.target).closest('.transfo-container').length) {
|
||||
this.$target.transfo('destroy');
|
||||
$(document).off('mousedown', mousedown);
|
||||
}
|
||||
if ($(mousedownEvent.target).closest('#image-transform').length) {
|
||||
this.$target
|
||||
.data('transfo-destroy', true)
|
||||
.attr('style', (this.$target.attr('style') || '')
|
||||
.replace(/[^;]*transform[\w:]*;?/g, ''));
|
||||
}
|
||||
this.$target.trigger('content_changed');
|
||||
};
|
||||
$(document).on('mousedown', mousedown);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_computeWidgetState(methodName, params) {
|
||||
if (methodName === 'setWidth') {
|
||||
return this.$target[0].style.width || '';
|
||||
} else if (methodName === 'setAlt') {
|
||||
return this.$target.attr('alt');
|
||||
} else if (methodName === 'setTitle') {
|
||||
return this.$target.attr('title');
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
||||
/*
|
||||
* Abstract option to be extended by the ImageOptimize and BackgroundOptimize
|
||||
* options that handles all the common parts.
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
odoo.define('wysiwyg.widgets.AltTools', function (require) {
|
||||
'use strict';
|
||||
|
||||
var core = require('web.core');
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
/**
|
||||
* Let users change the alt & title of a media.
|
||||
*/
|
||||
const AltTools = Widget.extend({
|
||||
template: 'wysiwyg.widgets.altTools',
|
||||
xmlDependencies: ['/web_editor/static/src/xml/wysiwyg.xml'],
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
init: function (parent, options, media, $button) {
|
||||
options = options || {};
|
||||
this._super(parent, _.extend({}, {
|
||||
title: _t("Change media description and tooltip")
|
||||
}, options));
|
||||
|
||||
this.$button = $button;
|
||||
this.media = media;
|
||||
const allEscQuots = /"/g;
|
||||
this.alt = ($(this.media).attr('alt') || "").replace(allEscQuots, '"');
|
||||
const title = $(this.media).attr('title') || $(this.media).data('original-title') || "";
|
||||
this.tag_title = (title).replace(allEscQuots, '"');
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: async function () {
|
||||
const def = await this._super.apply(this, arguments);
|
||||
this.$button.addClass('active');
|
||||
this.$el.find('#alt').on('input', this._onChange.bind(this));
|
||||
this.$el.find('#title').on('input', this._onChange.bind(this));
|
||||
return def;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
this.$button.removeClass('active');
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_onChange: function (ev) {
|
||||
const attributeName = ev.target.id;
|
||||
const $target = $(ev.target);
|
||||
const $media = $(this.media);
|
||||
const allNonEscQuots = /"/g;
|
||||
const value = $target.val();
|
||||
$media.attr(attributeName, value ? value.replace(allNonEscQuots, """) : null);
|
||||
$media.trigger('content_changed');
|
||||
this.final_data = this.media;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
return AltTools;
|
||||
});
|
||||
@@ -3,7 +3,6 @@ odoo.define('wysiwyg.widgets', function (require) {
|
||||
|
||||
var Dialog = require('wysiwyg.widgets.Dialog');
|
||||
var AltDialog = require('wysiwyg.widgets.AltDialog');
|
||||
var AltTools = require('wysiwyg.widgets.AltTools');
|
||||
var MediaDialog = require('wysiwyg.widgets.MediaDialog');
|
||||
var LinkDialog = require('wysiwyg.widgets.LinkDialog');
|
||||
var LinkTools = require('wysiwyg.widgets.LinkTools');
|
||||
@@ -16,7 +15,6 @@ var media = require('wysiwyg.widgets.media');
|
||||
return {
|
||||
Dialog: Dialog,
|
||||
AltDialog: AltDialog,
|
||||
AltTools: AltTools,
|
||||
MediaDialog: MediaDialog,
|
||||
LinkDialog: LinkDialog,
|
||||
LinkTools: LinkTools,
|
||||
|
||||
@@ -523,28 +523,6 @@ const Wysiwyg = Widget.extend({
|
||||
observerData.observer.disconnect();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Toggle the Alt tools in the toolbar to edit <img> alt and title attributes.
|
||||
*
|
||||
* @param {object} params
|
||||
* @param {Node} [params.node]
|
||||
*/
|
||||
toggleAltTools(params) {
|
||||
const image = (params && params.node) || this.lastMediaClicked;
|
||||
if (this.snippetsMenu) {
|
||||
if (this.altTools) {
|
||||
this.altTools.destroy();
|
||||
this.altTools = undefined;
|
||||
} else {
|
||||
const $btn = this.toolbar.$el.find('#media-description');
|
||||
this.altTools = new weWidgets.AltTools(this, params, image, $btn);
|
||||
this.altTools.appendTo(this.toolbar.$el);
|
||||
}
|
||||
} else {
|
||||
const altDialog = new weWidgets.AltDialog(this, params, image);
|
||||
altDialog.open();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Toggle the Link tools/dialog to edit links. If a snippet menu is present,
|
||||
* use the link tools, otherwise use the dialog.
|
||||
@@ -686,7 +664,7 @@ const Wysiwyg = Widget.extend({
|
||||
this.openMediaDialog();
|
||||
break;
|
||||
case 'media-description':
|
||||
this.toggleAltTools();
|
||||
new weWidgets.AltDialog(this, {}, this.lastMediaClicked).open();
|
||||
break;
|
||||
}
|
||||
};
|
||||
@@ -952,9 +930,6 @@ const Wysiwyg = Widget.extend({
|
||||
const $target = e ? editorWindow.$(e.target) : editorWindow.$();
|
||||
// Restore paragraph dropdown button's default ID.
|
||||
this.toolbar.$el.find('#mediaParagraphDropdownButton').attr('id', 'paragraphDropdownButton');
|
||||
// Remove the alt tools.
|
||||
this.altTools && this.altTools.destroy();
|
||||
this.altTools = undefined;
|
||||
// Hide the create-link button if the selection spans several blocks.
|
||||
const selection = this.odooEditor.document.getSelection();
|
||||
const range = selection.rangeCount && selection.getRangeAt(0);
|
||||
|
||||
@@ -79,34 +79,6 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Alt Tools (allows to change alt and title of page images) -->
|
||||
<t t-name="wysiwyg.widgets.altTools">
|
||||
<we-customizeblock-option>
|
||||
<we-row>
|
||||
<we-title
|
||||
title="'Alt tag' specifies an alternate text for an image, if the image cannot be displayed (slow connection, missing image, screen reader ...).">
|
||||
⌙ Description
|
||||
</we-title>
|
||||
<we-input class="o_we_user_value_widget">
|
||||
<div>
|
||||
<input id="alt" required="required" t-att-value="widget.alt" type="text"/>
|
||||
</div>
|
||||
</we-input>
|
||||
</we-row>
|
||||
<we-row>
|
||||
<we-title
|
||||
title="'Title tag' is shown as a tooltip when you hover the picture.">
|
||||
⌙ Tooltip
|
||||
</we-title>
|
||||
<we-input class="o_we_user_value_widget">
|
||||
<div>
|
||||
<input id="title" required="required" t-att-value="widget.tag_title" type="text"/>
|
||||
</div>
|
||||
</we-input>
|
||||
</we-row>
|
||||
</we-customizeblock-option>
|
||||
</t>
|
||||
|
||||
<!-- Media Dialog (allows to choose an img/pictogram/video) -->
|
||||
<div t-name="wysiwyg.widgets.media">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
|
||||
@@ -367,8 +367,7 @@
|
||||
|
||||
<!-- Replace a media -->
|
||||
<!-- TODO probably review this system once the new editor is merged to not duplicate the selector, etc -->
|
||||
<!-- TODO enable on span.fa, i.fa too but in current editor, this is problematic so best not waste more time for now -->
|
||||
<div data-js="ReplaceMedia" data-selector="img, .media_iframe_video">
|
||||
<div data-js="ReplaceMedia" data-selector="img, .media_iframe_video, span.fa, i.fa">
|
||||
<!-- Overlay button -->
|
||||
<we-button data-name="replace_media_overlay_opt" title="Replace" class="fa fa-refresh" data-replace-media="true" data-no-preview="true"/>
|
||||
<!-- Panel button-->
|
||||
@@ -377,6 +376,73 @@
|
||||
</we-row>
|
||||
</div>
|
||||
|
||||
<div data-js="FontawesomeTools" data-selector="span.fa, i.fa">
|
||||
<we-colorpicker string="Color"
|
||||
title="Color"
|
||||
data-select-style=""
|
||||
data-css-property="color"
|
||||
data-color-prefix="text-"/>
|
||||
|
||||
<we-colorpicker string="Background Color"
|
||||
title="Background Color"
|
||||
data-select-style=""
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"/>
|
||||
|
||||
<we-button-group string="Size">
|
||||
<we-button data-set-size="fa-1x" title="Size 1x">1x</we-button>
|
||||
<we-button data-set-size="fa-2x" title="Size 2x">2x</we-button>
|
||||
<we-button data-set-size="fa-3x" title="Size 3x">3x</we-button>
|
||||
<we-button data-set-size="fa-4x" title="Size 4x">4x</we-button>
|
||||
<we-button data-set-size="fa-5x" title="Size 5x">5x</we-button>
|
||||
</we-button-group>
|
||||
</div>
|
||||
|
||||
<div data-js="ImageTools" data-selector="img">
|
||||
<we-input class="o_we_large_input" string="Description" data-set-alt="" placeholder="Alt tag"
|
||||
title="'Alt tag' specifies an alternate text for an image, if the image cannot be displayed (slow connection, missing image, screen reader ...)."/>
|
||||
<we-input class="o_we_large_input" string="Tooltip" data-set-title="" placeholder="Title tag"
|
||||
title="'Title tag' is shown as a tooltip when you hover the picture."/>
|
||||
|
||||
<we-row string="Transform">
|
||||
<we-button data-crop="" data-no-preview="true" title="Crop Image"><i class="fa fa-crop"></i></we-button>
|
||||
<we-button data-transform="" data-no-preview="true" title="Transform the picture (click twice to reset transformation)">
|
||||
<i class="fa fa-object-ungroup"></i>
|
||||
</we-button>
|
||||
</we-row>
|
||||
|
||||
<we-button-group string="Width">
|
||||
<we-button data-set-width="" title="Resize Auto">Auto</we-button>
|
||||
<we-button data-set-width="25%" title="Resize Quarter">25%</we-button>
|
||||
<we-button data-set-width="50%" title="Resize Half">50%</we-button>
|
||||
<we-button data-set-width="100%" title="Resize Full">100%</we-button>
|
||||
</we-button-group>
|
||||
</div>
|
||||
|
||||
<div data-js="StaticMediaTools" data-selector="span.fa, i.fa, img">
|
||||
<we-select string="Alignment">
|
||||
<we-button data-align="" title="Unalign">None</we-button>
|
||||
<we-button data-align="left" title="Align Left">Left</we-button>
|
||||
<we-button data-align="center" title="Align Center">Center</we-button>
|
||||
<we-button data-align="right" title="Align Right">Right</we-button>
|
||||
</we-select>
|
||||
|
||||
<we-row string="Shape">
|
||||
<we-button data-toggle-shape-rounded="rounded" title="Shape: Rounded"><i class="fa fa-square fa-fw"></i></we-button>
|
||||
<we-button data-toggle-shape-circle="rounded-circle" title="Shape: Circle"><i class="fa fa-circle-o fa-fw"></i></we-button>
|
||||
<we-button data-toggle-shape-shadow="shadow" title="Shadow"><i class="fa fa-sun-o fa-fw"></i></we-button>
|
||||
<we-button data-toggle-shape-thumbnail="img-thumbnail" title="Shape: Thumbnail"><i class="fa fa-picture-o fa-fw"></i></we-button>
|
||||
</we-row>
|
||||
|
||||
<we-select string="Padding">
|
||||
<we-button data-set-padding="" title="Padding: None">None</we-button>
|
||||
<we-button data-set-padding="padding-small" title="Padding: Small">Small</we-button>
|
||||
<we-button data-set-padding="padding-medium" title="Padding: Medium">Medium</we-button>
|
||||
<we-button data-set-padding="padding-large" title="Padding: Large">Large</we-button>
|
||||
<we-button data-set-padding="padding-xl" title="Padding: XL">Extra Large</we-button>
|
||||
</we-select>
|
||||
</div>
|
||||
|
||||
<div data-js="ImageOptimize"
|
||||
data-selector="img">
|
||||
<t t-call="web_editor.snippet_options_image_optimization_widgets"/>
|
||||
|
||||
Reference in New Issue
Block a user