diff --git a/src/ngAnimate/animateQueue.js b/src/ngAnimate/animateQueue.js index 374377de8b6e..e1b833ca2d83 100644 --- a/src/ngAnimate/animateQueue.js +++ b/src/ngAnimate/animateQueue.js @@ -124,8 +124,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]; @@ -133,6 +134,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); } }); } @@ -140,9 +143,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { return matches; } - function triggerCallback(event, element, phase, data) { + function triggerCallback(event, parent, element, phase, data) { $$rAF(function() { - forEach(findCallbacks(element, event), function(callback) { + forEach(findCallbacks(parent, element, event), function(callback) { callback(element, phase, data); }); }); @@ -455,7 +458,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) { return runner; function notifyProgress(runner, event, phase, data) { - triggerCallback(event, element, phase, data); + triggerCallback(event, parent, element, phase, data); runner.progress(event, phase, data); } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 61810a891819..2ce990ed4966 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -1646,5 +1646,87 @@ describe("animations", function() { expect(count).toBe(1); })); + it('Leave : should trigger a callback for an leave animation', + inject(function($animate, $rootScope, $$rAF, $rootElement) { + + var callbackTriggered = false; + $animate.on('leave', 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(); + $$rAF.flush(); + + 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) { + + element = jqLite(''); + + var capturedState; + var capturedElement; + $animate.on('leave', 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) { + + element = jqLite(''); + + var capturedState; + var capturedElement; + $animate.on('leave', 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); + })); + }); });