fix(ngAnimate): fire callbacks when document is hidden

Since commit a3a7afd3aa, animations are not run
when the document is hidden (only their structural or class change effects are executed).
However, some libraries rely on the $animate.on() callbacks to be called even when no actual animation
runs.
This commit restores the behavior for the ngAnimate.$animate functions.
Note that callbacks still won't be called if animations are disabled, because this would be be a potential
breaking change, as some applications might rely on this implementation.

Fixes #14120
This commit is contained in:
Martin Staffa
2016-03-14 19:22:20 +01:00
parent 19eca35c72
commit 2b327f01be
2 changed files with 36 additions and 1 deletions
+6 -1
View File
@@ -343,12 +343,14 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
var documentHidden = $document[0].hidden;
// 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
// 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 skipAnimations = !animationsEnabled || documentHidden || disabledElementsLookup.get(node);
var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
var hasExistingAnimation = !!existingAnimation.state;
@@ -359,7 +361,10 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
}
if (skipAnimations) {
// Callbacks should fire even if the document is hidden (regression fix for issue #14120)
if (documentHidden) notifyProgress(runner, event, 'start');
close();
if (documentHidden) notifyProgress(runner, event, 'close');
return runner;
}
+30
View File
@@ -2323,6 +2323,36 @@ describe("animations", function() {
expect(classSpy).not.toHaveBeenCalled();
}));
describe('because the document is hidden', function() {
beforeEach(module(function($provide) {
var doc = jqLite({
body: document.body,
hidden: true
});
$provide.value('$document', doc);
}));
it('should trigger callbacks for an enter animation',
inject(function($animate, $rootScope, $rootElement, $document) {
var callbackTriggered = false;
var spy = jasmine.createSpy();
$animate.on('enter', jqLite($document[0].body), spy);
element = jqLite('<div></div>');
var runner = $animate.enter(element, $rootElement);
$rootScope.$digest();
$animate.flush(); // Flushes the animation frames for the callbacks
expect(spy.calls.count()).toBe(2);
expect(spy.calls.argsFor(0)[1]).toBe('start');
expect(spy.calls.argsFor(1)[1]).toBe('close');
}));
});
});
});