Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Fix animation event regression #14340

Merged
merged 2 commits into from
Apr 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/ng/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,9 @@ var $AnimateProvider = ['$provide', function($provide) {
* // remove all the animation event listeners listening for `enter`
* $animate.off('enter');
*
* // remove listeners for all animation events from the container element
* $animate.off(container);
*
* // remove all the animation event listeners listening for `enter` on the given element and its children
* $animate.off('enter', container);
*
Expand All @@ -334,7 +337,9 @@ var $AnimateProvider = ['$provide', function($provide) {
* $animate.off('enter', container, callback);
* ```
*
* @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
* @param {string|DOMElement} event|container the animation event (e.g. enter, leave, move,
* addClass, removeClass, etc...), or the container element. If it is the element, all other
* arguments are ignored.
* @param {DOMElement=} container the container element the event listener was placed on
* @param {Function=} callback the callback function that was registered as the listener
*/
Expand Down
47 changes: 37 additions & 10 deletions src/ngAnimate/animateQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,23 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
return matches;
}

function filterFromRegistry(list, matchContainer, matchCallback) {
var containerNode = extractElementNode(matchContainer);
return list.filter(function(entry) {
var isMatch = entry.node === containerNode &&
(!matchCallback || entry.callback === matchCallback);
return !isMatch;
});
}

function cleanupEventListeners(phase, element) {
if (phase === 'close' && !element[0].parentNode) {
// If the element is not attached to a parentNode, it has been removed by
// the domOperation, and we can safely remove the event callbacks
$animate.off(element);
}
}

var $animate = {
on: function(event, container, callback) {
var node = extractElementNode(container);
Expand All @@ -210,26 +227,33 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {

// Remove the callback when the element is removed from the DOM
jqLite(container).on('$destroy', function() {
$animate.off(event, container, callback);
var animationDetails = activeAnimationsLookup.get(node);

if (!animationDetails) {
// If there's an animation ongoing, the callback calling code will remove
// the event listeners. If we'd remove here, the callbacks would be removed
// before the animation ends
$animate.off(event, container, callback);
}
});
},

off: function(event, container, callback) {
if (arguments.length === 1 && !angular.isString(arguments[0])) {
container = arguments[0];
for (var eventType in callbackRegistry) {
callbackRegistry[eventType] = filterFromRegistry(callbackRegistry[eventType], container);
}

return;
}

var entries = callbackRegistry[event];
if (!entries) return;

callbackRegistry[event] = arguments.length === 1
? null
: filterFromRegistry(entries, container, callback);

function filterFromRegistry(list, matchContainer, matchCallback) {
var containerNode = extractElementNode(matchContainer);
return list.filter(function(entry) {
var isMatch = entry.node === containerNode &&
(!matchCallback || entry.callback === matchCallback);
return !isMatch;
});
}
},

pin: function(element, parentElement) {
Expand Down Expand Up @@ -543,7 +567,10 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
forEach(callbacks, function(callback) {
callback(element, phase, data);
});
cleanupEventListeners(phase, element);
});
} else {
cleanupEventListeners(phase, element);
}
});
runner.progress(event, phase, data);
Expand Down
Loading