@angular-wave/angular.ts 0.0.51 → 0.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/angular-ts.esm.js +2 -2
  2. package/dist/angular-ts.umd.js +2 -2
  3. package/package.json +1 -1
  4. package/src/animations/animate-children-directive.js +19 -99
  5. package/src/animations/animate-children-directive.md +80 -0
  6. package/src/animations/animate-css-driver.js +250 -256
  7. package/src/animations/animate-css.js +646 -875
  8. package/src/animations/animate-css.md +263 -0
  9. package/src/animations/animate-js-driver.js +54 -56
  10. package/src/animations/animate-js.js +303 -306
  11. package/src/animations/animate-queue.js +707 -716
  12. package/src/animations/animate-swap.js +30 -119
  13. package/src/animations/animate-swap.md +88 -0
  14. package/src/animations/animation.js +3 -3
  15. package/src/core/animate/animate-runner.js +147 -145
  16. package/src/core/animate/animate.js +568 -582
  17. package/src/core/animate/anomate.md +13 -0
  18. package/src/core/compile/compile.spec.js +5 -6
  19. package/src/core/core.html +0 -1
  20. package/src/directive/select/select.js +301 -305
  21. package/src/public.js +0 -1
  22. package/src/router/directives/state-directives.js +256 -574
  23. package/src/router/directives/state-directives.md +435 -0
  24. package/src/router/directives/view-directive.js +3 -3
  25. package/src/router/index.js +7 -7
  26. package/types/animations/animate-children-directive.d.ts +5 -80
  27. package/types/animations/animate-css-driver.d.ts +11 -0
  28. package/types/animations/animate-css.d.ts +8 -0
  29. package/types/animations/animate-js-driver.d.ts +8 -0
  30. package/types/animations/animate-js.d.ts +12 -0
  31. package/types/animations/animate-queue.d.ts +19 -0
  32. package/types/animations/animate-swap.d.ts +5 -89
  33. package/types/core/animate/animate-runner.d.ts +32 -0
  34. package/types/core/animate/animate.d.ts +509 -0
  35. package/types/directive/select/select.d.ts +79 -0
  36. package/types/router/directives/state-directives.d.ts +31 -0
  37. package/src/core/document.spec.js +0 -52
@@ -24,829 +24,820 @@ import {
24
24
 
25
25
  const NG_ANIMATE_ATTR_NAME = "data-ng-animate";
26
26
  const NG_ANIMATE_PIN_DATA = "$ngAnimatePin";
27
- export const $$AnimateQueueProvider = [
28
- "$animateProvider",
29
- function ($animateProvider) {
30
- const PRE_DIGEST_STATE = 1;
31
- const RUNNING_STATE = 2;
32
- const ONE_SPACE = " ";
33
-
34
- const rules = (this.rules = {
35
- skip: [],
36
- cancel: [],
37
- join: [],
38
- });
39
-
40
- function getEventData(options) {
41
- return {
42
- addClass: options.addClass,
43
- removeClass: options.removeClass,
44
- from: options.from,
45
- to: options.to,
46
- };
27
+ $$AnimateQueueProvider.$inject = ["$animateProvider"];
28
+ export function $$AnimateQueueProvider($animateProvider) {
29
+ const PRE_DIGEST_STATE = 1;
30
+ const RUNNING_STATE = 2;
31
+ const ONE_SPACE = " ";
32
+
33
+ const rules = (this.rules = {
34
+ skip: [],
35
+ cancel: [],
36
+ join: [],
37
+ });
38
+
39
+ function getEventData(options) {
40
+ return {
41
+ addClass: options.addClass,
42
+ removeClass: options.removeClass,
43
+ from: options.from,
44
+ to: options.to,
45
+ };
46
+ }
47
+
48
+ function makeTruthyCssClassMap(classString) {
49
+ if (!classString) {
50
+ return null;
47
51
  }
48
52
 
49
- function makeTruthyCssClassMap(classString) {
50
- if (!classString) {
51
- return null;
52
- }
53
-
54
- const keys = classString.split(ONE_SPACE);
55
- const map = Object.create(null);
56
-
57
- keys.forEach((key) => {
58
- map[key] = true;
59
- });
60
- return map;
61
- }
62
-
63
- function hasMatchingClasses(newClassString, currentClassString) {
64
- if (newClassString && currentClassString) {
65
- const currentClassMap = makeTruthyCssClassMap(currentClassString);
66
- return newClassString
67
- .split(ONE_SPACE)
68
- .some((className) => currentClassMap[className]);
69
- }
70
- }
71
-
72
- function isAllowed(ruleType, currentAnimation, previousAnimation) {
73
- return rules[ruleType].some((fn) =>
74
- fn(currentAnimation, previousAnimation),
75
- );
76
- }
53
+ const keys = classString.split(ONE_SPACE);
54
+ const map = Object.create(null);
77
55
 
78
- function hasAnimationClasses(animation, and) {
79
- const a = (animation.addClass || "").length > 0;
80
- const b = (animation.removeClass || "").length > 0;
81
- return and ? a && b : a || b;
56
+ keys.forEach((key) => {
57
+ map[key] = true;
58
+ });
59
+ return map;
60
+ }
61
+
62
+ function hasMatchingClasses(newClassString, currentClassString) {
63
+ if (newClassString && currentClassString) {
64
+ const currentClassMap = makeTruthyCssClassMap(currentClassString);
65
+ return newClassString
66
+ .split(ONE_SPACE)
67
+ .some((className) => currentClassMap[className]);
82
68
  }
69
+ }
83
70
 
84
- rules.join.push(
85
- (newAnimation) =>
86
- // if the new animation is class-based then we can just tack that on
87
- !newAnimation.structural && hasAnimationClasses(newAnimation),
88
- );
89
-
90
- rules.skip.push(
91
- (newAnimation) =>
92
- // there is no need to animate anything if no classes are being added and
93
- // there is no structural animation that will be triggered
94
- !newAnimation.structural && !hasAnimationClasses(newAnimation),
71
+ function isAllowed(ruleType, currentAnimation, previousAnimation) {
72
+ return rules[ruleType].some((fn) =>
73
+ fn(currentAnimation, previousAnimation),
95
74
  );
75
+ }
76
+
77
+ function hasAnimationClasses(animation, and) {
78
+ const a = (animation.addClass || "").length > 0;
79
+ const b = (animation.removeClass || "").length > 0;
80
+ return and ? a && b : a || b;
81
+ }
82
+
83
+ rules.join.push(
84
+ (newAnimation) =>
85
+ // if the new animation is class-based then we can just tack that on
86
+ !newAnimation.structural && hasAnimationClasses(newAnimation),
87
+ );
88
+
89
+ rules.skip.push(
90
+ (newAnimation) =>
91
+ // there is no need to animate anything if no classes are being added and
92
+ // there is no structural animation that will be triggered
93
+ !newAnimation.structural && !hasAnimationClasses(newAnimation),
94
+ );
95
+
96
+ rules.skip.push(
97
+ (newAnimation, currentAnimation) =>
98
+ // why should we trigger a new structural animation if the element will
99
+ // be removed from the DOM anyway?
100
+ currentAnimation.event === "leave" && newAnimation.structural,
101
+ );
102
+
103
+ rules.skip.push(
104
+ (newAnimation, currentAnimation) =>
105
+ // if there is an ongoing current animation then don't even bother running the class-based animation
106
+ currentAnimation.structural &&
107
+ currentAnimation.state === RUNNING_STATE &&
108
+ !newAnimation.structural,
109
+ );
110
+
111
+ rules.cancel.push(
112
+ (newAnimation, currentAnimation) =>
113
+ // there can never be two structural animations running at the same time
114
+ currentAnimation.structural && newAnimation.structural,
115
+ );
116
+
117
+ rules.cancel.push(
118
+ (newAnimation, currentAnimation) =>
119
+ // if the previous animation is already running, but the new animation will
120
+ // be triggered, but the new animation is structural
121
+ currentAnimation.state === RUNNING_STATE && newAnimation.structural,
122
+ );
123
+
124
+ rules.cancel.push((newAnimation, currentAnimation) => {
125
+ // cancel the animation if classes added / removed in both animation cancel each other out,
126
+ // but only if the current animation isn't structural
127
+
128
+ if (currentAnimation.structural) return false;
129
+
130
+ const nA = newAnimation.addClass;
131
+ const nR = newAnimation.removeClass;
132
+ const cA = currentAnimation.addClass;
133
+ const cR = currentAnimation.removeClass;
134
+
135
+ // early detection to save the global CPU shortage :)
136
+ if (
137
+ (isUndefined(nA) && isUndefined(nR)) ||
138
+ (isUndefined(cA) && isUndefined(cR))
139
+ ) {
140
+ return false;
141
+ }
96
142
 
97
- rules.skip.push(
98
- (newAnimation, currentAnimation) =>
99
- // why should we trigger a new structural animation if the element will
100
- // be removed from the DOM anyway?
101
- currentAnimation.event === "leave" && newAnimation.structural,
102
- );
143
+ return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA);
144
+ });
145
+
146
+ this.$get = [
147
+ "$rootScope",
148
+ "$rootElement",
149
+ "$document",
150
+ "$$animation",
151
+ "$$AnimateRunner",
152
+ "$templateRequest",
153
+ function (
154
+ $rootScope,
155
+ $rootElement,
156
+ $document,
157
+ $$animation,
158
+ $$AnimateRunner,
159
+ $templateRequest,
160
+ ) {
161
+ const activeAnimationsLookup = new Map();
162
+ const disabledElementsLookup = new Map();
163
+ let animationsEnabled = null;
164
+
165
+ function removeFromDisabledElementsLookup(evt) {
166
+ disabledElementsLookup.delete(evt.target);
167
+ }
103
168
 
104
- rules.skip.push(
105
- (newAnimation, currentAnimation) =>
106
- // if there is an ongoing current animation then don't even bother running the class-based animation
107
- currentAnimation.structural &&
108
- currentAnimation.state === RUNNING_STATE &&
109
- !newAnimation.structural,
110
- );
169
+ function postDigestTaskFactory() {
170
+ let postDigestCalled = false;
171
+ return function (fn) {
172
+ // we only issue a call to postDigest before
173
+ // it has first passed. This prevents any callbacks
174
+ // from not firing once the animation has completed
175
+ // since it will be out of the digest cycle.
176
+ if (postDigestCalled) {
177
+ fn();
178
+ } else {
179
+ $rootScope.$$postDigest(() => {
180
+ postDigestCalled = true;
181
+ fn();
182
+ });
183
+ }
184
+ };
185
+ }
111
186
 
112
- rules.cancel.push(
113
- (newAnimation, currentAnimation) =>
114
- // there can never be two structural animations running at the same time
115
- currentAnimation.structural && newAnimation.structural,
116
- );
187
+ // Wait until all directive and route-related templates are downloaded and
188
+ // compiled. The $templateRequest.totalPendingRequests variable keeps track of
189
+ // all of the remote templates being currently downloaded. If there are no
190
+ // templates currently downloading then the watcher will still fire anyway.
191
+ const deregisterWatch = $rootScope.$watch(
192
+ () => $templateRequest.totalPendingRequests === 0,
193
+ (isEmpty) => {
194
+ if (!isEmpty) return;
195
+ deregisterWatch();
196
+
197
+ // Now that all templates have been downloaded, $animate will wait until
198
+ // the post digest queue is empty before enabling animations. By having two
199
+ // calls to $postDigest calls we can ensure that the flag is enabled at the
200
+ // very end of the post digest queue. Since all of the animations in $animate
201
+ // use $postDigest, it's important that the code below executes at the end.
202
+ // This basically means that the page is fully downloaded and compiled before
203
+ // any animations are triggered.
204
+ $rootScope.$$postDigest(() => {
205
+ $rootScope.$$postDigest(() => {
206
+ // we check for null directly in the event that the application already called
207
+ // .enabled() with whatever arguments that it provided it with
208
+ if (animationsEnabled === null) {
209
+ animationsEnabled = true;
210
+ }
211
+ });
212
+ });
213
+ },
214
+ );
117
215
 
118
- rules.cancel.push(
119
- (newAnimation, currentAnimation) =>
120
- // if the previous animation is already running, but the new animation will
121
- // be triggered, but the new animation is structural
122
- currentAnimation.state === RUNNING_STATE && newAnimation.structural,
123
- );
216
+ const callbackRegistry = Object.create(null);
124
217
 
125
- rules.cancel.push((newAnimation, currentAnimation) => {
126
- // cancel the animation if classes added / removed in both animation cancel each other out,
127
- // but only if the current animation isn't structural
218
+ // remember that the `customFilter`/`classNameFilter` are set during the
219
+ // provider/config stage therefore we can optimize here and setup helper functions
220
+ const customFilter = $animateProvider.customFilter();
221
+ const classNameFilter = $animateProvider.classNameFilter();
222
+ const returnTrue = function () {
223
+ return true;
224
+ };
128
225
 
129
- if (currentAnimation.structural) return false;
226
+ const isAnimatableByFilter = customFilter || returnTrue;
227
+ const isAnimatableClassName = !classNameFilter
228
+ ? returnTrue
229
+ : function (node, options) {
230
+ const className = [
231
+ node.getAttribute("class"),
232
+ options.addClass,
233
+ options.removeClass,
234
+ ].join(" ");
235
+ return classNameFilter.test(className);
236
+ };
130
237
 
131
- const nA = newAnimation.addClass;
132
- const nR = newAnimation.removeClass;
133
- const cA = currentAnimation.addClass;
134
- const cR = currentAnimation.removeClass;
238
+ const applyAnimationClasses = applyAnimationClassesFactory();
135
239
 
136
- // early detection to save the global CPU shortage :)
137
- if (
138
- (isUndefined(nA) && isUndefined(nR)) ||
139
- (isUndefined(cA) && isUndefined(cR))
140
- ) {
141
- return false;
240
+ function normalizeAnimationDetails(element, animation) {
241
+ return mergeAnimationDetails(element, animation, {});
142
242
  }
143
243
 
144
- return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA);
145
- });
146
-
147
- this.$get = [
148
- "$rootScope",
149
- "$rootElement",
150
- "$document",
151
- "$$animation",
152
- "$$AnimateRunner",
153
- "$templateRequest",
154
- "$$isDocumentHidden",
155
- function (
156
- $rootScope,
157
- $rootElement,
158
- $document,
159
- $$animation,
160
- $$AnimateRunner,
161
- $templateRequest,
162
- $$isDocumentHidden,
163
- ) {
164
- const activeAnimationsLookup = new Map();
165
- const disabledElementsLookup = new Map();
166
- let animationsEnabled = null;
167
-
168
- function removeFromDisabledElementsLookup(evt) {
169
- disabledElementsLookup.delete(evt.target);
170
- }
244
+ // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
245
+ const contains =
246
+ window.Node.prototype.contains ||
247
+ function (arg) {
248
+ return this === arg || !!(this.compareDocumentPosition(arg) & 16);
249
+ };
171
250
 
172
- function postDigestTaskFactory() {
173
- let postDigestCalled = false;
174
- return function (fn) {
175
- // we only issue a call to postDigest before
176
- // it has first passed. This prevents any callbacks
177
- // from not firing once the animation has completed
178
- // since it will be out of the digest cycle.
179
- if (postDigestCalled) {
180
- fn();
181
- } else {
182
- $rootScope.$$postDigest(() => {
183
- postDigestCalled = true;
184
- fn();
185
- });
251
+ function findCallbacks(targetParentNode, targetNode, event) {
252
+ const matches = [];
253
+ const entries = callbackRegistry[event];
254
+ if (entries) {
255
+ entries.forEach((entry) => {
256
+ if (contains.call(entry.node, targetNode)) {
257
+ matches.push(entry.callback);
258
+ } else if (
259
+ event === "leave" &&
260
+ contains.call(entry.node, targetParentNode)
261
+ ) {
262
+ matches.push(entry.callback);
186
263
  }
187
- };
264
+ });
188
265
  }
189
266
 
190
- // Wait until all directive and route-related templates are downloaded and
191
- // compiled. The $templateRequest.totalPendingRequests variable keeps track of
192
- // all of the remote templates being currently downloaded. If there are no
193
- // templates currently downloading then the watcher will still fire anyway.
194
- const deregisterWatch = $rootScope.$watch(
195
- () => $templateRequest.totalPendingRequests === 0,
196
- (isEmpty) => {
197
- if (!isEmpty) return;
198
- deregisterWatch();
199
-
200
- // Now that all templates have been downloaded, $animate will wait until
201
- // the post digest queue is empty before enabling animations. By having two
202
- // calls to $postDigest calls we can ensure that the flag is enabled at the
203
- // very end of the post digest queue. Since all of the animations in $animate
204
- // use $postDigest, it's important that the code below executes at the end.
205
- // This basically means that the page is fully downloaded and compiled before
206
- // any animations are triggered.
207
- $rootScope.$$postDigest(() => {
208
- $rootScope.$$postDigest(() => {
209
- // we check for null directly in the event that the application already called
210
- // .enabled() with whatever arguments that it provided it with
211
- if (animationsEnabled === null) {
212
- animationsEnabled = true;
213
- }
214
- });
215
- });
216
- },
217
- );
218
-
219
- const callbackRegistry = Object.create(null);
267
+ return matches;
268
+ }
220
269
 
221
- // remember that the `customFilter`/`classNameFilter` are set during the
222
- // provider/config stage therefore we can optimize here and setup helper functions
223
- const customFilter = $animateProvider.customFilter();
224
- const classNameFilter = $animateProvider.classNameFilter();
225
- const returnTrue = function () {
226
- return true;
227
- };
270
+ function filterFromRegistry(list, matchContainer, matchCallback) {
271
+ const containerNode = extractElementNode(matchContainer);
272
+ return list.filter((entry) => {
273
+ const isMatch =
274
+ entry.node === containerNode &&
275
+ (!matchCallback || entry.callback === matchCallback);
276
+ return !isMatch;
277
+ });
278
+ }
228
279
 
229
- const isAnimatableByFilter = customFilter || returnTrue;
230
- const isAnimatableClassName = !classNameFilter
231
- ? returnTrue
232
- : function (node, options) {
233
- const className = [
234
- node.getAttribute("class"),
235
- options.addClass,
236
- options.removeClass,
237
- ].join(" ");
238
- return classNameFilter.test(className);
239
- };
240
-
241
- const applyAnimationClasses = applyAnimationClassesFactory();
242
-
243
- function normalizeAnimationDetails(element, animation) {
244
- return mergeAnimationDetails(element, animation, {});
280
+ function cleanupEventListeners(phase, node) {
281
+ if (phase === "close" && !node.parentNode) {
282
+ // If the element is not attached to a parentNode, it has been removed by
283
+ // the domOperation, and we can safely remove the event callbacks
284
+ $animate.off(node);
245
285
  }
286
+ }
246
287
 
247
- // IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
248
- const contains =
249
- window.Node.prototype.contains ||
250
- function (arg) {
251
- return this === arg || !!(this.compareDocumentPosition(arg) & 16);
252
- };
253
-
254
- function findCallbacks(targetParentNode, targetNode, event) {
255
- const matches = [];
256
- const entries = callbackRegistry[event];
257
- if (entries) {
258
- entries.forEach((entry) => {
259
- if (contains.call(entry.node, targetNode)) {
260
- matches.push(entry.callback);
261
- } else if (
262
- event === "leave" &&
263
- contains.call(entry.node, targetParentNode)
264
- ) {
265
- matches.push(entry.callback);
266
- }
267
- });
268
- }
288
+ let $animate = {
289
+ on(event, container, callback) {
290
+ const node = extractElementNode(container);
291
+ callbackRegistry[event] = callbackRegistry[event] || [];
292
+ callbackRegistry[event].push({
293
+ node,
294
+ callback,
295
+ });
269
296
 
270
- return matches;
271
- }
297
+ // Remove the callback when the element is removed from the DOM
298
+ JQLite(container).on("$destroy", () => {
299
+ const animationDetails = activeAnimationsLookup.get(node);
272
300
 
273
- function filterFromRegistry(list, matchContainer, matchCallback) {
274
- const containerNode = extractElementNode(matchContainer);
275
- return list.filter((entry) => {
276
- const isMatch =
277
- entry.node === containerNode &&
278
- (!matchCallback || entry.callback === matchCallback);
279
- return !isMatch;
301
+ if (!animationDetails) {
302
+ // If there's an animation ongoing, the callback calling code will remove
303
+ // the event listeners. If we'd remove here, the callbacks would be removed
304
+ // before the animation ends
305
+ $animate.off(event, container, callback);
306
+ }
280
307
  });
281
- }
308
+ },
309
+
310
+ off(event, container, callback) {
311
+ if (arguments.length === 1 && !isString(arguments[0])) {
312
+ container = arguments[0];
313
+ for (const eventType in callbackRegistry) {
314
+ callbackRegistry[eventType] = filterFromRegistry(
315
+ callbackRegistry[eventType],
316
+ container,
317
+ );
318
+ }
282
319
 
283
- function cleanupEventListeners(phase, node) {
284
- if (phase === "close" && !node.parentNode) {
285
- // If the element is not attached to a parentNode, it has been removed by
286
- // the domOperation, and we can safely remove the event callbacks
287
- $animate.off(node);
320
+ return;
288
321
  }
289
- }
290
-
291
- let $animate = {
292
- on(event, container, callback) {
293
- const node = extractElementNode(container);
294
- callbackRegistry[event] = callbackRegistry[event] || [];
295
- callbackRegistry[event].push({
296
- node,
297
- callback,
298
- });
299
-
300
- // Remove the callback when the element is removed from the DOM
301
- JQLite(container).on("$destroy", () => {
302
- const animationDetails = activeAnimationsLookup.get(node);
303
322
 
304
- if (!animationDetails) {
305
- // If there's an animation ongoing, the callback calling code will remove
306
- // the event listeners. If we'd remove here, the callbacks would be removed
307
- // before the animation ends
308
- $animate.off(event, container, callback);
309
- }
310
- });
311
- },
312
-
313
- off(event, container, callback) {
314
- if (arguments.length === 1 && !isString(arguments[0])) {
315
- container = arguments[0];
316
- for (const eventType in callbackRegistry) {
317
- callbackRegistry[eventType] = filterFromRegistry(
318
- callbackRegistry[eventType],
319
- container,
320
- );
321
- }
322
-
323
- return;
324
- }
323
+ const entries = callbackRegistry[event];
324
+ if (!entries) return;
325
+
326
+ callbackRegistry[event] =
327
+ arguments.length === 1
328
+ ? null
329
+ : filterFromRegistry(entries, container, callback);
330
+ },
331
+
332
+ pin(element, parentElement) {
333
+ assertArg(isElement(element), "element", "not an element");
334
+ assertArg(
335
+ isElement(parentElement),
336
+ "parentElement",
337
+ "not an element",
338
+ );
339
+ element.data(NG_ANIMATE_PIN_DATA, parentElement);
340
+ },
341
+
342
+ push(element, event, options, domOperation) {
343
+ options = options || {};
344
+ options.domOperation = domOperation;
345
+ return queueAnimation(element, event, options);
346
+ },
347
+
348
+ // this method has four signatures:
349
+ // () - global getter
350
+ // (bool) - global setter
351
+ // (element) - element getter
352
+ // (element, bool) - element setter<F37>
353
+ enabled(element, bool) {
354
+ const argCount = arguments.length;
355
+
356
+ if (argCount === 0) {
357
+ // () - Global getter
358
+ bool = !!animationsEnabled;
359
+ } else {
360
+ const hasElement = isElement(element);
325
361
 
326
- const entries = callbackRegistry[event];
327
- if (!entries) return;
328
-
329
- callbackRegistry[event] =
330
- arguments.length === 1
331
- ? null
332
- : filterFromRegistry(entries, container, callback);
333
- },
334
-
335
- pin(element, parentElement) {
336
- assertArg(isElement(element), "element", "not an element");
337
- assertArg(
338
- isElement(parentElement),
339
- "parentElement",
340
- "not an element",
341
- );
342
- element.data(NG_ANIMATE_PIN_DATA, parentElement);
343
- },
344
-
345
- push(element, event, options, domOperation) {
346
- options = options || {};
347
- options.domOperation = domOperation;
348
- return queueAnimation(element, event, options);
349
- },
350
-
351
- // this method has four signatures:
352
- // () - global getter
353
- // (bool) - global setter
354
- // (element) - element getter
355
- // (element, bool) - element setter<F37>
356
- enabled(element, bool) {
357
- const argCount = arguments.length;
358
-
359
- if (argCount === 0) {
360
- // () - Global getter
361
- bool = !!animationsEnabled;
362
+ if (!hasElement) {
363
+ // (bool) - Global setter
364
+ bool = animationsEnabled = !!element;
362
365
  } else {
363
- const hasElement = isElement(element);
366
+ const node = getDomNode(element);
364
367
 
365
- if (!hasElement) {
366
- // (bool) - Global setter
367
- bool = animationsEnabled = !!element;
368
+ if (argCount === 1) {
369
+ // (element) - Element getter
370
+ bool = !disabledElementsLookup.get(node);
368
371
  } else {
369
- const node = getDomNode(element);
370
-
371
- if (argCount === 1) {
372
- // (element) - Element getter
373
- bool = !disabledElementsLookup.get(node);
374
- } else {
375
- // (element, bool) - Element setter
376
- if (!disabledElementsLookup.has(node)) {
377
- // The element is added to the map for the first time.
378
- // Create a listener to remove it on `$destroy` (to avoid memory leak).
379
- JQLite(element).on(
380
- "$destroy",
381
- removeFromDisabledElementsLookup,
382
- );
383
- }
384
- disabledElementsLookup.set(node, !bool);
372
+ // (element, bool) - Element setter
373
+ if (!disabledElementsLookup.has(node)) {
374
+ // The element is added to the map for the first time.
375
+ // Create a listener to remove it on `$destroy` (to avoid memory leak).
376
+ JQLite(element).on(
377
+ "$destroy",
378
+ removeFromDisabledElementsLookup,
379
+ );
385
380
  }
381
+ disabledElementsLookup.set(node, !bool);
386
382
  }
387
383
  }
384
+ }
388
385
 
389
- return bool;
390
- },
391
- };
392
-
393
- return $animate;
386
+ return bool;
387
+ },
388
+ };
394
389
 
395
- function queueAnimation(originalElement, event, initialOptions) {
396
- // we always make a copy of the options since
397
- // there should never be any side effects on
398
- // the input data when running `$animateCss`.
399
- let options = structuredClone(initialOptions);
390
+ return $animate;
400
391
 
401
- let element = stripCommentsFromElement(originalElement);
402
- const node = getDomNode(element);
403
- const parentNode = node && node.parentNode;
392
+ function queueAnimation(originalElement, event, initialOptions) {
393
+ // we always make a copy of the options since
394
+ // there should never be any side effects on
395
+ // the input data when running `$animateCss`.
396
+ let options = structuredClone(initialOptions);
404
397
 
405
- options = prepareAnimationOptions(options);
398
+ let element = stripCommentsFromElement(originalElement);
399
+ const node = getDomNode(element);
400
+ const parentNode = node && node.parentNode;
406
401
 
407
- // we create a fake runner with a working promise.
408
- // These methods will become available after the digest has passed
409
- const runner = new $$AnimateRunner();
402
+ options = prepareAnimationOptions(options);
410
403
 
411
- // this is used to trigger callbacks in postDigest mode
412
- const runInNextPostDigestOrNow = postDigestTaskFactory();
404
+ // we create a fake runner with a working promise.
405
+ // These methods will become available after the digest has passed
406
+ const runner = new $$AnimateRunner();
413
407
 
414
- if (Array.isArray(options.addClass)) {
415
- options.addClass = options.addClass.join(" ");
416
- }
408
+ // this is used to trigger callbacks in postDigest mode
409
+ const runInNextPostDigestOrNow = postDigestTaskFactory();
417
410
 
418
- if (options.addClass && !isString(options.addClass)) {
419
- options.addClass = null;
420
- }
411
+ if (Array.isArray(options.addClass)) {
412
+ options.addClass = options.addClass.join(" ");
413
+ }
421
414
 
422
- if (Array.isArray(options.removeClass)) {
423
- options.removeClass = options.removeClass.join(" ");
424
- }
415
+ if (options.addClass && !isString(options.addClass)) {
416
+ options.addClass = null;
417
+ }
425
418
 
426
- if (options.removeClass && !isString(options.removeClass)) {
427
- options.removeClass = null;
428
- }
419
+ if (Array.isArray(options.removeClass)) {
420
+ options.removeClass = options.removeClass.join(" ");
421
+ }
429
422
 
430
- if (options.from && !isObject(options.from)) {
431
- options.from = null;
432
- }
423
+ if (options.removeClass && !isString(options.removeClass)) {
424
+ options.removeClass = null;
425
+ }
433
426
 
434
- if (options.to && !isObject(options.to)) {
435
- options.to = null;
436
- }
427
+ if (options.from && !isObject(options.from)) {
428
+ options.from = null;
429
+ }
437
430
 
438
- // If animations are hard-disabled for the whole application there is no need to continue.
439
- // There are also situations where a directive issues an animation for a JQLite wrapper that
440
- // contains only comment nodes. In this case, there is no way we can perform an animation.
441
- if (
442
- !animationsEnabled ||
443
- !node ||
444
- !isAnimatableByFilter(node, event, initialOptions) ||
445
- !isAnimatableClassName(node, options)
446
- ) {
447
- close();
448
- return runner;
449
- }
431
+ if (options.to && !isObject(options.to)) {
432
+ options.to = null;
433
+ }
450
434
 
451
- const isStructural = ["enter", "move", "leave"].indexOf(event) >= 0;
435
+ // If animations are hard-disabled for the whole application there is no need to continue.
436
+ // There are also situations where a directive issues an animation for a JQLite wrapper that
437
+ // contains only comment nodes. In this case, there is no way we can perform an animation.
438
+ if (
439
+ !animationsEnabled ||
440
+ !node ||
441
+ !isAnimatableByFilter(node, event, initialOptions) ||
442
+ !isAnimatableClassName(node, options)
443
+ ) {
444
+ close();
445
+ return runner;
446
+ }
452
447
 
453
- const documentHidden = $$isDocumentHidden();
448
+ const isStructural = ["enter", "move", "leave"].indexOf(event) >= 0;
449
+
450
+ // This is a hard disable of all animations the element itself, therefore there is no need to
451
+ // continue further past this point if not enabled
452
+ // Animations are also disabled if the document is currently hidden (page is not visible
453
+ // to the user), because browsers slow down or do not flush calls to requestAnimationFrame
454
+ let skipAnimations =
455
+ document.hidden || disabledElementsLookup.get(node);
456
+ const existingAnimation =
457
+ (!skipAnimations && activeAnimationsLookup.get(node)) || {};
458
+ const hasExistingAnimation = !!existingAnimation.state;
459
+
460
+ // there is no point in traversing the same collection of parent ancestors if a followup
461
+ // animation will be run on the same element that already did all that checking work
462
+ if (
463
+ !skipAnimations &&
464
+ (!hasExistingAnimation ||
465
+ existingAnimation.state !== PRE_DIGEST_STATE)
466
+ ) {
467
+ skipAnimations = !areAnimationsAllowed(node, parentNode);
468
+ }
454
469
 
455
- // This is a hard disable of all animations the element itself, therefore there is no need to
456
- // continue further past this point if not enabled
457
- // Animations are also disabled if the document is currently hidden (page is not visible
458
- // to the user), because browsers slow down or do not flush calls to requestAnimationFrame
459
- let skipAnimations =
460
- documentHidden || disabledElementsLookup.get(node);
461
- const existingAnimation =
462
- (!skipAnimations && activeAnimationsLookup.get(node)) || {};
463
- const hasExistingAnimation = !!existingAnimation.state;
470
+ if (skipAnimations) {
471
+ // Callbacks should fire even if the document is hidden (regression fix for issue #14120)
472
+ if (document.hidden)
473
+ notifyProgress(runner, event, "start", getEventData(options));
474
+ close();
475
+ if (document.hidden)
476
+ notifyProgress(runner, event, "close", getEventData(options));
477
+ return runner;
478
+ }
464
479
 
465
- // there is no point in traversing the same collection of parent ancestors if a followup
466
- // animation will be run on the same element that already did all that checking work
467
- if (
468
- !skipAnimations &&
469
- (!hasExistingAnimation ||
470
- existingAnimation.state !== PRE_DIGEST_STATE)
471
- ) {
472
- skipAnimations = !areAnimationsAllowed(node, parentNode);
473
- }
480
+ if (isStructural) {
481
+ closeChildAnimations(node);
482
+ }
474
483
 
475
- if (skipAnimations) {
476
- // Callbacks should fire even if the document is hidden (regression fix for issue #14120)
477
- if (documentHidden)
478
- notifyProgress(runner, event, "start", getEventData(options));
479
- close();
480
- if (documentHidden)
481
- notifyProgress(runner, event, "close", getEventData(options));
482
- return runner;
483
- }
484
+ const newAnimation = {
485
+ structural: isStructural,
486
+ element,
487
+ event,
488
+ addClass: options.addClass,
489
+ removeClass: options.removeClass,
490
+ close,
491
+ options,
492
+ runner,
493
+ };
484
494
 
485
- if (isStructural) {
486
- closeChildAnimations(node);
495
+ if (hasExistingAnimation) {
496
+ const skipAnimationFlag = isAllowed(
497
+ "skip",
498
+ newAnimation,
499
+ existingAnimation,
500
+ );
501
+ if (skipAnimationFlag) {
502
+ if (existingAnimation.state === RUNNING_STATE) {
503
+ close();
504
+ return runner;
505
+ }
506
+ mergeAnimationDetails(element, existingAnimation, newAnimation);
507
+ return existingAnimation.runner;
487
508
  }
488
-
489
- const newAnimation = {
490
- structural: isStructural,
491
- element,
492
- event,
493
- addClass: options.addClass,
494
- removeClass: options.removeClass,
495
- close,
496
- options,
497
- runner,
498
- };
499
-
500
- if (hasExistingAnimation) {
501
- const skipAnimationFlag = isAllowed(
502
- "skip",
503
- newAnimation,
504
- existingAnimation,
505
- );
506
- if (skipAnimationFlag) {
507
- if (existingAnimation.state === RUNNING_STATE) {
508
- close();
509
- return runner;
510
- }
509
+ const cancelAnimationFlag = isAllowed(
510
+ "cancel",
511
+ newAnimation,
512
+ existingAnimation,
513
+ );
514
+ if (cancelAnimationFlag) {
515
+ if (existingAnimation.state === RUNNING_STATE) {
516
+ // this will end the animation right away and it is safe
517
+ // to do so since the animation is already running and the
518
+ // runner callback code will run in async
519
+ existingAnimation.runner.end();
520
+ } else if (existingAnimation.structural) {
521
+ // this means that the animation is queued into a digest, but
522
+ // hasn't started yet. Therefore it is safe to run the close
523
+ // method which will call the runner methods in async.
524
+ existingAnimation.close();
525
+ } else {
526
+ // this will merge the new animation options into existing animation options
511
527
  mergeAnimationDetails(element, existingAnimation, newAnimation);
528
+
512
529
  return existingAnimation.runner;
513
530
  }
514
- const cancelAnimationFlag = isAllowed(
515
- "cancel",
531
+ } else {
532
+ // a joined animation means that this animation will take over the existing one
533
+ // so an example would involve a leave animation taking over an enter. Then when
534
+ // the postDigest kicks in the enter will be ignored.
535
+ const joinAnimationFlag = isAllowed(
536
+ "join",
516
537
  newAnimation,
517
538
  existingAnimation,
518
539
  );
519
- if (cancelAnimationFlag) {
540
+ if (joinAnimationFlag) {
520
541
  if (existingAnimation.state === RUNNING_STATE) {
521
- // this will end the animation right away and it is safe
522
- // to do so since the animation is already running and the
523
- // runner callback code will run in async
524
- existingAnimation.runner.end();
525
- } else if (existingAnimation.structural) {
526
- // this means that the animation is queued into a digest, but
527
- // hasn't started yet. Therefore it is safe to run the close
528
- // method which will call the runner methods in async.
529
- existingAnimation.close();
542
+ normalizeAnimationDetails(element, newAnimation);
530
543
  } else {
531
- // this will merge the new animation options into existing animation options
532
- mergeAnimationDetails(element, existingAnimation, newAnimation);
533
-
534
- return existingAnimation.runner;
535
- }
536
- } else {
537
- // a joined animation means that this animation will take over the existing one
538
- // so an example would involve a leave animation taking over an enter. Then when
539
- // the postDigest kicks in the enter will be ignored.
540
- const joinAnimationFlag = isAllowed(
541
- "join",
542
- newAnimation,
543
- existingAnimation,
544
- );
545
- if (joinAnimationFlag) {
546
- if (existingAnimation.state === RUNNING_STATE) {
547
- normalizeAnimationDetails(element, newAnimation);
548
- } else {
549
- applyGeneratedPreparationClasses(
550
- element,
551
- isStructural ? event : null,
552
- options,
553
- );
544
+ applyGeneratedPreparationClasses(
545
+ element,
546
+ isStructural ? event : null,
547
+ options,
548
+ );
554
549
 
555
- event = newAnimation.event = existingAnimation.event;
556
- options = mergeAnimationDetails(
557
- element,
558
- existingAnimation,
559
- newAnimation,
560
- );
550
+ event = newAnimation.event = existingAnimation.event;
551
+ options = mergeAnimationDetails(
552
+ element,
553
+ existingAnimation,
554
+ newAnimation,
555
+ );
561
556
 
562
- // we return the same runner since only the option values of this animation will
563
- // be fed into the `existingAnimation`.
564
- return existingAnimation.runner;
565
- }
557
+ // we return the same runner since only the option values of this animation will
558
+ // be fed into the `existingAnimation`.
559
+ return existingAnimation.runner;
566
560
  }
567
561
  }
568
- } else {
569
- // normalization in this case means that it removes redundant CSS classes that
570
- // already exist (addClass) or do not exist (removeClass) on the element
571
- normalizeAnimationDetails(element, newAnimation);
572
- }
573
-
574
- // when the options are merged and cleaned up we may end up not having to do
575
- // an animation at all, therefore we should check this before issuing a post
576
- // digest callback. Structural animations will always run no matter what.
577
- let isValidAnimation = newAnimation.structural;
578
- if (!isValidAnimation) {
579
- // animate (from/to) can be quickly checked first, otherwise we check if any classes are present
580
- isValidAnimation =
581
- (newAnimation.event === "animate" &&
582
- Object.keys(newAnimation.options.to || {}).length > 0) ||
583
- hasAnimationClasses(newAnimation);
584
562
  }
563
+ } else {
564
+ // normalization in this case means that it removes redundant CSS classes that
565
+ // already exist (addClass) or do not exist (removeClass) on the element
566
+ normalizeAnimationDetails(element, newAnimation);
567
+ }
585
568
 
586
- if (!isValidAnimation) {
587
- close();
588
- clearElementAnimationState(node);
589
- return runner;
590
- }
569
+ // when the options are merged and cleaned up we may end up not having to do
570
+ // an animation at all, therefore we should check this before issuing a post
571
+ // digest callback. Structural animations will always run no matter what.
572
+ let isValidAnimation = newAnimation.structural;
573
+ if (!isValidAnimation) {
574
+ // animate (from/to) can be quickly checked first, otherwise we check if any classes are present
575
+ isValidAnimation =
576
+ (newAnimation.event === "animate" &&
577
+ Object.keys(newAnimation.options.to || {}).length > 0) ||
578
+ hasAnimationClasses(newAnimation);
579
+ }
591
580
 
592
- // the counter keeps track of cancelled animations
593
- const counter = (existingAnimation.counter || 0) + 1;
594
- newAnimation.counter = counter;
581
+ if (!isValidAnimation) {
582
+ close();
583
+ clearElementAnimationState(node);
584
+ return runner;
585
+ }
595
586
 
596
- markElementAnimationState(node, PRE_DIGEST_STATE, newAnimation);
587
+ // the counter keeps track of cancelled animations
588
+ const counter = (existingAnimation.counter || 0) + 1;
589
+ newAnimation.counter = counter;
590
+
591
+ markElementAnimationState(node, PRE_DIGEST_STATE, newAnimation);
592
+
593
+ $rootScope.$$postDigest(() => {
594
+ // It is possible that the DOM nodes inside `originalElement` have been replaced. This can
595
+ // happen if the animated element is a transcluded clone and also has a `templateUrl`
596
+ // directive on it. Therefore, we must recreate `element` in order to interact with the
597
+ // actual DOM nodes.
598
+ // Note: We still need to use the old `node` for certain things, such as looking up in
599
+ // HashMaps where it was used as the key.
600
+
601
+ element = stripCommentsFromElement(originalElement);
602
+
603
+ let animationDetails = activeAnimationsLookup.get(node);
604
+ const animationCancelled = !animationDetails;
605
+ animationDetails = animationDetails || {};
606
+
607
+ // if addClass/removeClass is called before something like enter then the
608
+ // registered parent element may not be present. The code below will ensure
609
+ // that a final value for parent element is obtained
610
+ const parentElement = element.parent() || [];
611
+
612
+ // animate/structural/class-based animations all have requirements. Otherwise there
613
+ // is no point in performing an animation. The parent node must also be set.
614
+ const isValidAnimation =
615
+ parentElement.length > 0 &&
616
+ (animationDetails.event === "animate" ||
617
+ animationDetails.structural ||
618
+ hasAnimationClasses(animationDetails));
619
+
620
+ // this means that the previous animation was cancelled
621
+ // even if the follow-up animation is the same event
622
+ if (
623
+ animationCancelled ||
624
+ animationDetails.counter !== counter ||
625
+ !isValidAnimation
626
+ ) {
627
+ // if another animation did not take over then we need
628
+ // to make sure that the domOperation and options are
629
+ // handled accordingly
630
+ if (animationCancelled) {
631
+ applyAnimationClasses(element, options);
632
+ applyAnimationStyles(element, options);
633
+ }
597
634
 
598
- $rootScope.$$postDigest(() => {
599
- // It is possible that the DOM nodes inside `originalElement` have been replaced. This can
600
- // happen if the animated element is a transcluded clone and also has a `templateUrl`
601
- // directive on it. Therefore, we must recreate `element` in order to interact with the
602
- // actual DOM nodes.
603
- // Note: We still need to use the old `node` for certain things, such as looking up in
604
- // HashMaps where it was used as the key.
605
-
606
- element = stripCommentsFromElement(originalElement);
607
-
608
- let animationDetails = activeAnimationsLookup.get(node);
609
- const animationCancelled = !animationDetails;
610
- animationDetails = animationDetails || {};
611
-
612
- // if addClass/removeClass is called before something like enter then the
613
- // registered parent element may not be present. The code below will ensure
614
- // that a final value for parent element is obtained
615
- const parentElement = element.parent() || [];
616
-
617
- // animate/structural/class-based animations all have requirements. Otherwise there
618
- // is no point in performing an animation. The parent node must also be set.
619
- const isValidAnimation =
620
- parentElement.length > 0 &&
621
- (animationDetails.event === "animate" ||
622
- animationDetails.structural ||
623
- hasAnimationClasses(animationDetails));
624
-
625
- // this means that the previous animation was cancelled
626
- // even if the follow-up animation is the same event
635
+ // if the event changed from something like enter to leave then we do
636
+ // it, otherwise if it's the same then the end result will be the same too
627
637
  if (
628
638
  animationCancelled ||
629
- animationDetails.counter !== counter ||
630
- !isValidAnimation
639
+ (isStructural && animationDetails.event !== event)
631
640
  ) {
632
- // if another animation did not take over then we need
633
- // to make sure that the domOperation and options are
634
- // handled accordingly
635
- if (animationCancelled) {
636
- applyAnimationClasses(element, options);
637
- applyAnimationStyles(element, options);
638
- }
639
-
640
- // if the event changed from something like enter to leave then we do
641
- // it, otherwise if it's the same then the end result will be the same too
642
- if (
643
- animationCancelled ||
644
- (isStructural && animationDetails.event !== event)
645
- ) {
646
- options.domOperation();
647
- runner.end();
648
- }
649
-
650
- // in the event that the element animation was not cancelled or a follow-up animation
651
- // isn't allowed to animate from here then we need to clear the state of the element
652
- // so that any future animations won't read the expired animation data.
653
- if (!isValidAnimation) {
654
- clearElementAnimationState(node);
655
- }
641
+ options.domOperation();
642
+ runner.end();
643
+ }
656
644
 
657
- return;
645
+ // in the event that the element animation was not cancelled or a follow-up animation
646
+ // isn't allowed to animate from here then we need to clear the state of the element
647
+ // so that any future animations won't read the expired animation data.
648
+ if (!isValidAnimation) {
649
+ clearElementAnimationState(node);
658
650
  }
659
651
 
660
- // this combined multiple class to addClass / removeClass into a setClass event
661
- // so long as a structural event did not take over the animation
662
- event =
663
- !animationDetails.structural &&
664
- hasAnimationClasses(animationDetails, true)
665
- ? "setClass"
666
- : animationDetails.event;
667
-
668
- markElementAnimationState(node, RUNNING_STATE);
669
- const realRunner = $$animation(
670
- element,
671
- event,
672
- animationDetails.options,
673
- );
652
+ return;
653
+ }
674
654
 
675
- // this will update the runner's flow-control events based on
676
- // the `realRunner` object.
677
- runner.setHost(realRunner);
678
- notifyProgress(runner, event, "start", getEventData(options));
655
+ // this combined multiple class to addClass / removeClass into a setClass event
656
+ // so long as a structural event did not take over the animation
657
+ event =
658
+ !animationDetails.structural &&
659
+ hasAnimationClasses(animationDetails, true)
660
+ ? "setClass"
661
+ : animationDetails.event;
679
662
 
680
- realRunner.done((status) => {
681
- close(!status);
682
- const animationDetails = activeAnimationsLookup.get(node);
683
- if (animationDetails && animationDetails.counter === counter) {
684
- clearElementAnimationState(node);
685
- }
686
- notifyProgress(runner, event, "close", getEventData(options));
687
- });
663
+ markElementAnimationState(node, RUNNING_STATE);
664
+ const realRunner = $$animation(
665
+ element,
666
+ event,
667
+ animationDetails.options,
668
+ );
669
+
670
+ // this will update the runner's flow-control events based on
671
+ // the `realRunner` object.
672
+ runner.setHost(realRunner);
673
+ notifyProgress(runner, event, "start", getEventData(options));
674
+
675
+ realRunner.done((status) => {
676
+ close(!status);
677
+ const animationDetails = activeAnimationsLookup.get(node);
678
+ if (animationDetails && animationDetails.counter === counter) {
679
+ clearElementAnimationState(node);
680
+ }
681
+ notifyProgress(runner, event, "close", getEventData(options));
688
682
  });
683
+ });
689
684
 
690
- return runner;
685
+ return runner;
691
686
 
692
- function notifyProgress(runner, event, phase, data) {
693
- runInNextPostDigestOrNow(() => {
694
- const callbacks = findCallbacks(parentNode, node, event);
695
- if (callbacks.length) {
696
- callbacks.forEach((callback) => {
697
- callback(element, phase, data);
698
- });
699
- cleanupEventListeners(phase, node);
700
- } else {
701
- cleanupEventListeners(phase, node);
702
- }
703
- });
704
- runner.progress(event, phase, data);
705
- }
687
+ function notifyProgress(runner, event, phase, data) {
688
+ runInNextPostDigestOrNow(() => {
689
+ const callbacks = findCallbacks(parentNode, node, event);
690
+ if (callbacks.length) {
691
+ callbacks.forEach((callback) => {
692
+ callback(element, phase, data);
693
+ });
694
+ cleanupEventListeners(phase, node);
695
+ } else {
696
+ cleanupEventListeners(phase, node);
697
+ }
698
+ });
699
+ runner.progress(event, phase, data);
700
+ }
706
701
 
707
- function close(reject) {
708
- clearGeneratedClasses(element, options);
709
- applyAnimationClasses(element, options);
710
- applyAnimationStyles(element, options);
711
- options.domOperation();
712
- runner.complete(!reject);
713
- }
702
+ function close(reject) {
703
+ clearGeneratedClasses(element, options);
704
+ applyAnimationClasses(element, options);
705
+ applyAnimationStyles(element, options);
706
+ options.domOperation();
707
+ runner.complete(!reject);
714
708
  }
709
+ }
715
710
 
716
- function closeChildAnimations(node) {
717
- const children = node.querySelectorAll(`[${NG_ANIMATE_ATTR_NAME}]`);
718
- forEach(children, (child) => {
719
- const state = parseInt(
720
- child.getAttribute(NG_ANIMATE_ATTR_NAME),
721
- 10,
722
- );
723
- const animationDetails = activeAnimationsLookup.get(child);
724
- if (animationDetails) {
725
- switch (state) {
726
- case RUNNING_STATE:
727
- animationDetails.runner.end();
728
- /* falls through */
729
- case PRE_DIGEST_STATE:
730
- activeAnimationsLookup.delete(child);
731
- break;
732
- }
711
+ function closeChildAnimations(node) {
712
+ const children = node.querySelectorAll(`[${NG_ANIMATE_ATTR_NAME}]`);
713
+ forEach(children, (child) => {
714
+ const state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME), 10);
715
+ const animationDetails = activeAnimationsLookup.get(child);
716
+ if (animationDetails) {
717
+ switch (state) {
718
+ case RUNNING_STATE:
719
+ animationDetails.runner.end();
720
+ /* falls through */
721
+ case PRE_DIGEST_STATE:
722
+ activeAnimationsLookup.delete(child);
723
+ break;
733
724
  }
734
- });
735
- }
725
+ }
726
+ });
727
+ }
728
+
729
+ function clearElementAnimationState(node) {
730
+ node.removeAttribute(NG_ANIMATE_ATTR_NAME);
731
+ activeAnimationsLookup.delete(node);
732
+ }
736
733
 
737
- function clearElementAnimationState(node) {
738
- node.removeAttribute(NG_ANIMATE_ATTR_NAME);
739
- activeAnimationsLookup.delete(node);
734
+ /**
735
+ * This fn returns false if any of the following is true:
736
+ * a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
737
+ * b) a parent element has an ongoing structural animation, and animateChildren is false
738
+ * c) the element is not a child of the body
739
+ * d) the element is not a child of the $rootElement
740
+ */
741
+ function areAnimationsAllowed(node, parentNode) {
742
+ const bodyNode = $document[0].body;
743
+ const rootNode = getDomNode($rootElement);
744
+
745
+ let bodyNodeDetected = node === bodyNode || node.nodeName === "HTML";
746
+ let rootNodeDetected = node === rootNode;
747
+ let parentAnimationDetected = false;
748
+ let elementDisabled = disabledElementsLookup.get(node);
749
+ let animateChildren;
750
+
751
+ let parentHost = getOrSetCacheData(node, NG_ANIMATE_PIN_DATA);
752
+ if (parentHost) {
753
+ parentNode = getDomNode(parentHost);
740
754
  }
741
755
 
742
- /**
743
- * This fn returns false if any of the following is true:
744
- * a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
745
- * b) a parent element has an ongoing structural animation, and animateChildren is false
746
- * c) the element is not a child of the body
747
- * d) the element is not a child of the $rootElement
748
- */
749
- function areAnimationsAllowed(node, parentNode) {
750
- const bodyNode = $document[0].body;
751
- const rootNode = getDomNode($rootElement);
752
-
753
- let bodyNodeDetected = node === bodyNode || node.nodeName === "HTML";
754
- let rootNodeDetected = node === rootNode;
755
- let parentAnimationDetected = false;
756
- let elementDisabled = disabledElementsLookup.get(node);
757
- let animateChildren;
758
-
759
- let parentHost = getOrSetCacheData(node, NG_ANIMATE_PIN_DATA);
760
- if (parentHost) {
761
- parentNode = getDomNode(parentHost);
756
+ while (parentNode) {
757
+ if (!rootNodeDetected) {
758
+ // AngularJS doesn't want to attempt to animate elements outside of the application
759
+ // therefore we need to ensure that the rootElement is an ancestor of the current element
760
+ rootNodeDetected = parentNode === rootNode;
762
761
  }
763
762
 
764
- while (parentNode) {
765
- if (!rootNodeDetected) {
766
- // AngularJS doesn't want to attempt to animate elements outside of the application
767
- // therefore we need to ensure that the rootElement is an ancestor of the current element
768
- rootNodeDetected = parentNode === rootNode;
769
- }
763
+ if (parentNode.nodeType !== Node.ELEMENT_NODE) {
764
+ // no point in inspecting the #document element
765
+ break;
766
+ }
770
767
 
771
- if (parentNode.nodeType !== Node.ELEMENT_NODE) {
772
- // no point in inspecting the #document element
768
+ const details = activeAnimationsLookup.get(parentNode) || {};
769
+ // either an enter, leave or move animation will commence
770
+ // therefore we can't allow any animations to take place
771
+ // but if a parent animation is class-based then that's ok
772
+ if (!parentAnimationDetected) {
773
+ const parentNodeDisabled = disabledElementsLookup.get(parentNode);
774
+
775
+ if (parentNodeDisabled === true && elementDisabled !== false) {
776
+ // disable animations if the user hasn't explicitly enabled animations on the
777
+ // current element
778
+ elementDisabled = true;
779
+ // element is disabled via parent element, no need to check anything else
773
780
  break;
781
+ } else if (parentNodeDisabled === false) {
782
+ elementDisabled = false;
774
783
  }
784
+ parentAnimationDetected = details.structural;
785
+ }
775
786
 
776
- const details = activeAnimationsLookup.get(parentNode) || {};
777
- // either an enter, leave or move animation will commence
778
- // therefore we can't allow any animations to take place
779
- // but if a parent animation is class-based then that's ok
780
- if (!parentAnimationDetected) {
781
- const parentNodeDisabled = disabledElementsLookup.get(parentNode);
782
-
783
- if (parentNodeDisabled === true && elementDisabled !== false) {
784
- // disable animations if the user hasn't explicitly enabled animations on the
785
- // current element
786
- elementDisabled = true;
787
- // element is disabled via parent element, no need to check anything else
788
- break;
789
- } else if (parentNodeDisabled === false) {
790
- elementDisabled = false;
791
- }
792
- parentAnimationDetected = details.structural;
793
- }
794
-
795
- if (isUndefined(animateChildren) || animateChildren === true) {
796
- const value = getOrSetCacheData(
797
- parentNode,
798
- NG_ANIMATE_CHILDREN_DATA,
799
- );
800
- if (isDefined(value)) {
801
- animateChildren = value;
802
- }
787
+ if (isUndefined(animateChildren) || animateChildren === true) {
788
+ const value = getOrSetCacheData(
789
+ parentNode,
790
+ NG_ANIMATE_CHILDREN_DATA,
791
+ );
792
+ if (isDefined(value)) {
793
+ animateChildren = value;
803
794
  }
795
+ }
804
796
 
805
- // there is no need to continue traversing at this point
806
- if (parentAnimationDetected && animateChildren === false) break;
797
+ // there is no need to continue traversing at this point
798
+ if (parentAnimationDetected && animateChildren === false) break;
807
799
 
808
- if (!bodyNodeDetected) {
809
- // we also need to ensure that the element is or will be a part of the body element
810
- // otherwise it is pointless to even issue an animation to be rendered
811
- bodyNodeDetected = parentNode === bodyNode;
812
- }
800
+ if (!bodyNodeDetected) {
801
+ // we also need to ensure that the element is or will be a part of the body element
802
+ // otherwise it is pointless to even issue an animation to be rendered
803
+ bodyNodeDetected = parentNode === bodyNode;
804
+ }
813
805
 
814
- if (bodyNodeDetected && rootNodeDetected) {
815
- // If both body and root have been found, any other checks are pointless,
816
- // as no animation data should live outside the application
817
- break;
818
- }
806
+ if (bodyNodeDetected && rootNodeDetected) {
807
+ // If both body and root have been found, any other checks are pointless,
808
+ // as no animation data should live outside the application
809
+ break;
810
+ }
819
811
 
820
- if (!rootNodeDetected) {
821
- // If `rootNode` is not detected, check if `parentNode` is pinned to another element
822
- parentHost = getOrSetCacheData(parentNode, NG_ANIMATE_PIN_DATA);
823
- if (parentHost) {
824
- // The pin target element becomes the next parent element
825
- parentNode = getDomNode(parentHost);
826
- continue;
827
- }
812
+ if (!rootNodeDetected) {
813
+ // If `rootNode` is not detected, check if `parentNode` is pinned to another element
814
+ parentHost = getOrSetCacheData(parentNode, NG_ANIMATE_PIN_DATA);
815
+ if (parentHost) {
816
+ // The pin target element becomes the next parent element
817
+ parentNode = getDomNode(parentHost);
818
+ continue;
828
819
  }
829
-
830
- parentNode = parentNode.parentNode;
831
820
  }
832
821
 
833
- const allowAnimation =
834
- (!parentAnimationDetected || animateChildren) &&
835
- elementDisabled !== true;
836
- return allowAnimation && rootNodeDetected && bodyNodeDetected;
822
+ parentNode = parentNode.parentNode;
837
823
  }
838
824
 
839
- function markElementAnimationState(node, state, details) {
840
- details = details || {};
841
- details.state = state;
825
+ const allowAnimation =
826
+ (!parentAnimationDetected || animateChildren) &&
827
+ elementDisabled !== true;
828
+ return allowAnimation && rootNodeDetected && bodyNodeDetected;
829
+ }
830
+
831
+ function markElementAnimationState(node, state, details) {
832
+ details = details || {};
833
+ details.state = state;
842
834
 
843
- node.setAttribute(NG_ANIMATE_ATTR_NAME, state);
835
+ node.setAttribute(NG_ANIMATE_ATTR_NAME, state);
844
836
 
845
- const oldValue = activeAnimationsLookup.get(node);
846
- const newValue = oldValue ? extend(oldValue, details) : details;
847
- activeAnimationsLookup.set(node, newValue);
848
- }
849
- },
850
- ];
851
- },
852
- ];
837
+ const oldValue = activeAnimationsLookup.get(node);
838
+ const newValue = oldValue ? extend(oldValue, details) : details;
839
+ activeAnimationsLookup.set(node, newValue);
840
+ }
841
+ },
842
+ ];
843
+ }