Skip to content
Permalink
Browse files

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
  • Loading branch information...
matsko authored and Narretz committed Jan 15, 2016
1 parent 2d1ee4b commit 09f6061a8ee41cae4268e8d44d727d3bf52e22a9
Showing with 28 additions and 1 deletion.
  1. +3 −1 src/ngAnimate/animateQueue.js
  2. +25 −0 test/ngAnimate/animateSpec.js
@@ -337,7 +337,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
// this is a hard disable of all animations for the application or on
// the element itself, therefore there is no need to continue further
// past this point if not enabled
var skipAnimations = !animationsEnabled || disabledElementsLookup.get(node);
// Animations are also disabled if the document is currently hidden (page is not visible
// to the user), because browsers slow down or do not flush calls to requestAnimationFrame
var skipAnimations = !animationsEnabled || $document[0].hidden || disabledElementsLookup.get(node);
var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
var hasExistingAnimation = !!existingAnimation.state;

@@ -148,6 +148,31 @@ describe("animations", function() {
expect(copiedOptions).toEqual(initialOptions);
}));

it("should skip animations entirely if the document is hidden", function() {
var doc;

module(function($provide) {
doc = jqLite({
body: document.body,
hidden: true
});
$provide.value('$document', doc);
});

inject(function($animate, $rootScope) {
$animate.enter(element, parent);
$rootScope.$digest();
expect(capturedAnimation).toBeFalsy();
expect(element[0].parentNode).toEqual(parent[0]);

doc[0].hidden = false;

$animate.leave(element);
$rootScope.$digest();
expect(capturedAnimation).toBeTruthy();
});
});

it('should animate only the specified CSS className matched within $animateProvider.classNameFilter', function() {
module(function($animateProvider) {
$animateProvider.classNameFilter(/only-allow-this-animation/);

0 comments on commit 09f6061

Please sign in to comment.
You can’t perform that action at this time.