From b56e647f2c540d34860cdee8a6adf0785ce3b8ef Mon Sep 17 00:00:00 2001 From: qsm-odoo Date: Thu, 28 Dec 2017 14:41:25 +0100 Subject: [PATCH] [REF] web_editor, website: improve animations' restart - Before this commit, when we asked to (re)start animations on an element, we checked the animations to be started on the element and started them after destroying the animations with the same name which were already running on that element. This is in fact not correct. Indeed, if an animation was running on element but that the conditions that made the animation start are now gone, asking to restart the animations on that element should destroy the deprecated ones. (e.g. an animation "A" is to be started on all elements which have a class "a", if we remove the class "a" on an element then restart animations, the animation "A" should be destroy). The implementation is in fact even simpler: when asking a restart, a full stop is performed then a simple start. Note: this does not need to be a fix as multiple animations on a same element was recently introduced and the described case never occurs with current features. - When stopping the animations on an element, stops the animations of all its descendants too. - Add an helper method in the `SnippetOption` class to restart the animations running on the `$target` element. --- .../static/src/js/content/website_root.js | 26 ++++---- .../static/src/js/editor/snippets.options.js | 65 ++++++++++--------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/addons/website/static/src/js/content/website_root.js b/addons/website/static/src/js/content/website_root.js index 336ea822902..29163838f7a 100644 --- a/addons/website/static/src/js/content/website_root.js +++ b/addons/website/static/src/js/content/website_root.js @@ -137,27 +137,22 @@ var WebsiteRoot = BodyManager.extend({ */ _startAnimations: function (editableMode, $from) { var self = this; + editableMode = editableMode || false; if ($from === undefined) { $from = this.$('#wrapwrap'); } + + this._stopAnimations($from); + var defs = _.map(sAnimation.registry, function (Animation, animationName) { var selector = Animation.prototype.selector || ''; var $target = $from.find(selector).addBack(selector); var defs = _.map($target, function (el) { - var $snippet = $(el); - var animationIndex = _.findIndex(self.animations, function (animation) { - return animation.__name === animationName && $snippet[0] === animation.el; - }); - if (animationIndex >= 0) { - self.animations[animationIndex].destroy(); - self.animations.splice(animationIndex, 1); - } var animation = new Animation(self, editableMode); - animation.__name = animationName; self.animations.push(animation); - return animation.attachTo($snippet); + return animation.attachTo($(el)); }); return $.when.apply($, defs); }); @@ -168,12 +163,15 @@ var WebsiteRoot = BodyManager.extend({ * in edition mode for example. * * @private - * @param {jQuery} [$stopTarget] - * only stop the animations linked to the given element(s) + * @param {jQuery} [$from] + * only stop the animations linked to the given element(s) or one of + * its descendants */ - _stopAnimations: function ($stopTarget) { + _stopAnimations: function ($from) { var removedAnimations = _.map(this.animations, function (animation) { - if (!$stopTarget || $stopTarget.filter(animation.el).length) { + if (!$from + || $from.filter(animation.el).length + || $from.find(animation.el).length) { animation.destroy(); return animation; } diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index a53c402dbb1..5a6d569ae89 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -9,6 +9,26 @@ var options = require('web_editor.snippets.options'); var _t = core._t; var qweb = core.qweb; +options.Class.include({ + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * Refreshes all animations related to the given element. + * + * @private + * @param {jQuery} [$el=this.$target] + */ + _refreshAnimations: function ($el) { + this.trigger_up('animation_start_demand', { + editableMode: true, + $target: $el || this.$target, + }); + }, +}); + options.registry.menu_data = options.Class.extend({ xmlDependencies: ['/website/static/src/xml/website.editor.xml'], @@ -412,8 +432,10 @@ options.registry.parallax = options.Class.extend({ * @override */ start: function () { - this._refresh_callback = this._refresh.bind(this); - this.$target.on('snippet-option-change snippet-option-preview', this._refresh_callback); + var self = this; + this.$target.on('snippet-option-change snippet-option-preview', function () { + self._refreshAnimations(); + }); return this._super.apply(this, arguments); }, /** @@ -425,13 +447,17 @@ options.registry.parallax = options.Class.extend({ name: 'target', data: this.$target.find('> .s_parallax_bg'), }); - this._refresh(); + // Refresh the parallax animation on focus; at least useful because + // there may have been changes in the page that influenced the parallax + // rendering (new snippets, ...). + // TODO make this automatic. + this._refreshAnimations(); }, /** * @override */ onMove: function () { - this._refresh(); + this._refreshAnimations(); }, //-------------------------------------------------------------------------- @@ -445,27 +471,13 @@ options.registry.parallax = options.Class.extend({ */ scroll: function (previewMode, value) { this.$target.attr('data-scroll-background-ratio', value); - this._refresh(); + this._refreshAnimations(); }, //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- - /** - * Notifies the parallax animation that it needs to be reinitialized. - * - * @private - */ - _refresh: function () { - var self = this; - _.defer(function () { - self.trigger_up('animation_start_demand', { - editableMode: true, - $target: self.$target, - }); - }); - }, /** * @override */ @@ -667,10 +679,7 @@ options.registry.facebookPage = options.Class.extend({ $el.attr('data-' + key, value); $el.data(key, value); }); - self.trigger_up('animation_start_demand', { - editableMode: true, - $target: $el, - }); + self._refreshAnimations($el); }, }); @@ -729,10 +738,7 @@ options.registry.ul = options.Class.extend({ this.$target.find('li:has(.o_ul_toggle_self, .o_ul_toggle_next), li:has(>ul,>ol):not(:has(>li))').css('list-style', 'none'); this.$target.find('li:not(:has(>ul))').css('list-style', ''); - this.trigger_up('animation_start_demand', { - editableMode: true, - $target: this.$target, - }); + this._refreshAnimations(); }, }); @@ -1039,10 +1045,7 @@ options.registry.gallery = options.Class.extend({ // Apply layout animation this.$target.off('slide.bs.carousel').off('slid.bs.carousel'); this.$('li.fa').off('click'); - this.trigger_up('animation_start_demand', { - editableMode: true, - $target: this.$target, - }); + this._refreshAnimations(); }, /** * Allows to change the style of the individual images.