Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit a3a7afd

Browse files
matskoNarretz
authored andcommitted
fix(ngAnimate): do not trigger animations if the document is hidden
Prior to this fix, ngAnimate would always trigger animations even if the browser tab or browser window was not visible. This would cause issues with class updates / DOM operations even if elements were not using animations. The root cause is that browsers do not flush calls to requestAnimationFrame when browser windows / tabs are not visible. This fix disables animations if `document.hidden` is `true`. Closes #12842 Closes #13776
1 parent 20bc37f commit a3a7afd

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

src/ngAnimate/animateQueue.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
337337
// this is a hard disable of all animations for the application or on
338338
// the element itself, therefore there is no need to continue further
339339
// past this point if not enabled
340-
var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node);
340+
// Animations are also disabled if the document is currently hidden (page is not visible
341+
// to the user), because browsers slow down or do not flush calls to requestAnimationFrame
342+
var skipAnimations = !animationsEnabled || $document[0].hidden || disabledElementsLookup.get(node);
341343
var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
342344
var hasExistingAnimation = !!existingAnimation.state;
343345

test/ngAnimate/animateSpec.js

+25
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,31 @@ describe("animations", function() {
148148
expect(copiedOptions).toEqual(initialOptions);
149149
}));
150150

151+
it("should skip animations entirely if the document is hidden", function() {
152+
var doc;
153+
154+
module(function($provide) {
155+
doc = jqLite({
156+
body: document.body,
157+
hidden: true
158+
});
159+
$provide.value('$document', doc);
160+
});
161+
162+
inject(function($animate, $rootScope) {
163+
$animate.enter(element, parent);
164+
$rootScope.$digest();
165+
expect(capturedAnimation).toBeFalsy();
166+
expect(element[0].parentNode).toEqual(parent[0]);
167+
168+
doc[0].hidden = false;
169+
170+
$animate.leave(element);
171+
$rootScope.$digest();
172+
expect(capturedAnimation).toBeTruthy();
173+
});
174+
});
175+
151176
it('should animate only the specified CSS className matched within $animateProvider.classNameFilter', function() {
152177
module(function($animateProvider) {
153178
$animateProvider.classNameFilter(/only-allow-this-animation/);

0 commit comments

Comments
 (0)