[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.
This commit is contained in:
qsm-odoo
2018-08-13 18:42:52 +02:00
parent 4dce6cc98b
commit b56e647f2c
2 changed files with 46 additions and 45 deletions
@@ -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;
}
@@ -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.