@angular-wave/angular.ts 0.0.51 → 0.0.53
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.
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/src/animations/animate-children-directive.js +19 -99
- package/src/animations/animate-children-directive.md +80 -0
- package/src/animations/animate-css-driver.js +250 -256
- package/src/animations/animate-css.js +646 -875
- package/src/animations/animate-css.md +263 -0
- package/src/animations/animate-js-driver.js +54 -56
- package/src/animations/animate-js.js +303 -306
- package/src/animations/animate-queue.js +707 -716
- package/src/animations/animate-swap.js +30 -119
- package/src/animations/animate-swap.md +88 -0
- package/src/animations/animation.js +3 -3
- package/src/core/animate/animate-css.js +21 -6
- package/src/core/animate/animate-runner.js +147 -145
- package/src/core/animate/animate.js +572 -585
- package/src/core/animate/animate.spec.js +194 -286
- package/src/core/animate/anomate.md +13 -0
- package/src/core/animate/helpers.js +10 -0
- package/src/core/compile/compile.spec.js +5 -6
- package/src/core/core.html +0 -1
- package/src/directive/select/select.js +301 -305
- package/src/public.js +0 -1
- package/src/router/directives/state-directives.js +256 -574
- package/src/router/directives/state-directives.md +435 -0
- package/src/router/directives/view-directive.js +3 -3
- package/src/router/index.js +7 -7
- package/types/animations/animate-children-directive.d.ts +5 -80
- package/types/animations/animate-css-driver.d.ts +11 -0
- package/types/animations/animate-css.d.ts +8 -0
- package/types/animations/animate-js-driver.d.ts +8 -0
- package/types/animations/animate-js.d.ts +12 -0
- package/types/animations/animate-queue.d.ts +19 -0
- package/types/animations/animate-swap.d.ts +5 -89
- package/types/core/animate/animate-css.d.ts +1 -1
- package/types/core/animate/animate-runner.d.ts +32 -0
- package/types/core/animate/animate.d.ts +509 -0
- package/types/core/animate/helpers.d.ts +8 -0
- package/types/directive/select/select.d.ts +79 -0
- package/types/router/directives/state-directives.d.ts +31 -0
- package/src/core/document.spec.js +0 -52
|
@@ -32,220 +32,6 @@ import {
|
|
|
32
32
|
|
|
33
33
|
const ANIMATE_TIMER_KEY = "$$animateCss";
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
* @ngdoc service
|
|
37
|
-
* @name $animateCss
|
|
38
|
-
* @kind object
|
|
39
|
-
*
|
|
40
|
-
* @description
|
|
41
|
-
* The `$animateCss` service is a useful utility to trigger customized CSS-based transitions/keyframes
|
|
42
|
-
* from a JavaScript-based animation or directly from a directive. The purpose of `$animateCss` is NOT
|
|
43
|
-
* to side-step how `$animate` and ngAnimate work, but the goal is to allow pre-existing animations or
|
|
44
|
-
* directives to create more complex animations that can be purely driven using CSS code.
|
|
45
|
-
*
|
|
46
|
-
* Note that only browsers that support CSS transitions and/or keyframe animations are capable of
|
|
47
|
-
* rendering animations triggered via `$animateCss` (bad news for IE9 and lower).
|
|
48
|
-
*
|
|
49
|
-
* ## General Use
|
|
50
|
-
* Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that
|
|
51
|
-
* is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however,
|
|
52
|
-
* any automatic control over cancelling animations and/or preventing animations from being run on
|
|
53
|
-
* child elements will not be handled by AngularJS. For this to work as expected, please use `$animate` to
|
|
54
|
-
* trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger
|
|
55
|
-
* the CSS animation.
|
|
56
|
-
*
|
|
57
|
-
* The example below shows how we can create a folding animation on an element using `ng-if`:
|
|
58
|
-
*
|
|
59
|
-
* ```html
|
|
60
|
-
* <!-- notice the `fold-animation` CSS class -->
|
|
61
|
-
* <div ng-if="onOff" class="fold-animation">
|
|
62
|
-
* This element will go BOOM
|
|
63
|
-
* </div>
|
|
64
|
-
* <button ng-click="onOff=true">Fold In</button>
|
|
65
|
-
* ```
|
|
66
|
-
*
|
|
67
|
-
* Now we create the **JavaScript animation** that will trigger the CSS transition:
|
|
68
|
-
*
|
|
69
|
-
* ```js
|
|
70
|
-
* ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
|
|
71
|
-
* return {
|
|
72
|
-
* enter: function(element, doneFn) {
|
|
73
|
-
* let height = element[0].offsetHeight;
|
|
74
|
-
* return $animateCss(element, {
|
|
75
|
-
* from: { height:'0px' },
|
|
76
|
-
* to: { height:height + 'px' },
|
|
77
|
-
* duration: 1 // one second
|
|
78
|
-
* });
|
|
79
|
-
* }
|
|
80
|
-
* }
|
|
81
|
-
* }]);
|
|
82
|
-
* ```
|
|
83
|
-
*
|
|
84
|
-
* ## More Advanced Uses
|
|
85
|
-
*
|
|
86
|
-
* `$animateCss` is the underlying code that ngAnimate uses to power **CSS-based animations** behind the scenes. Therefore CSS hooks
|
|
87
|
-
* like `.ng-EVENT`, `.ng-EVENT-active`, `.ng-EVENT-stagger` are all features that can be triggered using `$animateCss` via JavaScript code.
|
|
88
|
-
*
|
|
89
|
-
* This also means that just about any combination of adding classes, removing classes, setting styles, dynamically setting a keyframe animation,
|
|
90
|
-
* applying a hardcoded duration or delay value, changing the animation easing or applying a stagger animation are all options that work with
|
|
91
|
-
* `$animateCss`. The service itself is smart enough to figure out the combination of options and examine the element styling properties in order
|
|
92
|
-
* to provide a working animation that will run in CSS.
|
|
93
|
-
*
|
|
94
|
-
* The example below showcases a more advanced version of the `.fold-animation` from the example above:
|
|
95
|
-
*
|
|
96
|
-
* ```js
|
|
97
|
-
* ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
|
|
98
|
-
* return {
|
|
99
|
-
* enter: function(element, doneFn) {
|
|
100
|
-
* let height = element[0].offsetHeight;
|
|
101
|
-
* return $animateCss(element, {
|
|
102
|
-
* addClass: 'red large-text pulse-twice',
|
|
103
|
-
* easing: 'ease-out',
|
|
104
|
-
* from: { height:'0px' },
|
|
105
|
-
* to: { height:height + 'px' },
|
|
106
|
-
* duration: 1 // one second
|
|
107
|
-
* });
|
|
108
|
-
* }
|
|
109
|
-
* }
|
|
110
|
-
* }]);
|
|
111
|
-
* ```
|
|
112
|
-
*
|
|
113
|
-
* Since we're adding/removing CSS classes then the CSS transition will also pick those up:
|
|
114
|
-
*
|
|
115
|
-
* ```css
|
|
116
|
-
* /* since a hardcoded duration value of 1 was provided in the JavaScript animation code,
|
|
117
|
-
* the CSS classes below will be transitioned despite them being defined as regular CSS classes */
|
|
118
|
-
* .red { background:red; }
|
|
119
|
-
* .large-text { font-size:20px; }
|
|
120
|
-
*
|
|
121
|
-
* /* we can also use a keyframe animation and $animateCss will make it work alongside the transition */
|
|
122
|
-
* .pulse-twice {
|
|
123
|
-
* animation: 0.5s pulse linear 2;
|
|
124
|
-
* -webkit-animation: 0.5s pulse linear 2;
|
|
125
|
-
* }
|
|
126
|
-
*
|
|
127
|
-
* @keyframes pulse {
|
|
128
|
-
* from { transform: scale(0.5); }
|
|
129
|
-
* to { transform: scale(1.5); }
|
|
130
|
-
* }
|
|
131
|
-
*
|
|
132
|
-
* @-webkit-keyframes pulse {
|
|
133
|
-
* from { -webkit-transform: scale(0.5); }
|
|
134
|
-
* to { -webkit-transform: scale(1.5); }
|
|
135
|
-
* }
|
|
136
|
-
* ```
|
|
137
|
-
*
|
|
138
|
-
* Given this complex combination of CSS classes, styles and options, `$animateCss` will figure everything out and make the animation happen.
|
|
139
|
-
*
|
|
140
|
-
* ## How the Options are handled
|
|
141
|
-
*
|
|
142
|
-
* `$animateCss` is very versatile and intelligent when it comes to figuring out what configurations to apply to the element to ensure the animation
|
|
143
|
-
* works with the options provided. Say for example we were adding a class that contained a keyframe value and we wanted to also animate some inline
|
|
144
|
-
* styles using the `from` and `to` properties.
|
|
145
|
-
*
|
|
146
|
-
* ```js
|
|
147
|
-
* let animator = $animateCss(element, {
|
|
148
|
-
* from: { background:'red' },
|
|
149
|
-
* to: { background:'blue' }
|
|
150
|
-
* });
|
|
151
|
-
* animator.start();
|
|
152
|
-
* ```
|
|
153
|
-
*
|
|
154
|
-
* ```css
|
|
155
|
-
* .rotating-animation {
|
|
156
|
-
* animation:0.5s rotate linear;
|
|
157
|
-
* -webkit-animation:0.5s rotate linear;
|
|
158
|
-
* }
|
|
159
|
-
*
|
|
160
|
-
* @keyframes rotate {
|
|
161
|
-
* from { transform: rotate(0deg); }
|
|
162
|
-
* to { transform: rotate(360deg); }
|
|
163
|
-
* }
|
|
164
|
-
*
|
|
165
|
-
* @-webkit-keyframes rotate {
|
|
166
|
-
* from { -webkit-transform: rotate(0deg); }
|
|
167
|
-
* to { -webkit-transform: rotate(360deg); }
|
|
168
|
-
* }
|
|
169
|
-
* ```
|
|
170
|
-
*
|
|
171
|
-
* The missing pieces here are that we do not have a transition set (within the CSS code nor within the `$animateCss` options) and the duration of the animation is
|
|
172
|
-
* going to be detected from what the keyframe styles on the CSS class are. In this event, `$animateCss` will automatically create an inline transition
|
|
173
|
-
* style matching the duration detected from the keyframe style (which is present in the CSS class that is being added) and then prepare both the transition
|
|
174
|
-
* and keyframe animations to run in parallel on the element. Then when the animation is underway the provided `from` and `to` CSS styles will be applied
|
|
175
|
-
* and spread across the transition and keyframe animation.
|
|
176
|
-
*
|
|
177
|
-
* ## What is returned
|
|
178
|
-
*
|
|
179
|
-
* `$animateCss` works in two stages: a preparation phase and an animation phase. Therefore when `$animateCss` is first called it will NOT actually
|
|
180
|
-
* start the animation. All that is going on here is that the element is being prepared for the animation (which means that the generated CSS classes are
|
|
181
|
-
* added and removed on the element). Once `$animateCss` is called it will return an object with the following properties:
|
|
182
|
-
*
|
|
183
|
-
* ```js
|
|
184
|
-
* let animator = $animateCss(element, { ... });
|
|
185
|
-
* ```
|
|
186
|
-
*
|
|
187
|
-
* Now what do the contents of our `animator` variable look like:
|
|
188
|
-
*
|
|
189
|
-
* ```js
|
|
190
|
-
* {
|
|
191
|
-
* // starts the animation
|
|
192
|
-
* start: Function,
|
|
193
|
-
*
|
|
194
|
-
* // ends (aborts) the animation
|
|
195
|
-
* end: Function
|
|
196
|
-
* }
|
|
197
|
-
* ```
|
|
198
|
-
*
|
|
199
|
-
* To actually start the animation we need to run `animation.start()` which will then return a promise that we can hook into to detect when the animation ends.
|
|
200
|
-
* If we choose not to run the animation then we MUST run `animation.end()` to perform a cleanup on the element (since some CSS classes and styles may have been
|
|
201
|
-
* applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
|
|
202
|
-
* and that changing them will not reconfigure the parameters of the animation.
|
|
203
|
-
*
|
|
204
|
-
* ### runner.done() vs runner.then()
|
|
205
|
-
* It is documented that `animation.start()` will return a promise object and this is true, however, there is also an additional method available on the
|
|
206
|
-
* runner called `.done(callbackFn)`. The done method works the same as `.finally(callbackFn)`, however, it does **not trigger a digest to occur**.
|
|
207
|
-
* Therefore, for performance reasons, it's always best to use `runner.done(callback)` instead of `runner.then()`, `runner.catch()` or `runner.finally()`
|
|
208
|
-
* unless you really need a digest to kick off afterwards.
|
|
209
|
-
*
|
|
210
|
-
* Keep in mind that, to make this easier, ngAnimate has tweaked the JS animations API to recognize when a runner instance is returned from $animateCss
|
|
211
|
-
* (so there is no need to call `runner.done(doneFn)` inside of your JavaScript animation code).
|
|
212
|
-
* Check the {@link ngAnimate.$animateCss#usage animation code above} to see how this works.
|
|
213
|
-
*
|
|
214
|
-
* @param {Element} element the element that will be animated
|
|
215
|
-
* @param {object} options the animation-related options that will be applied during the animation
|
|
216
|
-
*
|
|
217
|
-
* * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
|
|
218
|
-
* to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
|
|
219
|
-
* * `structural` - Indicates that the `ng-` prefix will be added to the event class. Setting to `false` or omitting will turn `ng-EVENT` and
|
|
220
|
-
* `ng-EVENT-active` in `EVENT` and `EVENT-active`. Unused if `event` is omitted.
|
|
221
|
-
* * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
|
|
222
|
-
* * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`).
|
|
223
|
-
* * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
|
|
224
|
-
* * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation.
|
|
225
|
-
* * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition.
|
|
226
|
-
* * `addClass` - A space separated list of CSS classes that will be added to the element and spread across the animation.
|
|
227
|
-
* * `removeClass` - A space separated list of CSS classes that will be removed from the element and spread across the animation.
|
|
228
|
-
* * `duration` - A number value representing the total duration of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `0`
|
|
229
|
-
* is provided then the animation will be skipped entirely.
|
|
230
|
-
* * `delay` - A number value representing the total delay of the transition and/or keyframe (note that a value of 1 is 1000ms). If a value of `true` is
|
|
231
|
-
* used then whatever delay value is detected from the CSS classes will be mirrored on the elements styles (e.g. by setting delay true then the style value
|
|
232
|
-
* of the element will be `transition-delay: DETECTED_VALUE`). Using `true` is useful when you want the CSS classes and inline styles to all share the same
|
|
233
|
-
* CSS delay value.
|
|
234
|
-
* * `stagger` - A numeric time value representing the delay between successively animated elements
|
|
235
|
-
* ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.})
|
|
236
|
-
* * `staggerIndex` - The numeric index representing the stagger item (e.g. a value of 5 is equal to the sixth item in the stagger; therefore when a
|
|
237
|
-
* `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
|
|
238
|
-
* * `applyClassesEarly` - Whether or not the classes being added or removed will be used when detecting the animation. This is set by `$animate` when enter/leave/move animations are fired to ensure that the CSS classes are resolved in time. (Note that this will prevent any transitions from occurring on the classes being added and removed.)
|
|
239
|
-
* * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once
|
|
240
|
-
* the animation is closed. This is useful for when the styles are used purely for the sake of
|
|
241
|
-
* the animation and do not have a lasting visual effect on the element (e.g. a collapse and open animation).
|
|
242
|
-
* By default this value is set to `false`.
|
|
243
|
-
*
|
|
244
|
-
* @return {object} an object with start and end methods and details about the animation.
|
|
245
|
-
*
|
|
246
|
-
* * `start` - The method to start the animation. This will return a `Promise` when called.
|
|
247
|
-
* * `end` - This method will cancel the animation and remove all applied CSS classes and styles.
|
|
248
|
-
*/
|
|
249
35
|
const ONE_SECOND = 1000;
|
|
250
36
|
|
|
251
37
|
const ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
|
|
@@ -351,791 +137,776 @@ function registerRestorableStyles(backup, node, properties) {
|
|
|
351
137
|
});
|
|
352
138
|
}
|
|
353
139
|
|
|
354
|
-
export
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
140
|
+
export function $AnimateCssProvider() {
|
|
141
|
+
this.$get = [
|
|
142
|
+
"$$AnimateRunner",
|
|
143
|
+
"$timeout",
|
|
144
|
+
"$$animateCache",
|
|
145
|
+
"$$rAFScheduler",
|
|
146
|
+
"$$animateQueue",
|
|
147
|
+
function (
|
|
148
|
+
$$AnimateRunner,
|
|
149
|
+
$timeout,
|
|
150
|
+
$$animateCache,
|
|
151
|
+
$$rAFScheduler,
|
|
152
|
+
$$animateQueue,
|
|
153
|
+
) {
|
|
154
|
+
const applyAnimationClasses = applyAnimationClassesFactory();
|
|
155
|
+
|
|
156
|
+
function computeCachedCssStyles(
|
|
157
|
+
node,
|
|
158
|
+
className,
|
|
159
|
+
cacheKey,
|
|
160
|
+
allowNoDuration,
|
|
161
|
+
properties,
|
|
368
162
|
) {
|
|
369
|
-
|
|
163
|
+
let timings = $$animateCache.get(cacheKey);
|
|
370
164
|
|
|
371
|
-
|
|
372
|
-
node,
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
allowNoDuration,
|
|
376
|
-
properties,
|
|
377
|
-
) {
|
|
378
|
-
let timings = $$animateCache.get(cacheKey);
|
|
379
|
-
|
|
380
|
-
if (!timings) {
|
|
381
|
-
timings = computeCssStyles(node, properties);
|
|
382
|
-
if (timings.animationIterationCount === "infinite") {
|
|
383
|
-
timings.animationIterationCount = 1;
|
|
384
|
-
}
|
|
165
|
+
if (!timings) {
|
|
166
|
+
timings = computeCssStyles(node, properties);
|
|
167
|
+
if (timings.animationIterationCount === "infinite") {
|
|
168
|
+
timings.animationIterationCount = 1;
|
|
385
169
|
}
|
|
170
|
+
}
|
|
386
171
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
172
|
+
// if a css animation has no duration we
|
|
173
|
+
// should mark that so that repeated addClass/removeClass calls are skipped
|
|
174
|
+
const hasDuration =
|
|
175
|
+
allowNoDuration ||
|
|
176
|
+
timings.transitionDuration > 0 ||
|
|
177
|
+
timings.animationDuration > 0;
|
|
393
178
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
179
|
+
// we keep putting this in multiple times even though the value and the cacheKey are the same
|
|
180
|
+
// because we're keeping an internal tally of how many duplicate animations are detected.
|
|
181
|
+
$$animateCache.put(cacheKey, timings, hasDuration);
|
|
182
|
+
|
|
183
|
+
return timings;
|
|
184
|
+
}
|
|
397
185
|
|
|
398
|
-
|
|
186
|
+
function computeCachedCssStaggerStyles(
|
|
187
|
+
node,
|
|
188
|
+
className,
|
|
189
|
+
cacheKey,
|
|
190
|
+
properties,
|
|
191
|
+
) {
|
|
192
|
+
let stagger;
|
|
193
|
+
const staggerCacheKey = `stagger-${cacheKey}`;
|
|
194
|
+
|
|
195
|
+
// if we have one or more existing matches of matching elements
|
|
196
|
+
// containing the same parent + CSS styles (which is how cacheKey works)
|
|
197
|
+
// then staggering is possible
|
|
198
|
+
if ($$animateCache.count(cacheKey) > 0) {
|
|
199
|
+
stagger = $$animateCache.get(staggerCacheKey);
|
|
200
|
+
|
|
201
|
+
if (!stagger) {
|
|
202
|
+
const staggerClassName = pendClasses(className, "-stagger");
|
|
203
|
+
|
|
204
|
+
node.className += ` ${staggerClassName}`;
|
|
205
|
+
stagger = computeCssStyles(node, properties);
|
|
206
|
+
|
|
207
|
+
// force the conversion of a null value to zero incase not set
|
|
208
|
+
stagger.animationDuration = Math.max(stagger.animationDuration, 0);
|
|
209
|
+
stagger.transitionDuration = Math.max(
|
|
210
|
+
stagger.transitionDuration,
|
|
211
|
+
0,
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
node.classList.remove(staggerClassName);
|
|
215
|
+
|
|
216
|
+
$$animateCache.put(staggerCacheKey, stagger, true);
|
|
217
|
+
}
|
|
399
218
|
}
|
|
400
219
|
|
|
401
|
-
|
|
220
|
+
return stagger || {};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const rafWaitQueue = [];
|
|
224
|
+
function waitUntilQuiet(callback) {
|
|
225
|
+
rafWaitQueue.push(callback);
|
|
226
|
+
$$rAFScheduler.waitUntilQuiet(() => {
|
|
227
|
+
$$animateCache.flush();
|
|
228
|
+
|
|
229
|
+
// DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
|
|
230
|
+
// the line below will force the browser to perform a repaint so
|
|
231
|
+
// that all the animated elements within the animation frame will
|
|
232
|
+
// be properly updated and drawn on screen. This is required to
|
|
233
|
+
// ensure that the preparation animation is properly flushed so that
|
|
234
|
+
// the active state picks up from there. DO NOT REMOVE THIS LINE.
|
|
235
|
+
// DO NOT OPTIMIZE THIS LINE. THE MINIFIER WILL REMOVE IT OTHERWISE WHICH
|
|
236
|
+
// WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
|
|
237
|
+
// WILL TAKE YEARS AWAY FROM YOUR LIFE.
|
|
238
|
+
|
|
239
|
+
const pageWidth = document.body.offsetWidth + 1;
|
|
240
|
+
|
|
241
|
+
// we use a for loop to ensure that if the queue is changed
|
|
242
|
+
// during this looping then it will consider new requests
|
|
243
|
+
for (let i = 0; i < rafWaitQueue.length; i++) {
|
|
244
|
+
rafWaitQueue[i](pageWidth);
|
|
245
|
+
}
|
|
246
|
+
rafWaitQueue.length = 0;
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function computeTimings(node, className, cacheKey, allowNoDuration) {
|
|
251
|
+
const timings = computeCachedCssStyles(
|
|
402
252
|
node,
|
|
403
253
|
className,
|
|
404
254
|
cacheKey,
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
node.className += ` ${staggerClassName}`;
|
|
420
|
-
stagger = computeCssStyles(node, properties);
|
|
421
|
-
|
|
422
|
-
// force the conversion of a null value to zero incase not set
|
|
423
|
-
stagger.animationDuration = Math.max(
|
|
424
|
-
stagger.animationDuration,
|
|
425
|
-
0,
|
|
426
|
-
);
|
|
427
|
-
stagger.transitionDuration = Math.max(
|
|
428
|
-
stagger.transitionDuration,
|
|
429
|
-
0,
|
|
430
|
-
);
|
|
255
|
+
allowNoDuration,
|
|
256
|
+
DETECT_CSS_PROPERTIES,
|
|
257
|
+
);
|
|
258
|
+
const aD = timings.animationDelay;
|
|
259
|
+
const tD = timings.transitionDelay;
|
|
260
|
+
timings.maxDelay = aD && tD ? Math.max(aD, tD) : aD || tD;
|
|
261
|
+
timings.maxDuration = Math.max(
|
|
262
|
+
timings.animationDuration * timings.animationIterationCount,
|
|
263
|
+
timings.transitionDuration,
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
return timings;
|
|
267
|
+
}
|
|
431
268
|
|
|
432
|
-
|
|
269
|
+
return function init(element, initialOptions) {
|
|
270
|
+
// all of the animation functions should create
|
|
271
|
+
// a copy of the options data, however, if a
|
|
272
|
+
// parent service has already created a copy then
|
|
273
|
+
// we should stick to using that
|
|
274
|
+
let options = initialOptions || {};
|
|
275
|
+
if (!options.$$prepared) {
|
|
276
|
+
options = prepareAnimationOptions(structuredClone(options));
|
|
277
|
+
}
|
|
433
278
|
|
|
434
|
-
|
|
435
|
-
|
|
279
|
+
const restoreStyles = {};
|
|
280
|
+
const node = getDomNode(element);
|
|
281
|
+
if (!node || !node.parentNode || !$$animateQueue.enabled()) {
|
|
282
|
+
return closeAndReturnNoopAnimator();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const temporaryStyles = [];
|
|
286
|
+
const classes = element.attr("class");
|
|
287
|
+
const styles = packageStyles(options);
|
|
288
|
+
let animationClosed;
|
|
289
|
+
let animationPaused;
|
|
290
|
+
let animationCompleted;
|
|
291
|
+
let runner;
|
|
292
|
+
let runnerHost;
|
|
293
|
+
let maxDelay;
|
|
294
|
+
let maxDelayTime;
|
|
295
|
+
let maxDuration;
|
|
296
|
+
let maxDurationTime;
|
|
297
|
+
let startTime;
|
|
298
|
+
const events = [];
|
|
299
|
+
|
|
300
|
+
if (options.duration === 0) {
|
|
301
|
+
return closeAndReturnNoopAnimator();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const method =
|
|
305
|
+
options.event && Array.isArray(options.event)
|
|
306
|
+
? options.event.join(" ")
|
|
307
|
+
: options.event;
|
|
308
|
+
|
|
309
|
+
const isStructural = method && options.structural;
|
|
310
|
+
let structuralClassName = "";
|
|
311
|
+
let addRemoveClassName = "";
|
|
312
|
+
|
|
313
|
+
if (isStructural) {
|
|
314
|
+
structuralClassName = pendClasses(method, EVENT_CLASS_PREFIX, true);
|
|
315
|
+
} else if (method) {
|
|
316
|
+
structuralClassName = method;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (options.addClass) {
|
|
320
|
+
addRemoveClassName += pendClasses(options.addClass, ADD_CLASS_SUFFIX);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (options.removeClass) {
|
|
324
|
+
if (addRemoveClassName.length) {
|
|
325
|
+
addRemoveClassName += " ";
|
|
436
326
|
}
|
|
327
|
+
addRemoveClassName += pendClasses(
|
|
328
|
+
options.removeClass,
|
|
329
|
+
REMOVE_CLASS_SUFFIX,
|
|
330
|
+
);
|
|
331
|
+
}
|
|
437
332
|
|
|
438
|
-
|
|
333
|
+
// there may be a situation where a structural animation is combined together
|
|
334
|
+
// with CSS classes that need to resolve before the animation is computed.
|
|
335
|
+
// However this means that there is no explicit CSS code to block the animation
|
|
336
|
+
// from happening (by setting 0s none in the class name). If this is the case
|
|
337
|
+
// we need to apply the classes before the first rAF so we know to continue if
|
|
338
|
+
// there actually is a detected transition or keyframe animation
|
|
339
|
+
if (options.applyClassesEarly && addRemoveClassName.length) {
|
|
340
|
+
applyAnimationClasses(element, options);
|
|
439
341
|
}
|
|
440
342
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
// WILL RESULT IN AN UNPREDICTABLE BUG THAT IS VERY HARD TO TRACK DOWN AND
|
|
455
|
-
// WILL TAKE YEARS AWAY FROM YOUR LIFE.
|
|
456
|
-
|
|
457
|
-
const pageWidth = document.body.offsetWidth + 1;
|
|
458
|
-
|
|
459
|
-
// we use a for loop to ensure that if the queue is changed
|
|
460
|
-
// during this looping then it will consider new requests
|
|
461
|
-
for (let i = 0; i < rafWaitQueue.length; i++) {
|
|
462
|
-
rafWaitQueue[i](pageWidth);
|
|
463
|
-
}
|
|
464
|
-
rafWaitQueue.length = 0;
|
|
465
|
-
});
|
|
343
|
+
let preparationClasses = [structuralClassName, addRemoveClassName]
|
|
344
|
+
.join(" ")
|
|
345
|
+
.trim();
|
|
346
|
+
let fullClassName = `${classes} ${preparationClasses}`;
|
|
347
|
+
const hasToStyles = styles.to && Object.keys(styles.to).length > 0;
|
|
348
|
+
const containsKeyframeAnimation =
|
|
349
|
+
(options.keyframeStyle || "").length > 0;
|
|
350
|
+
|
|
351
|
+
// there is no way we can trigger an animation if no styles and
|
|
352
|
+
// no classes are being applied which would then trigger a transition,
|
|
353
|
+
// unless there a is raw keyframe value that is applied to the element.
|
|
354
|
+
if (!containsKeyframeAnimation && !hasToStyles && !preparationClasses) {
|
|
355
|
+
return closeAndReturnNoopAnimator();
|
|
466
356
|
}
|
|
467
357
|
|
|
468
|
-
|
|
469
|
-
|
|
358
|
+
let stagger;
|
|
359
|
+
let cacheKey = $$animateCache.cacheKey(
|
|
360
|
+
node,
|
|
361
|
+
method,
|
|
362
|
+
options.addClass,
|
|
363
|
+
options.removeClass,
|
|
364
|
+
);
|
|
365
|
+
if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
|
|
366
|
+
preparationClasses = null;
|
|
367
|
+
return closeAndReturnNoopAnimator();
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (options.stagger > 0) {
|
|
371
|
+
const staggerVal = parseFloat(options.stagger);
|
|
372
|
+
stagger = {
|
|
373
|
+
transitionDelay: staggerVal,
|
|
374
|
+
animationDelay: staggerVal,
|
|
375
|
+
transitionDuration: 0,
|
|
376
|
+
animationDuration: 0,
|
|
377
|
+
};
|
|
378
|
+
} else {
|
|
379
|
+
stagger = computeCachedCssStaggerStyles(
|
|
470
380
|
node,
|
|
471
|
-
|
|
381
|
+
preparationClasses,
|
|
472
382
|
cacheKey,
|
|
473
|
-
|
|
474
|
-
DETECT_CSS_PROPERTIES,
|
|
475
|
-
);
|
|
476
|
-
const aD = timings.animationDelay;
|
|
477
|
-
const tD = timings.transitionDelay;
|
|
478
|
-
timings.maxDelay = aD && tD ? Math.max(aD, tD) : aD || tD;
|
|
479
|
-
timings.maxDuration = Math.max(
|
|
480
|
-
timings.animationDuration * timings.animationIterationCount,
|
|
481
|
-
timings.transitionDuration,
|
|
383
|
+
DETECT_STAGGER_CSS_PROPERTIES,
|
|
482
384
|
);
|
|
385
|
+
}
|
|
483
386
|
|
|
484
|
-
|
|
387
|
+
if (!options.$$skipPreparationClasses) {
|
|
388
|
+
element[0].classList.add(preparationClasses);
|
|
485
389
|
}
|
|
486
390
|
|
|
487
|
-
|
|
488
|
-
// all of the animation functions should create
|
|
489
|
-
// a copy of the options data, however, if a
|
|
490
|
-
// parent service has already created a copy then
|
|
491
|
-
// we should stick to using that
|
|
492
|
-
let options = initialOptions || {};
|
|
493
|
-
if (!options.$$prepared) {
|
|
494
|
-
options = prepareAnimationOptions(structuredClone(options));
|
|
495
|
-
}
|
|
391
|
+
let applyOnlyDuration;
|
|
496
392
|
|
|
497
|
-
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
393
|
+
if (options.transitionStyle) {
|
|
394
|
+
const transitionStyle = [TRANSITION_PROP, options.transitionStyle];
|
|
395
|
+
applyInlineStyle(node, transitionStyle);
|
|
396
|
+
temporaryStyles.push(transitionStyle);
|
|
397
|
+
}
|
|
502
398
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
let runner;
|
|
510
|
-
let runnerHost;
|
|
511
|
-
let maxDelay;
|
|
512
|
-
let maxDelayTime;
|
|
513
|
-
let maxDuration;
|
|
514
|
-
let maxDurationTime;
|
|
515
|
-
let startTime;
|
|
516
|
-
const events = [];
|
|
517
|
-
|
|
518
|
-
if (options.duration === 0) {
|
|
519
|
-
return closeAndReturnNoopAnimator();
|
|
520
|
-
}
|
|
399
|
+
if (options.duration >= 0) {
|
|
400
|
+
applyOnlyDuration = node.style[TRANSITION_PROP].length > 0;
|
|
401
|
+
const durationStyle = getCssTransitionDurationStyle(
|
|
402
|
+
options.duration,
|
|
403
|
+
applyOnlyDuration,
|
|
404
|
+
);
|
|
521
405
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
406
|
+
// we set the duration so that it will be picked up by getComputedStyle later
|
|
407
|
+
applyInlineStyle(node, durationStyle);
|
|
408
|
+
temporaryStyles.push(durationStyle);
|
|
409
|
+
}
|
|
526
410
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
411
|
+
if (options.keyframeStyle) {
|
|
412
|
+
const keyframeStyle = [ANIMATION_PROP, options.keyframeStyle];
|
|
413
|
+
applyInlineStyle(node, keyframeStyle);
|
|
414
|
+
temporaryStyles.push(keyframeStyle);
|
|
415
|
+
}
|
|
530
416
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
417
|
+
const itemIndex = stagger
|
|
418
|
+
? options.staggerIndex >= 0
|
|
419
|
+
? options.staggerIndex
|
|
420
|
+
: $$animateCache.count(cacheKey)
|
|
421
|
+
: 0;
|
|
422
|
+
|
|
423
|
+
const isFirst = itemIndex === 0;
|
|
424
|
+
|
|
425
|
+
// this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY
|
|
426
|
+
// without causing any combination of transitions to kick in. By adding a negative delay value
|
|
427
|
+
// it forces the setup class' transition to end immediately. We later then remove the negative
|
|
428
|
+
// transition delay to allow for the transition to naturally do it's thing. The beauty here is
|
|
429
|
+
// that if there is no transition defined then nothing will happen and this will also allow
|
|
430
|
+
// other transitions to be stacked on top of each other without any chopping them out.
|
|
431
|
+
if (isFirst && !options.skipBlocking) {
|
|
432
|
+
blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
|
|
433
|
+
}
|
|
536
434
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
435
|
+
let timings = computeTimings(
|
|
436
|
+
node,
|
|
437
|
+
fullClassName,
|
|
438
|
+
cacheKey,
|
|
439
|
+
!isStructural,
|
|
440
|
+
);
|
|
441
|
+
let relativeDelay = timings.maxDelay;
|
|
442
|
+
maxDelay = Math.max(relativeDelay, 0);
|
|
443
|
+
maxDuration = timings.maxDuration;
|
|
444
|
+
|
|
445
|
+
const flags = {};
|
|
446
|
+
flags.hasTransitions = timings.transitionDuration > 0;
|
|
447
|
+
flags.hasAnimations = timings.animationDuration > 0;
|
|
448
|
+
flags.hasTransitionAll =
|
|
449
|
+
flags.hasTransitions && timings.transitionProperty === "all";
|
|
450
|
+
flags.applyTransitionDuration =
|
|
451
|
+
hasToStyles &&
|
|
452
|
+
((flags.hasTransitions && !flags.hasTransitionAll) ||
|
|
453
|
+
(flags.hasAnimations && !flags.hasTransitions));
|
|
454
|
+
flags.applyAnimationDuration = options.duration && flags.hasAnimations;
|
|
455
|
+
flags.applyTransitionDelay =
|
|
456
|
+
truthyTimingValue(options.delay) &&
|
|
457
|
+
(flags.applyTransitionDuration || flags.hasTransitions);
|
|
458
|
+
flags.applyAnimationDelay =
|
|
459
|
+
truthyTimingValue(options.delay) && flags.hasAnimations;
|
|
460
|
+
flags.recalculateTimingStyles = addRemoveClassName.length > 0;
|
|
461
|
+
|
|
462
|
+
if (flags.applyTransitionDuration || flags.applyAnimationDuration) {
|
|
463
|
+
maxDuration = options.duration
|
|
464
|
+
? parseFloat(options.duration)
|
|
465
|
+
: maxDuration;
|
|
466
|
+
|
|
467
|
+
if (flags.applyTransitionDuration) {
|
|
468
|
+
flags.hasTransitions = true;
|
|
469
|
+
timings.transitionDuration = maxDuration;
|
|
470
|
+
applyOnlyDuration =
|
|
471
|
+
node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0;
|
|
472
|
+
temporaryStyles.push(
|
|
473
|
+
getCssTransitionDurationStyle(maxDuration, applyOnlyDuration),
|
|
541
474
|
);
|
|
542
475
|
}
|
|
543
476
|
|
|
544
|
-
if (
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
addRemoveClassName += pendClasses(
|
|
549
|
-
options.removeClass,
|
|
550
|
-
REMOVE_CLASS_SUFFIX,
|
|
551
|
-
);
|
|
477
|
+
if (flags.applyAnimationDuration) {
|
|
478
|
+
flags.hasAnimations = true;
|
|
479
|
+
timings.animationDuration = maxDuration;
|
|
480
|
+
temporaryStyles.push(getCssKeyframeDurationStyle(maxDuration));
|
|
552
481
|
}
|
|
482
|
+
}
|
|
553
483
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
484
|
+
if (maxDuration === 0 && !flags.recalculateTimingStyles) {
|
|
485
|
+
return closeAndReturnNoopAnimator();
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const activeClasses = pendClasses(
|
|
489
|
+
preparationClasses,
|
|
490
|
+
ACTIVE_CLASS_SUFFIX,
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
if (options.delay != null) {
|
|
494
|
+
var delayStyle;
|
|
495
|
+
if (typeof options.delay !== "boolean") {
|
|
496
|
+
delayStyle = parseFloat(options.delay);
|
|
497
|
+
// number in options.delay means we have to recalculate the delay for the closing timeout
|
|
498
|
+
maxDelay = Math.max(delayStyle, 0);
|
|
562
499
|
}
|
|
563
500
|
|
|
564
|
-
|
|
565
|
-
.
|
|
566
|
-
.trim();
|
|
567
|
-
let fullClassName = `${classes} ${preparationClasses}`;
|
|
568
|
-
const hasToStyles = styles.to && Object.keys(styles.to).length > 0;
|
|
569
|
-
const containsKeyframeAnimation =
|
|
570
|
-
(options.keyframeStyle || "").length > 0;
|
|
571
|
-
|
|
572
|
-
// there is no way we can trigger an animation if no styles and
|
|
573
|
-
// no classes are being applied which would then trigger a transition,
|
|
574
|
-
// unless there a is raw keyframe value that is applied to the element.
|
|
575
|
-
if (
|
|
576
|
-
!containsKeyframeAnimation &&
|
|
577
|
-
!hasToStyles &&
|
|
578
|
-
!preparationClasses
|
|
579
|
-
) {
|
|
580
|
-
return closeAndReturnNoopAnimator();
|
|
501
|
+
if (flags.applyTransitionDelay) {
|
|
502
|
+
temporaryStyles.push(getCssDelayStyle(delayStyle));
|
|
581
503
|
}
|
|
582
504
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
node,
|
|
586
|
-
method,
|
|
587
|
-
options.addClass,
|
|
588
|
-
options.removeClass,
|
|
589
|
-
);
|
|
590
|
-
if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
|
|
591
|
-
preparationClasses = null;
|
|
592
|
-
return closeAndReturnNoopAnimator();
|
|
505
|
+
if (flags.applyAnimationDelay) {
|
|
506
|
+
temporaryStyles.push(getCssDelayStyle(delayStyle, true));
|
|
593
507
|
}
|
|
508
|
+
}
|
|
594
509
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
510
|
+
// we need to recalculate the delay value since we used a pre-emptive negative
|
|
511
|
+
// delay value and the delay value is required for the final event checking. This
|
|
512
|
+
// property will ensure that this will happen after the RAF phase has passed.
|
|
513
|
+
if (options.duration == null && timings.transitionDuration > 0) {
|
|
514
|
+
flags.recalculateTimingStyles =
|
|
515
|
+
flags.recalculateTimingStyles || isFirst;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
maxDelayTime = maxDelay * ONE_SECOND;
|
|
519
|
+
maxDurationTime = maxDuration * ONE_SECOND;
|
|
520
|
+
if (!options.skipBlocking) {
|
|
521
|
+
flags.blockTransition = timings.transitionDuration > 0;
|
|
522
|
+
flags.blockKeyframeAnimation =
|
|
523
|
+
timings.animationDuration > 0 &&
|
|
524
|
+
stagger.animationDelay > 0 &&
|
|
525
|
+
stagger.animationDuration === 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (options.from) {
|
|
529
|
+
if (options.cleanupStyles) {
|
|
530
|
+
registerRestorableStyles(
|
|
531
|
+
restoreStyles,
|
|
605
532
|
node,
|
|
606
|
-
|
|
607
|
-
cacheKey,
|
|
608
|
-
DETECT_STAGGER_CSS_PROPERTIES,
|
|
533
|
+
Object.keys(options.from),
|
|
609
534
|
);
|
|
610
535
|
}
|
|
536
|
+
applyAnimationFromStyles(element, options);
|
|
537
|
+
}
|
|
611
538
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
539
|
+
if (flags.blockTransition || flags.blockKeyframeAnimation) {
|
|
540
|
+
applyBlocking(maxDuration);
|
|
541
|
+
} else if (!options.skipBlocking) {
|
|
542
|
+
blockTransitions(node, false);
|
|
543
|
+
}
|
|
615
544
|
|
|
616
|
-
|
|
545
|
+
// TODO(matsko): for 1.5 change this code to have an animator object for better debugging
|
|
546
|
+
return {
|
|
547
|
+
$$willAnimate: true,
|
|
548
|
+
end: endFn,
|
|
549
|
+
start() {
|
|
550
|
+
if (animationClosed) return;
|
|
617
551
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
552
|
+
runnerHost = {
|
|
553
|
+
end: endFn,
|
|
554
|
+
cancel: cancelFn,
|
|
555
|
+
resume: null, // this will be set during the start() phase
|
|
556
|
+
pause: null,
|
|
557
|
+
};
|
|
623
558
|
|
|
624
|
-
|
|
625
|
-
applyOnlyDuration = node.style[TRANSITION_PROP].length > 0;
|
|
626
|
-
const durationStyle = getCssTransitionDurationStyle(
|
|
627
|
-
options.duration,
|
|
628
|
-
applyOnlyDuration,
|
|
629
|
-
);
|
|
559
|
+
runner = new $$AnimateRunner(runnerHost);
|
|
630
560
|
|
|
631
|
-
|
|
632
|
-
applyInlineStyle(node, durationStyle);
|
|
633
|
-
temporaryStyles.push(durationStyle);
|
|
634
|
-
}
|
|
561
|
+
waitUntilQuiet(start);
|
|
635
562
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
563
|
+
// we don't have access to pause/resume the animation
|
|
564
|
+
// since it hasn't run yet. AnimateRunner will therefore
|
|
565
|
+
// set noop functions for resume and pause and they will
|
|
566
|
+
// later be overridden once the animation is triggered
|
|
567
|
+
return runner;
|
|
568
|
+
},
|
|
569
|
+
};
|
|
641
570
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
: $$animateCache.count(cacheKey)
|
|
646
|
-
: 0;
|
|
647
|
-
|
|
648
|
-
const isFirst = itemIndex === 0;
|
|
649
|
-
|
|
650
|
-
// this is a pre-emptive way of forcing the setup classes to be added and applied INSTANTLY
|
|
651
|
-
// without causing any combination of transitions to kick in. By adding a negative delay value
|
|
652
|
-
// it forces the setup class' transition to end immediately. We later then remove the negative
|
|
653
|
-
// transition delay to allow for the transition to naturally do it's thing. The beauty here is
|
|
654
|
-
// that if there is no transition defined then nothing will happen and this will also allow
|
|
655
|
-
// other transitions to be stacked on top of each other without any chopping them out.
|
|
656
|
-
if (isFirst && !options.skipBlocking) {
|
|
657
|
-
blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
|
|
658
|
-
}
|
|
571
|
+
function endFn() {
|
|
572
|
+
close();
|
|
573
|
+
}
|
|
659
574
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
cacheKey,
|
|
664
|
-
!isStructural,
|
|
665
|
-
);
|
|
666
|
-
let relativeDelay = timings.maxDelay;
|
|
667
|
-
maxDelay = Math.max(relativeDelay, 0);
|
|
668
|
-
maxDuration = timings.maxDuration;
|
|
669
|
-
|
|
670
|
-
const flags = {};
|
|
671
|
-
flags.hasTransitions = timings.transitionDuration > 0;
|
|
672
|
-
flags.hasAnimations = timings.animationDuration > 0;
|
|
673
|
-
flags.hasTransitionAll =
|
|
674
|
-
flags.hasTransitions && timings.transitionProperty === "all";
|
|
675
|
-
flags.applyTransitionDuration =
|
|
676
|
-
hasToStyles &&
|
|
677
|
-
((flags.hasTransitions && !flags.hasTransitionAll) ||
|
|
678
|
-
(flags.hasAnimations && !flags.hasTransitions));
|
|
679
|
-
flags.applyAnimationDuration =
|
|
680
|
-
options.duration && flags.hasAnimations;
|
|
681
|
-
flags.applyTransitionDelay =
|
|
682
|
-
truthyTimingValue(options.delay) &&
|
|
683
|
-
(flags.applyTransitionDuration || flags.hasTransitions);
|
|
684
|
-
flags.applyAnimationDelay =
|
|
685
|
-
truthyTimingValue(options.delay) && flags.hasAnimations;
|
|
686
|
-
flags.recalculateTimingStyles = addRemoveClassName.length > 0;
|
|
687
|
-
|
|
688
|
-
if (flags.applyTransitionDuration || flags.applyAnimationDuration) {
|
|
689
|
-
maxDuration = options.duration
|
|
690
|
-
? parseFloat(options.duration)
|
|
691
|
-
: maxDuration;
|
|
692
|
-
|
|
693
|
-
if (flags.applyTransitionDuration) {
|
|
694
|
-
flags.hasTransitions = true;
|
|
695
|
-
timings.transitionDuration = maxDuration;
|
|
696
|
-
applyOnlyDuration =
|
|
697
|
-
node.style[TRANSITION_PROP + PROPERTY_KEY].length > 0;
|
|
698
|
-
temporaryStyles.push(
|
|
699
|
-
getCssTransitionDurationStyle(maxDuration, applyOnlyDuration),
|
|
700
|
-
);
|
|
701
|
-
}
|
|
575
|
+
function cancelFn() {
|
|
576
|
+
close(true);
|
|
577
|
+
}
|
|
702
578
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
579
|
+
function close(rejected) {
|
|
580
|
+
// if the promise has been called already then we shouldn't close
|
|
581
|
+
// the animation again
|
|
582
|
+
if (animationClosed || (animationCompleted && animationPaused))
|
|
583
|
+
return;
|
|
584
|
+
animationClosed = true;
|
|
585
|
+
animationPaused = false;
|
|
586
|
+
|
|
587
|
+
if (preparationClasses && !options.$$skipPreparationClasses) {
|
|
588
|
+
preparationClasses
|
|
589
|
+
.split(" ")
|
|
590
|
+
.forEach((cls) => element.classList.remove(cls));
|
|
708
591
|
}
|
|
709
592
|
|
|
710
|
-
if (
|
|
711
|
-
|
|
593
|
+
if (activeClasses) {
|
|
594
|
+
activeClasses
|
|
595
|
+
.split(" ")
|
|
596
|
+
.forEach((cls) => element.classList.remove(cls));
|
|
712
597
|
}
|
|
713
598
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
ACTIVE_CLASS_SUFFIX,
|
|
717
|
-
);
|
|
599
|
+
blockKeyframeAnimations(node, false);
|
|
600
|
+
blockTransitions(node, false);
|
|
718
601
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
}
|
|
602
|
+
forEach(temporaryStyles, (entry) => {
|
|
603
|
+
// There is only one way to remove inline style properties entirely from elements.
|
|
604
|
+
// By using `removeProperty` this works, but we need to convert camel-cased CSS
|
|
605
|
+
// styles down to hyphenated values.
|
|
606
|
+
node.style[entry[0]] = "";
|
|
607
|
+
});
|
|
726
608
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
}
|
|
609
|
+
applyAnimationClasses(element, options);
|
|
610
|
+
applyAnimationStyles(element, options);
|
|
730
611
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
612
|
+
if (Object.keys(restoreStyles).length) {
|
|
613
|
+
forEach(restoreStyles, (value, prop) => {
|
|
614
|
+
if (value) {
|
|
615
|
+
node.style.setProperty(prop, value);
|
|
616
|
+
} else {
|
|
617
|
+
node.style.removeProperty(prop);
|
|
618
|
+
}
|
|
619
|
+
});
|
|
734
620
|
}
|
|
735
621
|
|
|
736
|
-
//
|
|
737
|
-
//
|
|
738
|
-
//
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
622
|
+
// the reason why we have this option is to allow a synchronous closing callback
|
|
623
|
+
// that is fired as SOON as the animation ends (when the CSS is removed) or if
|
|
624
|
+
// the animation never takes off at all. A good example is a leave animation since
|
|
625
|
+
// the element must be removed just after the animation is over or else the element
|
|
626
|
+
// will appear on screen for one animation frame causing an overbearing flicker.
|
|
627
|
+
if (options.onDone) {
|
|
628
|
+
options.onDone();
|
|
742
629
|
}
|
|
743
630
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
flags.blockTransition = timings.transitionDuration > 0;
|
|
748
|
-
flags.blockKeyframeAnimation =
|
|
749
|
-
timings.animationDuration > 0 &&
|
|
750
|
-
stagger.animationDelay > 0 &&
|
|
751
|
-
stagger.animationDuration === 0;
|
|
631
|
+
if (events && events.length) {
|
|
632
|
+
// Remove the transitionend / animationend listener(s)
|
|
633
|
+
element.off(events.join(" "), onAnimationProgress);
|
|
752
634
|
}
|
|
753
635
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
Object.keys(options.from),
|
|
760
|
-
);
|
|
761
|
-
}
|
|
762
|
-
applyAnimationFromStyles(element, options);
|
|
636
|
+
// Cancel the fallback closing timeout and remove the timer data
|
|
637
|
+
const animationTimerData = element.data(ANIMATE_TIMER_KEY);
|
|
638
|
+
if (animationTimerData) {
|
|
639
|
+
$timeout.cancel(animationTimerData[0].timer);
|
|
640
|
+
element.removeData(ANIMATE_TIMER_KEY);
|
|
763
641
|
}
|
|
764
642
|
|
|
765
|
-
if
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
blockTransitions(node, false);
|
|
643
|
+
// if the preparation function fails then the promise is not setup
|
|
644
|
+
if (runner) {
|
|
645
|
+
runner.complete(!rejected);
|
|
769
646
|
}
|
|
647
|
+
}
|
|
770
648
|
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
start() {
|
|
776
|
-
if (animationClosed) return;
|
|
649
|
+
function applyBlocking(duration) {
|
|
650
|
+
if (flags.blockTransition) {
|
|
651
|
+
blockTransitions(node, duration);
|
|
652
|
+
}
|
|
777
653
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
pause: null,
|
|
783
|
-
};
|
|
654
|
+
if (flags.blockKeyframeAnimation) {
|
|
655
|
+
blockKeyframeAnimations(node, !!duration);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
784
658
|
|
|
785
|
-
|
|
659
|
+
function closeAndReturnNoopAnimator() {
|
|
660
|
+
runner = new $$AnimateRunner({
|
|
661
|
+
end: endFn,
|
|
662
|
+
cancel: cancelFn,
|
|
663
|
+
});
|
|
786
664
|
|
|
787
|
-
|
|
665
|
+
// should flush the cache animation
|
|
666
|
+
waitUntilQuiet(() => {});
|
|
667
|
+
close();
|
|
788
668
|
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
// later be overridden once the animation is triggered
|
|
669
|
+
return {
|
|
670
|
+
$$willAnimate: false,
|
|
671
|
+
start() {
|
|
793
672
|
return runner;
|
|
794
673
|
},
|
|
674
|
+
end: endFn,
|
|
795
675
|
};
|
|
676
|
+
}
|
|
796
677
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
678
|
+
function onAnimationProgress(event) {
|
|
679
|
+
event.stopPropagation();
|
|
680
|
+
const ev = event.originalEvent || event;
|
|
800
681
|
|
|
801
|
-
|
|
802
|
-
|
|
682
|
+
if (ev.target !== node) {
|
|
683
|
+
// Since TransitionEvent / AnimationEvent bubble up,
|
|
684
|
+
// we have to ignore events by finished child animations
|
|
685
|
+
return;
|
|
803
686
|
}
|
|
804
687
|
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
if (animationClosed || (animationCompleted && animationPaused))
|
|
809
|
-
return;
|
|
810
|
-
animationClosed = true;
|
|
811
|
-
animationPaused = false;
|
|
812
|
-
|
|
813
|
-
if (preparationClasses && !options.$$skipPreparationClasses) {
|
|
814
|
-
preparationClasses
|
|
815
|
-
.split(" ")
|
|
816
|
-
.forEach((cls) => element.classList.remove(cls));
|
|
817
|
-
}
|
|
688
|
+
// we now always use `Date.now()` due to the recent changes with
|
|
689
|
+
// event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info)
|
|
690
|
+
const timeStamp = ev.$manualTimeStamp || Date.now();
|
|
818
691
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
blockKeyframeAnimations(node, false);
|
|
826
|
-
blockTransitions(node, false);
|
|
692
|
+
/* Firefox (or possibly just Gecko) likes to not round values up
|
|
693
|
+
* when a ms measurement is used for the animation */
|
|
694
|
+
const elapsedTime = parseFloat(
|
|
695
|
+
ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES),
|
|
696
|
+
);
|
|
827
697
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
698
|
+
/* $manualTimeStamp is a mocked timeStamp value which is set
|
|
699
|
+
* within browserTrigger(). This is only here so that tests can
|
|
700
|
+
* mock animations properly. Real events fallback to event.timeStamp,
|
|
701
|
+
* or, if they don't, then a timeStamp is automatically created for them.
|
|
702
|
+
* We're checking to see if the timeStamp surpasses the expected delay,
|
|
703
|
+
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
|
704
|
+
* pre-condition since animationPauseds sometimes close off early */
|
|
705
|
+
if (
|
|
706
|
+
Math.max(timeStamp - startTime, 0) >= maxDelayTime &&
|
|
707
|
+
elapsedTime >= maxDuration
|
|
708
|
+
) {
|
|
709
|
+
// we set this flag to ensure that if the transition is paused then, when resumed,
|
|
710
|
+
// the animation will automatically close itself since transitions cannot be paused.
|
|
711
|
+
animationCompleted = true;
|
|
712
|
+
close();
|
|
713
|
+
}
|
|
714
|
+
}
|
|
834
715
|
|
|
835
|
-
|
|
836
|
-
|
|
716
|
+
function start() {
|
|
717
|
+
if (animationClosed) return;
|
|
718
|
+
if (!node.parentNode) {
|
|
719
|
+
close();
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
837
722
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
723
|
+
// even though we only pause keyframe animations here the pause flag
|
|
724
|
+
// will still happen when transitions are used. Only the transition will
|
|
725
|
+
// not be paused since that is not possible. If the animation ends when
|
|
726
|
+
// paused then it will not complete until unpaused or cancelled.
|
|
727
|
+
const playPause = function (playAnimation) {
|
|
728
|
+
if (!animationCompleted) {
|
|
729
|
+
animationPaused = !playAnimation;
|
|
730
|
+
if (timings.animationDuration) {
|
|
731
|
+
const value = blockKeyframeAnimations(node, animationPaused);
|
|
732
|
+
if (animationPaused) {
|
|
733
|
+
temporaryStyles.push(value);
|
|
842
734
|
} else {
|
|
843
|
-
|
|
735
|
+
removeFromArray(temporaryStyles, value);
|
|
844
736
|
}
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
// that is fired as SOON as the animation ends (when the CSS is removed) or if
|
|
850
|
-
// the animation never takes off at all. A good example is a leave animation since
|
|
851
|
-
// the element must be removed just after the animation is over or else the element
|
|
852
|
-
// will appear on screen for one animation frame causing an overbearing flicker.
|
|
853
|
-
if (options.onDone) {
|
|
854
|
-
options.onDone();
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
if (events && events.length) {
|
|
858
|
-
// Remove the transitionend / animationend listener(s)
|
|
859
|
-
element.off(events.join(" "), onAnimationProgress);
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
// Cancel the fallback closing timeout and remove the timer data
|
|
863
|
-
const animationTimerData = element.data(ANIMATE_TIMER_KEY);
|
|
864
|
-
if (animationTimerData) {
|
|
865
|
-
$timeout.cancel(animationTimerData[0].timer);
|
|
866
|
-
element.removeData(ANIMATE_TIMER_KEY);
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
// if the preparation function fails then the promise is not setup
|
|
870
|
-
if (runner) {
|
|
871
|
-
runner.complete(!rejected);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
function applyBlocking(duration) {
|
|
876
|
-
if (flags.blockTransition) {
|
|
877
|
-
blockTransitions(node, duration);
|
|
737
|
+
}
|
|
738
|
+
} else if (animationPaused && playAnimation) {
|
|
739
|
+
animationPaused = false;
|
|
740
|
+
close();
|
|
878
741
|
}
|
|
742
|
+
};
|
|
879
743
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
744
|
+
// checking the stagger duration prevents an accidentally cascade of the CSS delay style
|
|
745
|
+
// being inherited from the parent. If the transition duration is zero then we can safely
|
|
746
|
+
// rely that the delay value is an intentional stagger delay style.
|
|
747
|
+
const maxStagger =
|
|
748
|
+
itemIndex > 0 &&
|
|
749
|
+
((timings.transitionDuration && stagger.transitionDuration === 0) ||
|
|
750
|
+
(timings.animationDuration && stagger.animationDuration === 0)) &&
|
|
751
|
+
Math.max(stagger.animationDelay, stagger.transitionDelay);
|
|
752
|
+
if (maxStagger) {
|
|
753
|
+
$timeout(
|
|
754
|
+
triggerAnimationStart,
|
|
755
|
+
Math.floor(maxStagger * itemIndex * ONE_SECOND),
|
|
756
|
+
false,
|
|
757
|
+
);
|
|
758
|
+
} else {
|
|
759
|
+
triggerAnimationStart();
|
|
883
760
|
}
|
|
884
761
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
});
|
|
890
|
-
|
|
891
|
-
// should flush the cache animation
|
|
892
|
-
waitUntilQuiet(() => {});
|
|
893
|
-
close();
|
|
894
|
-
|
|
895
|
-
return {
|
|
896
|
-
$$willAnimate: false,
|
|
897
|
-
start() {
|
|
898
|
-
return runner;
|
|
899
|
-
},
|
|
900
|
-
end: endFn,
|
|
901
|
-
};
|
|
902
|
-
}
|
|
762
|
+
// this will decorate the existing promise runner with pause/resume methods
|
|
763
|
+
runnerHost.resume = function () {
|
|
764
|
+
playPause(true);
|
|
765
|
+
};
|
|
903
766
|
|
|
904
|
-
function
|
|
905
|
-
|
|
906
|
-
|
|
767
|
+
runnerHost.pause = function () {
|
|
768
|
+
playPause(false);
|
|
769
|
+
};
|
|
907
770
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
}
|
|
771
|
+
function triggerAnimationStart() {
|
|
772
|
+
// just incase a stagger animation kicks in when the animation
|
|
773
|
+
// itself was cancelled entirely
|
|
774
|
+
if (animationClosed) return;
|
|
913
775
|
|
|
914
|
-
|
|
915
|
-
// event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info)
|
|
916
|
-
const timeStamp = ev.$manualTimeStamp || Date.now();
|
|
776
|
+
applyBlocking(false);
|
|
917
777
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
);
|
|
778
|
+
forEach(temporaryStyles, (entry) => {
|
|
779
|
+
const key = entry[0];
|
|
780
|
+
const value = entry[1];
|
|
781
|
+
node.style[key] = value;
|
|
782
|
+
});
|
|
923
783
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
) {
|
|
935
|
-
// we set this flag to ensure that if the transition is paused then, when resumed,
|
|
936
|
-
// the animation will automatically close itself since transitions cannot be paused.
|
|
937
|
-
animationCompleted = true;
|
|
938
|
-
close();
|
|
939
|
-
}
|
|
940
|
-
}
|
|
784
|
+
applyAnimationClasses(element, options);
|
|
785
|
+
element.className += ` ${activeClasses}`;
|
|
786
|
+
if (flags.recalculateTimingStyles) {
|
|
787
|
+
fullClassName = `${node.getAttribute("class")} ${preparationClasses}`;
|
|
788
|
+
cacheKey = $$animateCache.cacheKey(
|
|
789
|
+
node,
|
|
790
|
+
method,
|
|
791
|
+
options.addClass,
|
|
792
|
+
options.removeClass,
|
|
793
|
+
);
|
|
941
794
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
795
|
+
timings = computeTimings(node, fullClassName, cacheKey, false);
|
|
796
|
+
relativeDelay = timings.maxDelay;
|
|
797
|
+
maxDelay = Math.max(relativeDelay, 0);
|
|
798
|
+
maxDuration = timings.maxDuration;
|
|
948
799
|
|
|
949
|
-
|
|
950
|
-
// will still happen when transitions are used. Only the transition will
|
|
951
|
-
// not be paused since that is not possible. If the animation ends when
|
|
952
|
-
// paused then it will not complete until unpaused or cancelled.
|
|
953
|
-
const playPause = function (playAnimation) {
|
|
954
|
-
if (!animationCompleted) {
|
|
955
|
-
animationPaused = !playAnimation;
|
|
956
|
-
if (timings.animationDuration) {
|
|
957
|
-
const value = blockKeyframeAnimations(node, animationPaused);
|
|
958
|
-
if (animationPaused) {
|
|
959
|
-
temporaryStyles.push(value);
|
|
960
|
-
} else {
|
|
961
|
-
removeFromArray(temporaryStyles, value);
|
|
962
|
-
}
|
|
963
|
-
}
|
|
964
|
-
} else if (animationPaused && playAnimation) {
|
|
965
|
-
animationPaused = false;
|
|
800
|
+
if (maxDuration === 0) {
|
|
966
801
|
close();
|
|
802
|
+
return;
|
|
967
803
|
}
|
|
968
|
-
};
|
|
969
804
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
// rely that the delay value is an intentional stagger delay style.
|
|
973
|
-
const maxStagger =
|
|
974
|
-
itemIndex > 0 &&
|
|
975
|
-
((timings.transitionDuration &&
|
|
976
|
-
stagger.transitionDuration === 0) ||
|
|
977
|
-
(timings.animationDuration &&
|
|
978
|
-
stagger.animationDuration === 0)) &&
|
|
979
|
-
Math.max(stagger.animationDelay, stagger.transitionDelay);
|
|
980
|
-
if (maxStagger) {
|
|
981
|
-
$timeout(
|
|
982
|
-
triggerAnimationStart,
|
|
983
|
-
Math.floor(maxStagger * itemIndex * ONE_SECOND),
|
|
984
|
-
false,
|
|
985
|
-
);
|
|
986
|
-
} else {
|
|
987
|
-
triggerAnimationStart();
|
|
805
|
+
flags.hasTransitions = timings.transitionDuration > 0;
|
|
806
|
+
flags.hasAnimations = timings.animationDuration > 0;
|
|
988
807
|
}
|
|
989
808
|
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
applyBlocking(false);
|
|
1005
|
-
|
|
1006
|
-
forEach(temporaryStyles, (entry) => {
|
|
1007
|
-
const key = entry[0];
|
|
1008
|
-
const value = entry[1];
|
|
1009
|
-
node.style[key] = value;
|
|
1010
|
-
});
|
|
1011
|
-
|
|
1012
|
-
applyAnimationClasses(element, options);
|
|
1013
|
-
element.className += ` ${activeClasses}`;
|
|
1014
|
-
if (flags.recalculateTimingStyles) {
|
|
1015
|
-
fullClassName = `${node.getAttribute("class")} ${preparationClasses}`;
|
|
1016
|
-
cacheKey = $$animateCache.cacheKey(
|
|
1017
|
-
node,
|
|
1018
|
-
method,
|
|
1019
|
-
options.addClass,
|
|
1020
|
-
options.removeClass,
|
|
1021
|
-
);
|
|
809
|
+
if (flags.applyAnimationDelay) {
|
|
810
|
+
relativeDelay =
|
|
811
|
+
typeof options.delay !== "boolean" &&
|
|
812
|
+
truthyTimingValue(options.delay)
|
|
813
|
+
? parseFloat(options.delay)
|
|
814
|
+
: relativeDelay;
|
|
815
|
+
|
|
816
|
+
maxDelay = Math.max(relativeDelay, 0);
|
|
817
|
+
timings.animationDelay = relativeDelay;
|
|
818
|
+
delayStyle = getCssDelayStyle(relativeDelay, true);
|
|
819
|
+
temporaryStyles.push(delayStyle);
|
|
820
|
+
node.style[delayStyle[0]] = delayStyle[1];
|
|
821
|
+
}
|
|
1022
822
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
maxDelay = Math.max(relativeDelay, 0);
|
|
1026
|
-
maxDuration = timings.maxDuration;
|
|
823
|
+
maxDelayTime = maxDelay * ONE_SECOND;
|
|
824
|
+
maxDurationTime = maxDuration * ONE_SECOND;
|
|
1027
825
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
826
|
+
if (options.easing) {
|
|
827
|
+
let easeProp;
|
|
828
|
+
const easeVal = options.easing;
|
|
829
|
+
if (flags.hasTransitions) {
|
|
830
|
+
easeProp = TRANSITION_PROP + TIMING_KEY;
|
|
831
|
+
temporaryStyles.push([easeProp, easeVal]);
|
|
832
|
+
node.style[easeProp] = easeVal;
|
|
1035
833
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
truthyTimingValue(options.delay)
|
|
1041
|
-
? parseFloat(options.delay)
|
|
1042
|
-
: relativeDelay;
|
|
1043
|
-
|
|
1044
|
-
maxDelay = Math.max(relativeDelay, 0);
|
|
1045
|
-
timings.animationDelay = relativeDelay;
|
|
1046
|
-
delayStyle = getCssDelayStyle(relativeDelay, true);
|
|
1047
|
-
temporaryStyles.push(delayStyle);
|
|
1048
|
-
node.style[delayStyle[0]] = delayStyle[1];
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
maxDelayTime = maxDelay * ONE_SECOND;
|
|
1052
|
-
maxDurationTime = maxDuration * ONE_SECOND;
|
|
1053
|
-
|
|
1054
|
-
if (options.easing) {
|
|
1055
|
-
let easeProp;
|
|
1056
|
-
const easeVal = options.easing;
|
|
1057
|
-
if (flags.hasTransitions) {
|
|
1058
|
-
easeProp = TRANSITION_PROP + TIMING_KEY;
|
|
1059
|
-
temporaryStyles.push([easeProp, easeVal]);
|
|
1060
|
-
node.style[easeProp] = easeVal;
|
|
1061
|
-
}
|
|
1062
|
-
if (flags.hasAnimations) {
|
|
1063
|
-
easeProp = ANIMATION_PROP + TIMING_KEY;
|
|
1064
|
-
temporaryStyles.push([easeProp, easeVal]);
|
|
1065
|
-
node.style[easeProp] = easeVal;
|
|
1066
|
-
}
|
|
834
|
+
if (flags.hasAnimations) {
|
|
835
|
+
easeProp = ANIMATION_PROP + TIMING_KEY;
|
|
836
|
+
temporaryStyles.push([easeProp, easeVal]);
|
|
837
|
+
node.style[easeProp] = easeVal;
|
|
1067
838
|
}
|
|
839
|
+
}
|
|
1068
840
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
841
|
+
if (timings.transitionDuration) {
|
|
842
|
+
events.push(TRANSITIONEND_EVENT);
|
|
843
|
+
}
|
|
1072
844
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
845
|
+
if (timings.animationDuration) {
|
|
846
|
+
events.push(ANIMATIONEND_EVENT);
|
|
847
|
+
}
|
|
1076
848
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
const animationsData = element.data(ANIMATE_TIMER_KEY) || [];
|
|
1083
|
-
let setupFallbackTimer = true;
|
|
1084
|
-
if (animationsData.length) {
|
|
1085
|
-
const currentTimerData = animationsData[0];
|
|
1086
|
-
setupFallbackTimer = endTime > currentTimerData.expectedEndTime;
|
|
1087
|
-
if (setupFallbackTimer) {
|
|
1088
|
-
$timeout.cancel(currentTimerData.timer);
|
|
1089
|
-
} else {
|
|
1090
|
-
animationsData.push(close);
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
849
|
+
startTime = Date.now();
|
|
850
|
+
const timerTime =
|
|
851
|
+
maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime;
|
|
852
|
+
const endTime = startTime + timerTime;
|
|
1093
853
|
|
|
854
|
+
const animationsData = element.data(ANIMATE_TIMER_KEY) || [];
|
|
855
|
+
let setupFallbackTimer = true;
|
|
856
|
+
if (animationsData.length) {
|
|
857
|
+
const currentTimerData = animationsData[0];
|
|
858
|
+
setupFallbackTimer = endTime > currentTimerData.expectedEndTime;
|
|
1094
859
|
if (setupFallbackTimer) {
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
timer,
|
|
1098
|
-
expectedEndTime: endTime,
|
|
1099
|
-
};
|
|
860
|
+
$timeout.cancel(currentTimerData.timer);
|
|
861
|
+
} else {
|
|
1100
862
|
animationsData.push(close);
|
|
1101
|
-
element.data(ANIMATE_TIMER_KEY, animationsData);
|
|
1102
863
|
}
|
|
864
|
+
}
|
|
1103
865
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
866
|
+
if (setupFallbackTimer) {
|
|
867
|
+
const timer = $timeout(onAnimationExpired, timerTime, false);
|
|
868
|
+
animationsData[0] = {
|
|
869
|
+
timer,
|
|
870
|
+
expectedEndTime: endTime,
|
|
871
|
+
};
|
|
872
|
+
animationsData.push(close);
|
|
873
|
+
element.data(ANIMATE_TIMER_KEY, animationsData);
|
|
874
|
+
}
|
|
1107
875
|
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
876
|
+
if (events.length) {
|
|
877
|
+
element.on(events.join(" "), onAnimationProgress);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
if (options.to) {
|
|
881
|
+
if (options.cleanupStyles) {
|
|
882
|
+
registerRestorableStyles(
|
|
883
|
+
restoreStyles,
|
|
884
|
+
node,
|
|
885
|
+
Object.keys(options.to),
|
|
886
|
+
);
|
|
1117
887
|
}
|
|
888
|
+
applyAnimationToStyles(element, options);
|
|
1118
889
|
}
|
|
890
|
+
}
|
|
1119
891
|
|
|
1120
|
-
|
|
1121
|
-
|
|
892
|
+
function onAnimationExpired() {
|
|
893
|
+
const animationsData = element.data(ANIMATE_TIMER_KEY);
|
|
1122
894
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
}
|
|
1130
|
-
element.removeData(ANIMATE_TIMER_KEY);
|
|
895
|
+
// this will be false in the event that the element was
|
|
896
|
+
// removed from the DOM (via a leave animation or something
|
|
897
|
+
// similar)
|
|
898
|
+
if (animationsData) {
|
|
899
|
+
for (let i = 1; i < animationsData.length; i++) {
|
|
900
|
+
animationsData[i]();
|
|
1131
901
|
}
|
|
902
|
+
element.removeData(ANIMATE_TIMER_KEY);
|
|
1132
903
|
}
|
|
1133
904
|
}
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
},
|
|
908
|
+
];
|
|
909
|
+
}
|
|
1139
910
|
|
|
1140
911
|
function blockTransitions(node, duration) {
|
|
1141
912
|
// we use a negative delay value since it performs blocking
|