feat(ngAnimate): let $animate.off() remove all listeners for an element

This commit is contained in:
Martin Staffa
2016-03-29 19:57:30 +02:00
parent c75fb80333
commit ea4120bf35
3 changed files with 86 additions and 10 deletions
+6 -1
View File
@@ -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);
*
@@ -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
*/
+18 -9
View File
@@ -199,6 +199,15 @@ 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;
});
}
var $animate = {
on: function(event, container, callback) {
var node = extractElementNode(container);
@@ -215,21 +224,21 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
},
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) {
+62
View File
@@ -1896,6 +1896,68 @@ describe("animations", function() {
expect(count).toBe(3);
}));
it('should remove all event listeners for an element when $animate.off(element) is called',
inject(function($animate, $rootScope, $rootElement, $document, $$rAF) {
element = jqLite('<div></div>');
var otherElement = jqLite('<div></div>');
$rootElement.append(otherElement);
var count = 0;
var runner;
$animate.on('enter', element, counter);
$animate.on('leave', element, counter);
$animate.on('addClass', element, counter);
$animate.on('addClass', otherElement, counter);
function counter(element, phase) {
count++;
}
runner = $animate.enter(element, $rootElement);
$rootScope.$digest();
$animate.flush();
runner.end();
runner = $animate.addClass(element, 'blue');
$rootScope.$digest();
$animate.flush();
runner.end();
$$rAF.flush();
expect(count).toBe(4);
$animate.off(element);
runner = $animate.enter(element, $rootElement);
$animate.flush();
expect(capturedAnimation[1]).toBe('enter');
runner.end();
runner = $animate.addClass(element, 'red');
$animate.flush();
expect(capturedAnimation[1]).toBe('addClass');
runner.end();
runner = $animate.leave(element);
$animate.flush();
expect(capturedAnimation[1]).toBe('leave');
runner.end();
// Try to flush all remaining callbacks
expect(function() {
$$rAF.flush();
}).toThrowError('No rAF callbacks present');
expect(count).toBe(4);
// Check that other elements' event listeners are not affected
$animate.addClass(otherElement, 'green');
$animate.flush();
expect(count).toBe(5);
}));
it('should fire a `start` callback when the animation starts with the matching element',
inject(function($animate, $rootScope, $rootElement, $document) {