diff --git a/src/ng/animateRunner.js b/src/ng/animateRunner.js index 51701b4c16f8..0b6cacc8d6f0 100644 --- a/src/ng/animateRunner.js +++ b/src/ng/animateRunner.js @@ -28,8 +28,8 @@ var $$AnimateAsyncRunFactoryProvider = function() { }; var $$AnimateRunnerFactoryProvider = function() { - this.$get = ['$q', '$sniffer', '$$animateAsyncRun', - function($q, $sniffer, $$animateAsyncRun) { + this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout', + function($q, $sniffer, $$animateAsyncRun, $document, $timeout) { var INITIAL_STATE = 0; var DONE_PENDING_STATE = 1; @@ -74,8 +74,19 @@ var $$AnimateRunnerFactoryProvider = function() { function AnimateRunner(host) { this.setHost(host); + var rafTick = $$animateAsyncRun(); + var timeoutTick = function(fn) { + $timeout(fn, 0, false); + }; + this._doneCallbacks = []; - this._runInAnimationFrame = $$animateAsyncRun(); + this._tick = function(fn) { + if ($document[0].hidden) { + timeoutTick(fn); + } else { + rafTick(fn); + } + }; this._state = 0; } @@ -148,7 +159,7 @@ var $$AnimateRunnerFactoryProvider = function() { var self = this; if (self._state === INITIAL_STATE) { self._state = DONE_PENDING_STATE; - self._runInAnimationFrame(function() { + self._tick(function() { self._resolve(response); }); } diff --git a/test/ng/animateRunnerSpec.js b/test/ng/animateRunnerSpec.js index d6fab470e8df..622da76ff22b 100644 --- a/test/ng/animateRunnerSpec.js +++ b/test/ng/animateRunnerSpec.js @@ -162,6 +162,43 @@ describe("$$AnimateRunner", function() { expect(animationFailed).toBe(true); })); + it("should use timeouts to trigger async operations when the document is hidden", function() { + var doc; + + module(function($provide) { + doc = jqLite({ + body: document.body, + hidden: true + }); + $provide.value('$document', doc); + }); + + inject(function($$AnimateRunner, $rootScope, $$rAF, $timeout) { + var spy = jasmine.createSpy(); + var runner = new $$AnimateRunner(); + runner.done(spy); + runner.complete(true); + expect(spy).not.toHaveBeenCalled(); + $$rAF.flush(); + expect(spy).not.toHaveBeenCalled(); + $timeout.flush(); + expect(spy).toHaveBeenCalled(); + + doc[0].hidden = false; + + spy = jasmine.createSpy(); + runner = new $$AnimateRunner(); + runner.done(spy); + runner.complete(true); + expect(spy).not.toHaveBeenCalled(); + $$rAF.flush(); + expect(spy).toHaveBeenCalled(); + expect(function() { + $timeout.flush(); + }).toThrow(); + }); + }); + they("should expose the `finally` promise function to handle the final state when $prop", { 'rejected': 'cancel', 'resolved': 'end' }, function(method) { inject(function($$AnimateRunner, $rootScope) {