diff options
| author | Samuel Degueldre <sad@odoo.com> | 2019-10-24 13:15:55 +0000 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2019-11-18 09:56:40 +0000 |
| commit | dfd98f49e7f2ab5c94dcae3af2d14750d301fa0a (patch) | |
| tree | 80515984c7819fd3d80503ff54cf37a034c27c8a | |
| parent | 01debf53f676e415241e4b2db0087e30eb1f0e8e (diff) | |
[IMP] web_editor: rework background-sizing option
Previously, background size and position for snippets was configured in
a modal, the user could choose a "focus point", which is rather
unintuitive. They could also choose to use the "contain" background
mode, with or without repeat, or a third option, where they could
customize everything, from the background size in both directions to
whether to repeat the background in only one or in both directions.
This commit streamlines the background-sizing options, only the "cover"
and "repeat pattern" options have been kept, as they cover almost every
use case. Their configuration has been moved into the options menu for
consistency with the rest of the editor, and the background's position
is now chosen by clicking on the corresponding menu option, and dragging
the background to the desired place.
Part of https://github.com/odoo/odoo/pull/38959
maintask-2066614
task-2088304
| -rw-r--r-- | addons/web_editor/static/src/js/editor/snippets.options.js | 380 | ||||
| -rw-r--r-- | addons/web_editor/static/src/scss/wysiwyg_snippets.scss | 23 | ||||
| -rw-r--r-- | addons/web_editor/static/src/xml/editor.xml | 104 | ||||
| -rw-r--r-- | addons/website/static/src/js/editor/snippets.options.js | 2 | ||||
| -rw-r--r-- | addons/website/static/src/scss/website.scss | 11 | ||||
| -rw-r--r-- | addons/website/static/src/scss/website.wysiwyg.scss | 158 | ||||
| -rw-r--r-- | addons/website/views/snippets.xml | 15 |
7 files changed, 281 insertions, 412 deletions
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 1237c041bf1..49867305fa7 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -3,7 +3,6 @@ odoo.define('web_editor.snippets.options', function (require) { var core = require('web.core'); var ColorPaletteWidget = require('web_editor.ColorPalette').ColorPaletteWidget; -var Dialog = require('web.Dialog'); var Widget = require('web.Widget'); var weWidgets = require('wysiwyg.widgets'); @@ -1520,9 +1519,9 @@ registry.background = SnippetOption.extend({ }); /** - * Handles the edition of snippet's background image position. + * Handles the edition of snippets' background image position. */ -registry['background_position'] = SnippetOption.extend({ +registry.BackgroundPosition = SnippetOption.extend({ xmlDependencies: ['/web_editor/static/src/xml/editor.xml'], /** @@ -1530,16 +1529,36 @@ registry['background_position'] = SnippetOption.extend({ */ start: function () { this._super.apply(this, arguments); - var self = this; - this.$target.on('snippet-option-change', function () { - self.onFocus(); + + this._initOverlay(); + this.img = document.createElement('img'); + this.img.src = this._getSrcFromCssValue(); + + this.$target.on('snippet-option-change', () => { + // Hides option if the bg image is removed in favor of a bg color + this._updateUI(); + // this.img is used to compute dragging speed + this.img.src = this._getSrcFromCssValue(); }); + + // Resize overlay content on window resize because background images + // change size, and on carousel slide because they sometimes take up + // more space and move elements around them. + $(window).on('resize.bgposition', () => this._dimensionOverlay()); + }, + /** + * @override + */ + destroy: function () { + this._toggleBgOverlay(false); + $(window).off('.bgposition'); + this._super.apply(this, arguments); }, /** * @override */ onFocus: function () { - this.$el.toggleClass('d-none', this.$target.css('background-image') === 'none'); + this._updateUI(); }, //-------------------------------------------------------------------------- @@ -1547,77 +1566,31 @@ registry['background_position'] = SnippetOption.extend({ //-------------------------------------------------------------------------- /** - * Opens a Dialog to edit the snippet's backgroung image position. + * Sets the background type (cover/repeat pattern). * - * @see this.selectClass for parameters + * @see this.selectClass for params */ - backgroundPosition: function (previewMode, value, $opt) { - var self = this; - - this.previousState = [this.$target.attr('class'), this.$target.css('background-size'), this.$target.css('background-position')]; - - this.bgPos = self.$target.css('background-position').split(' '); - this.bgSize = self.$target.css('background-size').split(' '); - - this.modal = new Dialog(null, { - title: _t("Background Image Sizing"), - $content: $(qweb.render('web_editor.dialog.background_position')), - buttons: [ - {text: _t("Ok"), classes: 'btn-primary', close: true, click: _.bind(this._saveChanges, this)}, - {text: _t("Discard"), close: true, click: _.bind(this._discardChanges, this)}, - ], - }).open(); - - this.modal.opened().then(function () { - // Fetch data form $target - var value = ((self.$target.hasClass('o_bg_img_opt_contain')) ? 'contain' : ((self.$target.hasClass('o_bg_img_opt_custom')) ? 'custom' : 'cover')); - self.modal.$('> label > input[value=' + value + ']').prop('checked', true); - - if (self.$target.hasClass('o_bg_img_opt_repeat')) { - self.modal.$('#o_bg_img_opt_contain_repeat').prop('checked', true); - self.modal.$('#o_bg_img_opt_custom_repeat').val('o_bg_img_opt_repeat'); - } else if (self.$target.hasClass('o_bg_img_opt_repeat_x')) { - self.modal.$('#o_bg_img_opt_custom_repeat').val('o_bg_img_opt_repeat_x'); - } else if (self.$target.hasClass('o_bg_img_opt_repeat_y')) { - self.modal.$('#o_bg_img_opt_custom_repeat').val('o_bg_img_opt_repeat_y'); - } - - if (self.bgPos.length > 1) { - self.bgPos = { - x: self.bgPos[0], - y: self.bgPos[1], - }; - self.modal.$('#o_bg_img_opt_custom_pos_x').val(self.bgPos.x.replace('%', '')); - self.modal.$('#o_bg_img_opt_custom_pos_y').val(self.bgPos.y.replace('%', '')); - } - if (self.bgSize.length > 1) { - self.modal.$('#o_bg_img_opt_custom_size_x').val(self.bgSize[0].replace('%', '')); - self.modal.$('#o_bg_img_opt_custom_size_y').val(self.bgSize[1].replace('%', '')); - } - - // Focus Point - self.$focus = self.modal.$('.o_focus_point'); - self._updatePosInformation(); - - var imgURL = /\(['"]?([^'"]+)['"]?\)/g.exec(self.$target.css('background-image')); - imgURL = (imgURL && imgURL[1]) || ''; - var $img = $('<img/>', {class: 'img img-fluid', src: imgURL}); - $img.on('load', function () { - self._bindImageEvents($img); - }); - $img.prependTo(self.modal.$('.o_bg_img_opt_object')); + backgroundType: function (previewMode, value, $opt) { + this.$target.toggleClass('o_bg_img_opt_repeat', value === 'repeat-pattern'); + this.$target.css('background-position', ''); + this.$target.css('background-size', ''); + }, + /** + * Saves current background position and enables overlay. + * + * @see this.selectClass for params + */ + backgroundPositionOverlay: function (previewMode, value, $opt) { + const position = this.$target.css('background-position').split(' ').map(v => parseInt(v)); + // Convert % values to pixels (because mouse movement is in pixels) + const delta = this._getBackgroundDelta(); + this.originalPosition = { + left: position[0] / 100 * delta.x || 0, + top: position[1] / 100 * delta.y || 0, + }; + this.currentPosition = _.clone(this.originalPosition); - // Bind events - self.modal.$el.on('change', '> label > input', function (e) { - self.modal.$('> .o_bg_img_opt').addClass('o_hidden') - .filter('[data-value=' + e.target.value + ']') - .removeClass('o_hidden'); - }); - self.modal.$el.on('change', 'input, select', function (e) { - self._saveChanges(); - }); - self.modal.$('> label > input:checked').trigger('change'); - }); + this._toggleBgOverlay(true); }, //-------------------------------------------------------------------------- @@ -1625,116 +1598,219 @@ registry['background_position'] = SnippetOption.extend({ //-------------------------------------------------------------------------- /** - * Bind events on the given image so that the users can adapt the focus - * point. + * Initializes the overlay, binds events to the buttons, inserts it in + * the DOM. * * @private - * @param {jQuery} $img */ - _bindImageEvents: function ($img) { - var self = this; + _initOverlay: function () { + this.$backgroundOverlay = $(qweb.render('web_editor.background_position_overlay')); + this.$overlayContent = this.$backgroundOverlay.find('.o_we_overlay_content'); + this.$overlayBackground = this.$overlayContent.find('.o_overlay_background'); - var mousedown = false; - $img.on('mousedown', function (e) { - mousedown = true; + this.$backgroundOverlay.on('click', '.o_btn_apply', () => { + this.$target.css('background-position', this.$bgDragger.css('background-position')); + this._toggleBgOverlay(false); }); - $img.on('mousemove', function (e) { - if (mousedown) { - _update(e); - } + this.$backgroundOverlay.on('click', '.o_btn_discard', () => { + this._toggleBgOverlay(false); }); - $img.on('mouseup', function (e) { - self.$focus.addClass('o_with_transition'); - _update(e); - setTimeout(function () { - self.$focus.removeClass('o_with_transition'); - }, 200); - mousedown = false; + + this.$backgroundOverlay.insertAfter(this.$overlay); + }, + /** + * Sets the overlay in the right place so that the draggable background + * renders over the target, and size the background item like the target. + * + * @private + */ + _dimensionOverlay: function () { + if (!this.$backgroundOverlay.is('.oe_active')) { + return; + } + // TODO: change #wrapwrap after web_editor rework. + const $wrapwrap = $('#wrapwrap'); + const targetOffset = this.$target.offset(); + + this.$backgroundOverlay.css({ + width: $wrapwrap.innerWidth(), + height: $wrapwrap.innerHeight(), }); - function _update(e) { - var posX = e.pageX - $(e.target).offset().left; - var posY = e.pageY - $(e.target).offset().top; - self.bgPos = { - x: clipValue(posX / $img.width() * 100).toFixed(2) + '%', - y: clipValue(posY / $img.height() * 100).toFixed(2) + '%', - }; - self._updatePosInformation(); - self._saveChanges(); + this.$overlayContent.offset(targetOffset); - function clipValue(value) { - return Math.max(0, Math.min(value, 100)); - } + this.$bgDragger.css({ + width: `${this.$target.innerWidth()}px`, + height: `${this.$target.innerHeight()}px`, + }); + }, + /** + * Toggles the overlay's display and renders a background clone inside of it. + * + * @private + * @param {boolean} activate toggle the overlay on (true) or off (false) + */ + _toggleBgOverlay: function (activate) { + if (this.$backgroundOverlay.is('.oe_active') === activate) { + return; } + + if (!activate) { + this.$backgroundOverlay.removeClass('oe_active'); + this.trigger_up('unblock_preview_overlays'); + this.trigger_up('activate_snippet', {$snippet: this.$target}); + + $(document).off('click.bgposition'); + return; + } + + this.trigger_up('hide_overlay'); + this.trigger_up('activate_snippet', { + $snippet: this.$target, + previewMode: true, + }); + this.trigger_up('block_preview_overlays'); + + // Create empty clone of $target with same display size, make it draggable and give it a tooltip. + this.$bgDragger = this.$target.clone().empty(); + this.$bgDragger.on('mousedown', this._onDragBackgroundStart.bind(this)); + this.$bgDragger.tooltip({ + title: 'Click and drag the background to adjust its position!', + trigger: 'manual', + container: this.$backgroundOverlay + }); + + // Replace content of overlayBackground, activate the overlay and give it the right dimensions. + this.$overlayBackground.empty().append(this.$bgDragger); + this.$backgroundOverlay.addClass('oe_active'); + this._dimensionOverlay(); + this.$bgDragger.tooltip('show'); + + // Needs to be deferred or the click event that activated the overlay deactivates it as well. + // This is caused by the click event which we are currently handling bubbling up to the document. + window.setTimeout(() => $(document).on('click.bgposition', this._onDocumentClicked.bind(this)), 0); + }, + /** + * Disables background position if no background image, disables size inputs + * in cover mode, and activates the proper select option. + * + * @override + */ + _setActive: function () { + this.$el.toggleClass('d-none', this.$target.css('background-image') === 'none'); + this.$el.find('we-input').toggleClass('d-none', this.$target.css('background-repeat') !== 'repeat'); + this.$el.find('[data-background-type]').removeClass('active') + .filter(`[data-background-type=${this.$target.css('background-repeat') === 'repeat' ? 'repeat-pattern' : 'cover'}]`).addClass('active'); + + this._super.apply(this, arguments); }, /** - * Removes all option-related classes and style on the target element. + * Returns the src value from a css value related to a background image + * (e.g. "url('blabla')" => "blabla" / "none" => ""). * * @private + * @param {string} value + * @returns {string} */ - _clean: function () { - this.$target.removeClass('o_bg_img_opt_contain o_bg_img_opt_custom o_bg_img_opt_repeat o_bg_img_opt_repeat_x o_bg_img_opt_repeat_y') - .css({ - 'background-size': '', - 'background-position': '', - }); + _getSrcFromCssValue: function (value) { + if (value === undefined) { + value = this.$target.css('background-image'); + } + var srcValueWrapper = /url\(['"]*|['"]*\)|^none$/g; + return value && value.replace(srcValueWrapper, '') || ''; }, /** - * Restores the target style before last edition made with the option. + * Returns the difference between the target's size and the background's + * rendered size. Background position values in % are a percentage of this. * * @private */ - _discardChanges: function () { - this._clean(); - if (this.previousState) { - this.$target.addClass(this.previousState[0]).css({ - 'background-size': this.previousState[1], - 'background-position': this.previousState[2], - }); + _getBackgroundDelta: function () { + const bgSize = this.$target.css('background-size'); + if (bgSize !== 'cover') { + let [width, height] = bgSize.split(' '); + if (width === 'auto' && (height === 'auto' || !height)) { + return { + x: this.$target.outerWidth() - this.img.naturalWidth, + y: this.$target.outerHeight() - this.img.naturalHeight, + }; + } + // At least one of width or height is not auto, so we can use it to calculate the other if it's not set + [width, height] = [parseInt(width), parseInt(height)]; + return { + x: this.$target.outerWidth() - (width || (height * this.img.naturalWidth / this.img.naturalHeight)), + y: this.$target.outerHeight() - (height || (width * this.img.naturalHeight / this.img.naturalWidth)), + }; } + + const renderRatio = Math.max( + this.$target.outerWidth() / this.img.naturalWidth, + this.$target.outerHeight() / this.img.naturalHeight + ); + + return { + x: this.$target.outerWidth() - Math.round(renderRatio * this.img.naturalWidth), + y: this.$target.outerHeight() - Math.round(renderRatio * this.img.naturalHeight), + }; }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + /** - * Updates the visual representation of the chosen background position. + * Drags the overlay's background image, copied to target on "Apply". * * @private */ - _updatePosInformation: function () { - this.modal.$('.o_bg_img_opt_ui_info .o_x').text(this.bgPos.x); - this.modal.$('.o_bg_img_opt_ui_info .o_y').text(this.bgPos.y); - this.$focus.css({ - left: this.bgPos.x, - top: this.bgPos.y, + _onDragBackgroundStart: function (ev) { + ev.preventDefault(); + this.$bgDragger.addClass('o_we_grabbing'); + const $document = $(this.ownerDocument); + $document.on('mousemove.bgposition', this._onDragBackgroundMove.bind(this)); + $document.one('mouseup', () => { + this.$bgDragger.removeClass('o_we_grabbing'); + $document.off('mousemove.bgposition'); }); }, /** - * Updates the target element to match the chosen options. + * Drags the overlay's background image, copied to target on "Apply". * * @private */ - _saveChanges: function () { - this._clean(); + _onDragBackgroundMove: function (ev) { + ev.preventDefault(); - var bgImgSize = this.modal.$('> :not(label):not(.o_hidden)').data('value') || 'cover'; - switch (bgImgSize) { - case 'cover': - this.$target.css('background-position', this.bgPos.x + ' ' + this.bgPos.y); - break; - case 'contain': - this.$target.addClass('o_bg_img_opt_contain'); - this.$target.toggleClass('o_bg_img_opt_repeat', this.modal.$('#o_bg_img_opt_contain_repeat').prop('checked')); - break; - case 'custom': - this.$target.addClass('o_bg_img_opt_custom'); - var sizeX = this.modal.$('#o_bg_img_opt_custom_size_x').val(); - var sizeY = this.modal.$('#o_bg_img_opt_custom_size_y').val(); - var posX = this.modal.$('#o_bg_img_opt_custom_pos_x').val(); - var posY = this.modal.$('#o_bg_img_opt_custom_pos_y').val(); - this.$target.addClass(this.modal.$('#o_bg_img_opt_custom_repeat').val()) - .css({ - 'background-size': (sizeX ? sizeX + '%' : 'auto') + ' ' + (sizeY ? sizeY + '%' : 'auto'), - 'background-position': (posX ? posX + '%' : 'auto') + ' ' + (posY ? posY + '%' : 'auto'), - }); - break; + const delta = this._getBackgroundDelta(); + this.currentPosition.left = clamp(this.currentPosition.left + ev.originalEvent.movementX, [0, delta.x]); + this.currentPosition.top = clamp(this.currentPosition.top + ev.originalEvent.movementY, [0, delta.y]); + + const percentPosition = { + left: this.currentPosition.left / delta.x * 100, + top: this.currentPosition.top / delta.y * 100, + }; + // In cover mode, one delta will be 0 and dividing by it will yield Infinity. + // Defaulting to originalPosition in that case (can't be dragged) + percentPosition.left = isFinite(percentPosition.left) ? percentPosition.left : this.originalPosition.left; + percentPosition.top = isFinite(percentPosition.top) ? percentPosition.top : this.originalPosition.top; + + this.$bgDragger.css('background-position', `${percentPosition.left}% ${percentPosition.top}%`); + + function clamp(val, bounds) { + // We sort the bounds because when one dimension of the rendered background is + // larger than the container, delta is negative, and we want to use it as lower bound + bounds = bounds.sort(); + return Math.max(bounds[0], Math.min(val, bounds[1])); + } + }, + /** + * Deactivates the overlay if the user clicks outside of it. + * + * @private + */ + _onDocumentClicked: function (ev) { + if (!ev.target.closest('.o_we_background_position_overlay')) { + this._toggleBgOverlay(false); } }, }); diff --git a/addons/web_editor/static/src/scss/wysiwyg_snippets.scss b/addons/web_editor/static/src/scss/wysiwyg_snippets.scss index 5ddba517474..98c3d56b22e 100644 --- a/addons/web_editor/static/src/scss/wysiwyg_snippets.scss +++ b/addons/web_editor/static/src/scss/wysiwyg_snippets.scss @@ -836,6 +836,29 @@ body.editor_enable.editor_has_snippets { } } } + + // Background position overlay + &.o_we_background_position_overlay { + background-color: rgba(0,0,0,.7); + z-index: auto; + + .o_we_overlay_content { + cursor: grab; + + .o_we_grabbing { + cursor: grabbing; + } + } + + .o_overlay_background > * { + display: block !important; + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + left: 0 !important; + transform: none !important; + } + } } .contact_menu { diff --git a/addons/web_editor/static/src/xml/editor.xml b/addons/web_editor/static/src/xml/editor.xml index ca653c5d7ea..b1d7128e2c1 100644 --- a/addons/web_editor/static/src/xml/editor.xml +++ b/addons/web_editor/static/src/xml/editor.xml @@ -13,102 +13,16 @@ <!-- Snippet options --> <!--=================--> - <!-- Background position option dialog --> - <div t-name="web_editor.dialog.background_position" class="o_bg_img_opt_modal"> - <label class="radio-inline"><input type="radio" name="o_bg_img_opt" value="cover"/> Cover</label> - <label class="radio-inline"><input type="radio" name="o_bg_img_opt" value="contain"/> Contain</label> - <label class="radio-inline"><input type="radio" name="o_bg_img_opt" value="custom"/> Custom</label> - - <div class="o_bg_img_opt" data-value="cover"> - <div class="o_bg_img_opt_cover_edition"> - <h6>Assign a focal point that will always be visible</h6> - <div class="o_bg_img_opt_object"> - <span class="grid grid-1"/> - <span class="grid grid-2"/> - <span class="grid grid-3"/> - <span class="grid grid-4"/> - <span class="o_focus_point"/> - <div class="o_bg_img_opt_ui_info">X: <span class="o_x"/> Y: <span class="o_y"/></div> + <!-- Background position option overlay --> + <t t-name="web_editor.background_position_overlay"> + <div class="o_we_background_position_overlay oe_overlay"> + <div class="o_we_overlay_content position-absolute"> + <div class="o_overlay_background"/> + <div class="position-absolute d-flex m-1" style="top: 0"> + <button class="btn btn-primary mr-1 o_btn_apply">Apply</button> + <button class="btn btn-danger o_btn_discard">Discard</button> </div> </div> </div> - <div class="o_bg_img_opt" data-value="contain"> - <form> - <div class="form-group row"> - <label class="col-md-2 col-form-label" for="repeatInput">Repeat</label> - <div class="col-md-5"> - <div class="checkbox"> - <label> - <input type="checkbox" id="o_bg_img_opt_contain_repeat"/> - </label> - </div> - </div> - </div> - </form> - </div> - <form class="o_bg_img_opt" data-value="custom"> - <fieldset> - <legend>Background size</legend> - <p>Sets the width and height of the background image in percent of the parent element.</p> - <div class="form-group row"> - <label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_size_x">Background width</label> - <div class="col-md-5"> - <div class="input-group"> - <input type="number" min="0" max="100" class="form-control" id="o_bg_img_opt_custom_size_x" placeholder="auto"/> - <div class="input-group-append"> - <div class="input-group-text">%</div> - </div> - </div> - </div> - </div> - <div class="form-group row"> - <label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_size_y">Background height</label> - <div class="col-md-5"> - <div class="input-group"> - <input type="number" min="0" max="100" class="form-control" id="o_bg_img_opt_custom_size_y" placeholder="auto"/> - <div class="input-group-append"> - <div class="input-group-text">%</div> - </div> - </div> - </div> - </div> - </fieldset> - <fieldset> - <legend>Background position</legend> - <p>Set the starting position of the background image.</p> - <div class="form-group row"> - <label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_pos_x">Horizontal</label> - <div class="col-md-5"> - <div class="input-group"> - <input type="number" min="0" max="100" class="form-control " id="o_bg_img_opt_custom_pos_x" placeholder="auto"/> - <div class="input-group-append"> - <div class="input-group-text">%</div> - </div> - </div> - </div> - </div> - <div class="form-group row"> - <label class="col-md-3 col-form-label" for="o_bg_img_opt_custom_pos_y">Vertical</label> - <div class="col-md-5"> - <div class="input-group"> - <input type="number" min="0" max="100" class="form-control" id="o_bg_img_opt_custom_pos_y" placeholder="auto"/> - <div class="input-group-append"> - <div class="input-group-text">%</div> - </div> - </div> - </div> - </div> - </fieldset> - <fieldset> - <legend>Background repeat</legend> - <p>Define if/how the background image will be repeated</p> - <select class="form-control" id="o_bg_img_opt_custom_repeat"> - <option value="">No repeat</option> - <option value="o_bg_img_opt_repeat">Repeat both</option> - <option value="o_bg_img_opt_repeat_x">Repeat x</option> - <option value="o_bg_img_opt_repeat_y">Repeat y</option> - </select> - </fieldset> - </form> - </div> + </t> </templates> diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index c1af7852fd2..bf7960cc13d 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -674,7 +674,7 @@ options.registry.parallax = options.Class.extend({ */ onFocus: function () { this.trigger_up('option_update', { - optionNames: ['background', 'background_position'], + optionNames: ['background', 'BackgroundPosition'], name: 'target', data: this.$target.find('> .s_parallax_bg'), }); diff --git a/addons/website/static/src/scss/website.scss b/addons/website/static/src/scss/website.scss index 850f180f903..6e29659612c 100644 --- a/addons/website/static/src/scss/website.scss +++ b/addons/website/static/src/scss/website.scss @@ -239,6 +239,14 @@ font[class*='bg-'] { .oe_img_bg { background-size: cover; background-repeat: no-repeat; + + &.o_bg_img_opt_repeat { + background-size: auto; + background-repeat: repeat; + } + + // Compatibility <= 13.0, TODO remove? + // ----------------------------------- &.o_bg_img_opt_contain { background-size: contain; background-position: center center; @@ -246,9 +254,6 @@ font[class*='bg-'] { &.o_bg_img_opt_custom { background-size: auto; } - &.o_bg_img_opt_repeat { - background-repeat: repeat; - } &.o_bg_img_opt_repeat_x { background-repeat: repeat-x; } diff --git a/addons/website/static/src/scss/website.wysiwyg.scss b/addons/website/static/src/scss/website.wysiwyg.scss index 3206e4b027a..4e6fa2bc0c9 100644 --- a/addons/website/static/src/scss/website.wysiwyg.scss +++ b/addons/website/static/src/scss/website.wysiwyg.scss @@ -159,161 +159,3 @@ html[lang] > body.editor_enable [data-oe-translation-state] { opacity: 0; } } - -// MODALS -body .modal { - - // BACKGROUND IMAGE OPTIONS - .o_bg_img_opt_modal .o_bg_img_opt { - margin: 15px 0; - - .help-control { - @include o-position-absolute(15px, 15px); - } - - .help { - margin: 15px 0; - - .simulator { - position: relative; - float: left; - margin-right: 15px; - width: 120px; - height: 100px; - - .bg { - @include o-position-absolute(0, 0, 0, 0); - border: 1px dotted #888787; - background-image: url(/web/image); - background-position: center center; - background-size: cover; - } - - .el { - @include o-position-absolute(10px, 0, 10px, 0); - border: 1px solid #222; - } - - &.contain_bg { - .bg { - @include o-position-absolute(0, 12px, 20px, 12px); - } - - .el { - @include o-position-absolute(0, 0, 20px, 0); - } - } - } - - +* { - clear: left; - } - } - - .o_bg_img_opt_cover_edition { - @include o-we-preview-box; - padding: 0 25px 25px 25px; - - h6 { - color: white; - font-weight: bold; - } - - .o_bg_img_opt_object { - position: relative; - background: white; - min-height: 10px; - @include o-we-preview-content; - - >img { - cursor: crosshair; - border-top: 1px solid #5A5A5A; - border-bottom: 1px solid #111; - } - - &:hover .o_focus_point:before { - opacity: 0.5; - } - } - - .o_bg_img_opt_ui_info { - animation: fadeInOut 2s ease forwards; - @include o-position-absolute($bottom: 1px, $right: 0); - display: block; - padding: 3px 13px; - background-color: rgba(255, 255, 255, 0.8); - color: #333; - text-align: center; - font-weight: bold; - pointer-events: none; - - span { - font-weight: normal; - } - - .o_x { - margin-right: 10px - } - } - - .grid { - @include o-position-absolute($top: 33.33%, $left: 0); - display: block; - width: 100%; - height: 1px; - background: fade-out(lighten($o-brand-primary, 30%), 0.5); - pointer-events: none; - - &.grid-2 { - top: 66.66% - } - - &.grid-3 { - top: 0; - left: 33.33%; - width: 1px; - height: 100% - } - - &.grid-4 { - top: 0; - left: 66.66%; - width: 1px; - height: 100% - } - } - - .o_focus_point { - @include o-position-absolute($top: 0, $left: 0); - width: 30px; - height: 30px; - border: 2px solid white; - border-radius: 100%; - margin-top: -15px; - margin-left: -15px; - box-shadow: 0 0 1px #333; - pointer-events: none; - - &.o_with_transition { - transition: all 0.2s ease 0s; - } - - &:before { - pointer-events: none; - content: ""; - display: block; - width: 100px; - height: 100px; - margin-top: -37px; - margin-left: -37px; - border: 1px solid #EAEAEA; - background: rgba(247, 76, 76, 0); - border-radius: 100em; - opacity: 1; - box-shadow: 0 0 0 100em rgba(0, 0, 0, 0.33); - transition: opacity 0.2s ease 0s; - } - } - } - } -} diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml index 16b218b6366..103dd62cc4a 100644 --- a/addons/website/views/snippets.xml +++ b/addons/website/views/snippets.xml @@ -1226,11 +1226,20 @@ data-selector="section, .parallax, .carousel-item" data-exclude=".s_hr, .s_image_gallery, .o_gallery .carousel-item"/> - <!-- Background Image --> - <div data-js="background_position" + <!-- Background Image Size/Position --> + <div data-js="BackgroundPosition" data-selector="section, .parallax, .carousel-item" data-exclude=".o_gallery .carousel-item"> - <we-button data-background-position="true" data-no-preview="true">Background Image Sizing</we-button> + <we-row> + <we-select data-no-preview="true"> + <we-button data-background-type="cover">Cover</we-button> + <we-button data-background-type="repeat-pattern">Repeat pattern</we-button> + </we-select> + <we-button class="fa fa-fw fa-arrows" title="Background Position" + data-background-position-overlay="true" data-no-preview="true"/> + </we-row> + <we-input string="Background width" data-set-style="background-size" data-default-value="auto"/> + <we-input string="Background height" data-set-style="background-size" data-default-value="auto"/> </div> <!-- Parallax --> |
