diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 3345dce7691d..04f837c8aaa9 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -139,8 +139,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { return mergeAnimationOptions(element, options, {}); } - function findCallbacks(element, event) { + function findCallbacks(parent, element, event) { var targetNode = getDomNode(element); + var targetParentNode = getDomNode(parent); var matches = []; var entries = callbackRegistry[event]; @@ -148,6 +149,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { forEach(entries, function(entry) { if (entry.node.contains(targetNode)) { matches.push(entry.callback); + } else if (event === 'leave' && entry.node.contains(targetParentNode)) { + matches.push(entry.callback); } }); } @@ -473,7 +476,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { function notifyProgress(runner, event, phase, data) { runInNextPostDigestOrNow(function() { - var callbacks = findCallbacks(element, event); + var callbacks = findCallbacks(parent, element, event); if (callbacks.length) { // do not optimize this call here to RAF because // we don't know how heavy the callback code here will diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index c08808150420..9df3b400bdc3 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -1781,5 +1781,86 @@ describe("animations", function() { expect(isElementRemoved).toBe(true); })); + it('leave : should trigger a callback for an leave animation', + inject(function($animate, $rootScope, $$rAF, $rootElement, $document) { + + var callbackTriggered = false; + $animate.on('leave', jqLite($document[0].body), function() { + callbackTriggered = true; + }); + + element = jqLite('
'); + $rootElement.append(element); + $animate.leave(element, $rootElement); + $rootScope.$digest(); + + $$rAF.flush(); + + expect(callbackTriggered).toBe(true); + })); + + it('leave : should not fire a callback if the element is outside of the given container', + inject(function($animate, $rootScope, $$rAF, $rootElement) { + + var callbackTriggered = false; + var innerContainer = jqLite('
'); + $rootElement.append(innerContainer); + + $animate.on('leave', innerContainer, + function(element, phase, data) { + callbackTriggered = true; + }); + + element = jqLite('
'); + $rootElement.append(element); + $animate.leave(element, $rootElement); + $rootScope.$digest(); + + expect(callbackTriggered).toBe(false); + })); + + it('leave : should fire a `start` callback when the animation starts with the matching element', + inject(function($animate, $rootScope, $$rAF, $rootElement, $document) { + + element = jqLite('
'); + + var capturedState; + var capturedElement; + $animate.on('leave', jqLite($document[0].body), function(element, phase) { + capturedState = phase; + capturedElement = element; + }); + + $rootElement.append(element); + $animate.leave(element, $rootElement); + $rootScope.$digest(); + $$rAF.flush(); + + expect(capturedState).toBe('start'); + expect(capturedElement).toBe(element); + })); + + it('leave : should fire a `close` callback when the animation ends with the matching element', + inject(function($animate, $rootScope, $$rAF, $rootElement, $document) { + + element = jqLite('
'); + + var capturedState; + var capturedElement; + $animate.on('leave', jqLite($document[0].body), function(element, phase) { + capturedState = phase; + capturedElement = element; + }); + + $rootElement.append(element); + var runner = $animate.leave(element, $rootElement); + $rootScope.$digest(); + runner.end(); + $$rAF.flush(); + + expect(capturedState).toBe('close'); + expect(capturedElement).toBe(element); + })); + }); });