diff options
| author | Samuel Degueldre <sad@odoo.com> | 2019-10-18 05:38:45 +0000 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2019-11-06 12:26:27 +0000 |
| commit | 958c850f9f6ce722b0938331d0df9f873645f467 (patch) | |
| tree | 5161e58675fafc00a30ed8857b1b16b98f0eb506 /addons/website/static/src/js | |
| parent | aa62e957183644f67f85c01e2cdd73ac80f1576f (diff) | |
[REF] website, web_editor: refactor (quotes) carousel snippets
Previously, the carousel and quotes carousel snippets were the only ones
that were not enclosed in section blocks. This had a number of
undesirable side effects, such as editing the anchor on the carousel
breaking the carousel functionality, and the inability to separately
choose a background for the carousel itself and individual slides.
I also used this opportunity to move controls relative to the entire
carousel onto the carousel itself rather than the individual slides. The
sizing_y (vertical padding) will however keep targeting individual
slides, as the carousel uses the height of its tallest slide, and also
because padding on the carousel will not get covered by slide
backgrounds and saty blank, which is unwanted.
Lastly, most of the snippet options for the carousel were rewritten, as
they were quite broken. There was some compatibility code for saas-3
left, some useless events were bound to the controls, even though they
were already handled through event-delegation at the document level.
Finally, most of the edition features were broken on duplicated
carousels since the onClone method wasn't reassigning most of the things
it needed to.
Part of https://github.com/odoo/odoo/pull/38997
task-2090180
Diffstat (limited to 'addons/website/static/src/js')
| -rw-r--r-- | addons/website/static/src/js/content/snippets.animation.js | 24 | ||||
| -rw-r--r-- | addons/website/static/src/js/editor/snippets.options.js | 157 |
2 files changed, 72 insertions, 109 deletions
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(); - - 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'), - }); - }); + 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()); - return def; + return this._super.apply(this, arguments); }, /** - * 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(); + destroy: function () { + this._super.apply(this, arguments); + this.$target.off('.carousel_option'); }, /** * @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'); + onBuilt: function () { + this._assignUniqueID(); }, /** - * 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._assignUniqueID(); + }, + /** + * @override + */ + onFocus: function () { + 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('<li data-target="#' + this.id + '" data-slide-to="' + cycle + '"></li>'); - 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($('<li>', { + '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')); - }); - this.$target.find('.carousel-indicators [data-slide-to]').off('click').on('click', function () { - self.$target.carousel(+$(this).data('slide-to')); + _retargetEdition: function () { + this.trigger_up('activate_snippet', { + $snippet: this.$items.filter('.active'), + ifInactiveOptions: true, }); - - /* 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); }, }); |
