Skip to content

Commit ea4120b

Browse files
committed
feat(ngAnimate): let $animate.off() remove all listeners for an element
1 parent c75fb80 commit ea4120b

File tree

3 files changed

+86
-10
lines changed

3 files changed

+86
-10
lines changed

src/ng/animate.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ var $AnimateProvider = ['$provide', function($provide) {
326326
* // remove all the animation event listeners listening for `enter`
327327
* $animate.off('enter');
328328
*
329+
* // remove listeners for all animation events from the container element
330+
* $animate.off(container);
331+
*
329332
* // remove all the animation event listeners listening for `enter` on the given element and its children
330333
* $animate.off('enter', container);
331334
*
@@ -334,7 +337,9 @@ var $AnimateProvider = ['$provide', function($provide) {
334337
* $animate.off('enter', container, callback);
335338
* ```
336339
*
337-
* @param {string} event the animation event (e.g. enter, leave, move, addClass, removeClass, etc...)
340+
* @param {string|DOMElement} event|container the animation event (e.g. enter, leave, move,
341+
* addClass, removeClass, etc...), or the container element. If it is the element, all other
342+
* arguments are ignored.
338343
* @param {DOMElement=} container the container element the event listener was placed on
339344
* @param {Function=} callback the callback function that was registered as the listener
340345
*/

src/ngAnimate/animateQueue.js

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,15 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
199199
return matches;
200200
}
201201

202+
function filterFromRegistry(list, matchContainer, matchCallback) {
203+
var containerNode = extractElementNode(matchContainer);
204+
return list.filter(function(entry) {
205+
var isMatch = entry.node === containerNode &&
206+
(!matchCallback || entry.callback === matchCallback);
207+
return !isMatch;
208+
});
209+
}
210+
202211
var $animate = {
203212
on: function(event, container, callback) {
204213
var node = extractElementNode(container);
@@ -215,21 +224,21 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
215224
},
216225

217226
off: function(event, container, callback) {
227+
if (arguments.length === 1 && !angular.isString(arguments[0])) {
228+
container = arguments[0];
229+
for (var eventType in callbackRegistry) {
230+
callbackRegistry[eventType] = filterFromRegistry(callbackRegistry[eventType], container);
231+
}
232+
233+
return;
234+
}
235+
218236
var entries = callbackRegistry[event];
219237
if (!entries) return;
220238

221239
callbackRegistry[event] = arguments.length === 1
222240
? null
223241
: filterFromRegistry(entries, container, callback);
224-
225-
function filterFromRegistry(list, matchContainer, matchCallback) {
226-
var containerNode = extractElementNode(matchContainer);
227-
return list.filter(function(entry) {
228-
var isMatch = entry.node === containerNode &&
229-
(!matchCallback || entry.callback === matchCallback);
230-
return !isMatch;
231-
});
232-
}
233242
},
234243

235244
pin: function(element, parentElement) {

test/ngAnimate/animateSpec.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,68 @@ describe("animations", function() {
18961896
expect(count).toBe(3);
18971897
}));
18981898

1899+
it('should remove all event listeners for an element when $animate.off(element) is called',
1900+
inject(function($animate, $rootScope, $rootElement, $document, $$rAF) {
1901+
1902+
element = jqLite('<div></div>');
1903+
var otherElement = jqLite('<div></div>');
1904+
$rootElement.append(otherElement);
1905+
1906+
var count = 0;
1907+
var runner;
1908+
$animate.on('enter', element, counter);
1909+
$animate.on('leave', element, counter);
1910+
$animate.on('addClass', element, counter);
1911+
$animate.on('addClass', otherElement, counter);
1912+
1913+
function counter(element, phase) {
1914+
count++;
1915+
}
1916+
1917+
runner = $animate.enter(element, $rootElement);
1918+
$rootScope.$digest();
1919+
$animate.flush();
1920+
runner.end();
1921+
1922+
runner = $animate.addClass(element, 'blue');
1923+
$rootScope.$digest();
1924+
$animate.flush();
1925+
1926+
runner.end();
1927+
$$rAF.flush();
1928+
1929+
expect(count).toBe(4);
1930+
1931+
$animate.off(element);
1932+
1933+
runner = $animate.enter(element, $rootElement);
1934+
$animate.flush();
1935+
expect(capturedAnimation[1]).toBe('enter');
1936+
runner.end();
1937+
1938+
runner = $animate.addClass(element, 'red');
1939+
$animate.flush();
1940+
expect(capturedAnimation[1]).toBe('addClass');
1941+
runner.end();
1942+
1943+
runner = $animate.leave(element);
1944+
$animate.flush();
1945+
expect(capturedAnimation[1]).toBe('leave');
1946+
runner.end();
1947+
1948+
// Try to flush all remaining callbacks
1949+
expect(function() {
1950+
$$rAF.flush();
1951+
}).toThrowError('No rAF callbacks present');
1952+
1953+
expect(count).toBe(4);
1954+
1955+
// Check that other elements' event listeners are not affected
1956+
$animate.addClass(otherElement, 'green');
1957+
$animate.flush();
1958+
expect(count).toBe(5);
1959+
}));
1960+
18991961
it('should fire a `start` callback when the animation starts with the matching element',
19001962
inject(function($animate, $rootScope, $rootElement, $document) {
19011963

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy