diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js index 5712d450473..f23d9981890 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -1302,7 +1302,7 @@ var SnippetEditor = Widget.extend({ gridUtils._resizeGrid(rowEl); } else if (this.$target[0].classList.contains('o_grid_item') && this.dropped) { // Case when dropping a grid item in a non-grid dropzone. - this.$target[0].classList.remove('o_grid_item', 'o_grid_item_image'); + this.$target[0].classList.remove('o_grid_item', 'o_grid_item_image', 'o_grid_item_image_contain'); this.$target[0].style.removeProperty('grid-area'); } @@ -1342,7 +1342,7 @@ var SnippetEditor = Widget.extend({ if (this.$target[0].classList.contains('o_grid_item')) { // Case when a grid column is dropped near a non-grid // dropzone. - this.$target[0].classList.remove('o_grid_item', 'o_grid_item_image'); + this.$target[0].classList.remove('o_grid_item', 'o_grid_item_image', 'o_grid_item_image_contain'); this.$target[0].style.removeProperty('z-index'); this.$target[0].style.removeProperty('grid-area'); } @@ -2656,6 +2656,7 @@ var SnippetsMenu = Widget.extend({ _computeSnippetTemplates: function (html) { var self = this; var $html = $(html); + this._patchForComputeSnippetTemplates($html); var $scroll = $html.siblings('#o_scroll'); this.templateOptions = []; @@ -2800,6 +2801,15 @@ var SnippetsMenu = Widget.extend({ this.$el.addClass('o_loaded'); $(this.el.ownerDocument.body).addClass('editor_has_snippets'); }, + /** + * Eases patching the XML definition for snippets and options in stable + * versions. Note: in the future, we will probably move to other ways to + * define snippets and options. + * + * @private + * @param {jQuery} + */ + _patchForComputeSnippetTemplates($html) {}, /** * Creates a snippet editor to associated to the given snippet. If the given * snippet already has a linked snippet editor, the function only returns diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index 8182b942662..e5adc663f4d 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -5143,7 +5143,7 @@ registry.layout_column = SnippetOptionWidget.extend({ gridUtils._reloadLazyImages(columnEl); // Removing the grid properties. - columnEl.classList.remove('o_grid_item', 'o_grid_item_image'); + columnEl.classList.remove('o_grid_item', 'o_grid_item_image', 'o_grid_item_image_contain'); columnEl.style.removeProperty('grid-area'); columnEl.style.removeProperty('z-index'); } diff --git a/addons/web_editor/static/src/scss/web_editor.frontend.scss b/addons/web_editor/static/src/scss/web_editor.frontend.scss index 5b6d081b2e5..d949eae7ea9 100644 --- a/addons/web_editor/static/src/scss/web_editor.frontend.scss +++ b/addons/web_editor/static/src/scss/web_editor.frontend.scss @@ -57,8 +57,15 @@ --gutter-x: 30px; } -.o_grid_item_image > img:not([data-shape]) { - width: 100% !important; - height: 100% !important; - object-fit: cover !important; +.o_grid_item_image { + > img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; + } + + &.o_grid_item_image_contain > img, + > img[data-shape] { + object-fit: contain !important; + } } diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 36d40a6a05a..daba07839f5 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -3612,6 +3612,61 @@ options.registry.SwitchableViews = options.Class.extend({ } }); +options.registry.GridImage = options.Class.extend({ + + //-------------------------------------------------------------------------- + // Options + //-------------------------------------------------------------------------- + + /** + * @see this.selectClass for parameters + */ + changeGridImageMode(previewMode, widgetValue, params) { + const imageGridItemEl = this._getImageGridItem(); + if (imageGridItemEl) { + imageGridItemEl.classList.toggle('o_grid_item_image_contain', widgetValue === 'contain'); + } + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Returns the parent column if it is marked as a grid item containing an + * image. + * + * @returns {?HTMLElement} + */ + _getImageGridItem() { + const parentEl = this.$target[0].parentNode; + if (parentEl && parentEl.classList.contains('o_grid_item_image')) { + return parentEl; + } + return null; + }, + /** + * @override + */ + _computeVisibility() { + return this._super(...arguments) + && !!this._getImageGridItem() + && !('shape' in this.$target[0].dataset); + }, + /** + * @override + */ + _computeWidgetState(methodName, params) { + if (methodName === 'changeGridImageMode') { + const imageGridItemEl = this._getImageGridItem(); + return imageGridItemEl && imageGridItemEl.classList.contains('o_grid_item_image_contain') + ? 'contain' + : 'cover'; + } + return this._super(...arguments); + }, +}); + return { UrlPickerUserValueWidget: UrlPickerUserValueWidget, FontFamilyPickerUserValueWidget: FontFamilyPickerUserValueWidget, diff --git a/addons/website/views/snippets/snippets.xml b/addons/website/views/snippets/snippets.xml index 693386c8ed2..0cb13b047de 100644 --- a/addons/website/views/snippets/snippets.xml +++ b/addons/website/views/snippets/snippets.xml @@ -1346,6 +1346,14 @@ + +