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 eec85058ebc..9cc1d080bda 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -593,6 +593,7 @@ registry.sizing = SnippetOption.extend({ var direction = $handle.hasClass('n') ? 'top': 'bottom'; $handle.height(self.$target.css('padding-' + direction)); }); + this.$target.trigger('content_changed'); }, }); diff --git a/addons/website/static/src/js/content/snippets.animation.js b/addons/website/static/src/js/content/snippets.animation.js index c303d0691d3..e4969f43ce6 100644 --- a/addons/website/static/src/js/content/snippets.animation.js +++ b/addons/website/static/src/js/content/snippets.animation.js @@ -430,18 +430,17 @@ registry.slider = publicWidget.Widget.extend({ selector: '.carousel', disabledInEditableMode: false, edit_events: { - 'slid.bs.carousel': '_onEditionSlide', + 'content_changed': '_onContentChanged', }, /** * @override */ start: function () { - if (!this.editableMode) { - this.$('img').on('load.slider', this._onImageLoaded.bind(this)); - this._computeHeights(); - } - this.$target.carousel(); + this.$('img').on('load.slider', () => this._computeHeights()); + this._computeHeights(); + // Initialize carousel and pause if in edit mode. + this.$target.carousel(this.editableMode ? 'pause' : undefined); return this._super.apply(this, arguments); }, /** @@ -467,6 +466,7 @@ registry.slider = publicWidget.Widget.extend({ _computeHeights: function () { var maxHeight = 0; var $items = this.$('.carousel-item'); + $items.css('min-height', ''); _.each($items, function (el) { var $item = $(el); var isActive = $item.hasClass('active'); @@ -477,9 +477,7 @@ registry.slider = publicWidget.Widget.extend({ } $item.toggleClass('active', isActive); }); - _.each($items, function (el) { - $(el).css('min-height', maxHeight); - }); + $items.css('min-height', maxHeight); }, //-------------------------------------------------------------------------- @@ -489,13 +487,7 @@ registry.slider = publicWidget.Widget.extend({ /** * @private */ - _onEditionSlide: function () { - this._computeHeights(); - }, - /** - * @private - */ - _onImageLoaded: function () { + _onContentChanged: function (ev) { this._computeHeights(); }, }); diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 8e0f4b2dc4a..e46796d4dd4 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -225,69 +225,46 @@ options.registry.carousel = options.Class.extend({ * @override */ start: function () { - var self = this; - - this.$target.carousel({interval: false}); - this.id = this.$target.attr('id'); - this.$inner = this.$target.find('.carousel-inner'); - this.$indicators = this.$target.find('.carousel-indicators'); this.$target.carousel('pause'); - this._rebindEvents(); + this.$indicators = this.$target.find('.carousel-indicators'); + this.$controls = this.$target.find('.carousel-control-prev, .carousel-control-next, .carousel-indicators'); + this.$items = this.$target.find('.carousel-item'); + this.$target.on('slid.bs.carousel.carousel_option', () => this._retargetEdition()); - var def = this._super.apply(this, arguments); - - // set background and prepare to clean for save - this.$target.on('slid.bs.carousel', function () { - self.$target.carousel('pause'); - self.trigger_up('option_update', { - optionNames: ['background', 'background_position', 'colorpicker', 'sizing_y'], - name: 'target', - data: self.$target.find('.carousel-item.active'), - }); - }); - - return def; + return this._super.apply(this, arguments); + }, + /** + * @override + */ + destroy: function () { + this._super.apply(this, arguments); + this.$target.off('.carousel_option'); }, /** - * Associates unique ID on slider elements. - * * @override */ onBuilt: function () { - this.id = 'myCarousel' + new Date().getTime(); - this.$target.attr('id', this.id); - this.$target.find('[data-target]').attr('data-target', '#' + this.id); - this._rebindEvents(); + this._assignUniqueID(); + }, + /** + * @override + */ + onClone: function () { + this._assignUniqueID(); }, /** * @override */ onFocus: function () { - // Needs to be done on focus, not on start, as all other options are - // maybe not all initialized in start - this.$target.trigger('slid.bs.carousel'); - }, - /** - * Associates unique ID on cloned slider elements. - * - * @override - */ - onClone: function () { - var id = 'myCarousel' + new Date().getTime(); - this.$target.attr('id', id); - this.$target.find('[data-slide]').attr('href', '#' + id); - this.$target.find('[data-slide-to]').attr('data-target', '#' + id); + this._retargetEdition(); }, /** * @override */ cleanForSave: function () { this._super.apply(this, arguments); - this.$target.find('.carousel-item').removeClass('next prev left right active') - .first().addClass('active'); - this.$target.find('.carousel-indicators').find('li').removeClass('active').html('') - .first().addClass('active'); - this.$target.removeClass('oe_img_bg ' + this._class).css('background-image', ''); + this.$items.removeClass('next prev left right active').first().addClass('active'); + this.$indicators.find('li').removeClass('active').empty().first().addClass('active'); }, //-------------------------------------------------------------------------- @@ -300,18 +277,18 @@ options.registry.carousel = options.Class.extend({ * @see this.selectClass for parameters */ addSlide: function (previewMode) { - var self = this; - var cycle = this.$inner.find('.carousel-item').length; - var $active = this.$inner.find('.carousel-item.active, .carousel-item.prev, .carousel-item.next').first(); - var index = $active.index(); - this.$('.carousel-control-prev, .carousel-control-next, .carousel-indicators').removeClass('d-none'); - this.$indicators.append('
  • '); - var $clone = $active.clone(true); - $clone.removeClass('active').insertAfter($active); - _.defer(function () { - self.$target.carousel().carousel(++index); - self._rebindEvents(); - }); + this.$controls.removeClass('d-none'); + this.$indicators.append($('
  • ', { + 'data-target': '#' + this.$target.attr('id'), + 'data-slide-to': this.$items.length, + })); + // Need to remove editor data from the clone so it gets its own. + const $active = this.$items.filter('.active'); + $active.clone(false) + .removeClass('active') + .insertAfter($active); + this.$items = this.$target.find('.carousel-item'); + this.$target.carousel('next'); }, /** * Removes the current slide. @@ -319,33 +296,19 @@ options.registry.carousel = options.Class.extend({ * @see this.selectClass for parameters. */ removeSlide: function (previewMode) { - if (this.remove_process) { - return; - } - - var self = this; - - var $items = this.$inner.find('.carousel-item'); - var cycle = $items.length - 1; - var $active = $items.filter('.active'); - var index = $active.index(); - - if (cycle > 0) { - this.remove_process = true; - this.$target.on('slid.bs.carousel.slide_removal', function (event) { - $active.remove(); - self.$indicators.find('li:last').remove(); - self.$target.off('slid.bs.carousel.slide_removal'); - self._rebindEvents(); - self.remove_process = false; - if (cycle === 1) { - self.$target.find('.carousel-control-prev, .carousel-control-next, .carousel-indicators').addClass('d-none'); - } - }); - _.defer(function () { - self._refreshPublicWidgets(); - self.$target.carousel(index > 0 ? --index : cycle); + const newLength = this.$items.length - 1; + if (!this.removing && newLength > 0) { + const $toDelete = this.$items.filter('.active'); + this.$target.one('slid.bs.carousel', (event) => { + $toDelete.remove(); + this.$indicators.find('li:last').remove(); + this.$items = this.$target.find('.carousel-item'); + this.$controls.toggleClass('d-none', newLength === 1); + this.$target.find('.carousel').trigger('content_changed'); + this.removing = false; }); + this.removing = true; + this.$target.carousel('prev'); } }, /** @@ -366,25 +329,33 @@ options.registry.carousel = options.Class.extend({ */ _setActive: function () { this._super.apply(this, arguments); - this.$el.find('[data-interval]').removeClass('active') - .filter('[data-interval=' + this.$target.attr('data-interval') + ']').addClass('active'); + this.$el.find('[data-interval]') + .removeClass('active') + .filter(`[data-interval=${this.$target.attr('data-interval')}]`) + .addClass('active'); }, /** - * Rebinds carousel events on indicators. + * Activates current slide for edition and vertical padding. Padding on the + * carousel itself would mean the slides' backgrounds don't cover the padding. * * @private */ - _rebindEvents: function () { - var self = this; - this.$target.find('.carousel-control-prev, .carousel-control-next').off('click').on('click', function () { - self.$target.carousel($(this).data('slide')); + _retargetEdition: function () { + this.trigger_up('activate_snippet', { + $snippet: this.$items.filter('.active'), + ifInactiveOptions: true, }); - this.$target.find('.carousel-indicators [data-slide-to]').off('click').on('click', function () { - self.$target.carousel(+$(this).data('slide-to')); - }); - - /* Fix: backward compatibility saas-3 */ - this.$target.find('.item.text_image, .item.image_text, .item.text_only').find('.container > .carousel-caption > div, .container > img.carousel-image').attr('contentEditable', 'true'); + }, + /** + * Creates a unique ID for the carousel and reassign data-attributes that depend on it. + * + * @private + */ + _assignUniqueID: function () { + const id = 'myCarousel' + Date.now(); + this.$target.attr('id', id); + this.$target.find('[data-target]').attr('data-target', '#' + id); + this.$target.find('[data-slide]').attr('href', '#' + id); }, }); diff --git a/addons/website/views/snippets.xml b/addons/website/views/snippets.xml index 95bac08325d..ac46f7b5371 100644 --- a/addons/website/views/snippets.xml +++ b/addons/website/views/snippets.xml @@ -198,76 +198,78 @@ @@ -1147,7 +1151,8 @@
    + data-selector="section" + data-target="> .carousel"> Add Slide @@ -1310,9 +1315,9 @@
    -
    +
    Background @@ -1320,7 +1325,8 @@
    + data-selector="section, .parallax, .carousel-item" + data-exclude=".o_gallery .carousel-item"> Background Image Sizing @@ -1346,8 +1352,8 @@
    + data-selector="section, .carousel-item" + data-exclude=".parallax, .o_gallery .carousel-item"> Background Color @@ -1389,7 +1395,8 @@
    + data-selector="section, .row > div, .parallax, .s_hr, .s_btn, .carousel-item" + data-exclude="section:has(> .carousel), .o_gallery .carousel-item"/>