From 959f2bbb2d12c23a74902433c6247290d8f2fb89 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Fri, 11 Dec 2015 12:20:31 +0100 Subject: [PATCH] fix($animateCss): only (de)register listeners when events have been added Previously, when an animation was closed because no animation styles where found, it would call .off() with an empty string as the argument. For both jquery/jqlite this is the same as calling .off() without any argument, which deregisters all event listeners on an element. Closes #13514 --- src/ngAnimate/animateCss.js | 9 ++++++--- test/ngAnimate/animateCssSpec.js | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/ngAnimate/animateCss.js b/src/ngAnimate/animateCss.js index ba5e34773cf6..80e20f8095d3 100644 --- a/src/ngAnimate/animateCss.js +++ b/src/ngAnimate/animateCss.js @@ -749,8 +749,8 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { options.onDone(); } - // Remove the transitionend / animationend listener(s) - if (events) { + if (events && events.length) { + // Remove the transitionend / animationend listener(s) element.off(events.join(' '), onAnimationProgress); } @@ -960,7 +960,10 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) { element.data(ANIMATE_TIMER_KEY, animationsData); } - element.on(events.join(' '), onAnimationProgress); + if (events.length) { + element.on(events.join(' '), onAnimationProgress); + } + if (options.to) { if (options.cleanupStyles) { registerRestorableStyles(restoreStyles, node, Object.keys(options.to)); diff --git a/test/ngAnimate/animateCssSpec.js b/test/ngAnimate/animateCssSpec.js index 74fa12fc4b75..e43dd89a912c 100644 --- a/test/ngAnimate/animateCssSpec.js +++ b/test/ngAnimate/animateCssSpec.js @@ -1502,6 +1502,39 @@ describe("ngAnimate $animateCss", function() { expect(elementOffSpy.mostRecentCall.args[0]).toBe(event); }); }); + + they("should not add or remove $prop event listeners when no animation styles are detected", + [TRANSITIONEND_EVENT, ANIMATIONEND_EVENT], function(event) { + inject(function($animateCss, $timeout) { + + progress = event === TRANSITIONEND_EVENT ? transitionProgress : keyframeProgress; + + // Make sure other event listeners are not affected + var otherEndSpy = jasmine.createSpy('otherEndSpy'); + element.on(event, otherEndSpy); + + expect(elementOnSpy).toHaveBeenCalledOnce(); + elementOnSpy.reset(); + + var animator = $animateCss(element, { + event: 'enter', + structural: true + }); + + expect(animator.$$willAnimate).toBeFalsy(); + + // This will close the animation because no styles have been detected + var runner = animator.start(); + triggerAnimationStartFrame(); + + expect(elementOnSpy).not.toHaveBeenCalled(); + expect(elementOffSpy).not.toHaveBeenCalled(); + + progress(element, 10); + expect(otherEndSpy).toHaveBeenCalledOnce(); + }); + }); + }); });