angularjs-rails 1.4.8 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/angularjs-rails/version.rb +2 -2
- data/vendor/assets/javascripts/angular-animate.js +477 -286
- data/vendor/assets/javascripts/angular-aria.js +51 -51
- data/vendor/assets/javascripts/angular-cookies.js +9 -8
- data/vendor/assets/javascripts/angular-loader.js +45 -4
- data/vendor/assets/javascripts/angular-message-format.js +2 -2
- data/vendor/assets/javascripts/angular-messages.js +7 -5
- data/vendor/assets/javascripts/angular-mocks.js +406 -35
- data/vendor/assets/javascripts/angular-resource.js +121 -37
- data/vendor/assets/javascripts/angular-route.js +36 -11
- data/vendor/assets/javascripts/angular-sanitize.js +280 -246
- data/vendor/assets/javascripts/angular-scenario.js +2183 -773
- data/vendor/assets/javascripts/angular-touch.js +115 -14
- data/vendor/assets/javascripts/angular.js +2183 -773
- data/vendor/assets/javascripts/unstable/angular2-polyfills.js +3316 -0
- data/vendor/assets/javascripts/unstable/angular2.js +19327 -25066
- metadata +15 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b483abd42e39cf8cece41a4395e00cbbc1f47fa
|
4
|
+
data.tar.gz: 6550da43653042c3a20cd931363ea937af6c2cc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb396bd22d16510898e0bcd3055f0b9064f786be225b9bd49b9634df67f6865d0cb39c35ff394ac02ea73f1151adf9fc02bd871679d6ffacec1a50500a86df27
|
7
|
+
data.tar.gz: 715cadcda48fb98ef800458f91c3c8b13e01015ddbb39b36526e97de5c33b84dd7d47c09f285c84726debdfe3df642b9ed44338ab09c9d6c7c11e6c019762782
|
@@ -1,12 +1,13 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
3
|
-
* (c) 2010-
|
2
|
+
* @license AngularJS v1.5.0
|
3
|
+
* (c) 2010-2016 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
6
6
|
(function(window, angular, undefined) {'use strict';
|
7
7
|
|
8
8
|
/* jshint ignore:start */
|
9
9
|
var noop = angular.noop;
|
10
|
+
var copy = angular.copy;
|
10
11
|
var extend = angular.extend;
|
11
12
|
var jqLite = angular.element;
|
12
13
|
var forEach = angular.forEach;
|
@@ -25,6 +26,7 @@ var ADD_CLASS_SUFFIX = '-add';
|
|
25
26
|
var REMOVE_CLASS_SUFFIX = '-remove';
|
26
27
|
var EVENT_CLASS_PREFIX = 'ng-';
|
27
28
|
var ACTIVE_CLASS_SUFFIX = '-active';
|
29
|
+
var PREPARE_CLASS_SUFFIX = '-prepare';
|
28
30
|
|
29
31
|
var NG_ANIMATE_CLASSNAME = 'ng-animate';
|
30
32
|
var NG_ANIMATE_CHILDREN_DATA = '$$ngAnimateChildren';
|
@@ -76,6 +78,7 @@ var isPromiseLike = function(p) {
|
|
76
78
|
return p && p.then ? true : false;
|
77
79
|
};
|
78
80
|
|
81
|
+
var ngMinErr = angular.$$minErr('ng');
|
79
82
|
function assertArg(arg, name, reason) {
|
80
83
|
if (!arg) {
|
81
84
|
throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
|
@@ -220,7 +223,10 @@ function applyAnimationToStyles(element, options) {
|
|
220
223
|
}
|
221
224
|
}
|
222
225
|
|
223
|
-
function
|
226
|
+
function mergeAnimationDetails(element, oldAnimation, newAnimation) {
|
227
|
+
var target = oldAnimation.options || {};
|
228
|
+
var newOptions = newAnimation.options || {};
|
229
|
+
|
224
230
|
var toAdd = (target.addClass || '') + ' ' + (newOptions.addClass || '');
|
225
231
|
var toRemove = (target.removeClass || '') + ' ' + (newOptions.removeClass || '');
|
226
232
|
var classes = resolveElementClasses(element.attr('class'), toAdd, toRemove);
|
@@ -252,6 +258,9 @@ function mergeAnimationOptions(element, target, newOptions) {
|
|
252
258
|
target.removeClass = null;
|
253
259
|
}
|
254
260
|
|
261
|
+
oldAnimation.addClass = target.addClass;
|
262
|
+
oldAnimation.removeClass = target.removeClass;
|
263
|
+
|
255
264
|
return target;
|
256
265
|
}
|
257
266
|
|
@@ -387,7 +396,7 @@ var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
|
|
387
396
|
queue = scheduler.queue = [];
|
388
397
|
|
389
398
|
/* waitUntilQuiet does two things:
|
390
|
-
* 1. It will run the FINAL `fn` value only when an
|
399
|
+
* 1. It will run the FINAL `fn` value only when an uncanceled RAF has passed through
|
391
400
|
* 2. It will delay the next wave of tasks from running until the quiet `fn` has run.
|
392
401
|
*
|
393
402
|
* The motivation here is that animation code can request more time from the scheduler
|
@@ -422,16 +431,101 @@ var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
|
|
422
431
|
}
|
423
432
|
}];
|
424
433
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
434
|
+
/**
|
435
|
+
* @ngdoc directive
|
436
|
+
* @name ngAnimateChildren
|
437
|
+
* @restrict AE
|
438
|
+
* @element ANY
|
439
|
+
*
|
440
|
+
* @description
|
441
|
+
*
|
442
|
+
* ngAnimateChildren allows you to specify that children of this element should animate even if any
|
443
|
+
* of the children's parents are currently animating. By default, when an element has an active `enter`, `leave`, or `move`
|
444
|
+
* (structural) animation, child elements that also have an active structural animation are not animated.
|
445
|
+
*
|
446
|
+
* Note that even if `ngAnimteChildren` is set, no child animations will run when the parent element is removed from the DOM (`leave` animation).
|
447
|
+
*
|
448
|
+
*
|
449
|
+
* @param {string} ngAnimateChildren If the value is empty, `true` or `on`,
|
450
|
+
* then child animations are allowed. If the value is `false`, child animations are not allowed.
|
451
|
+
*
|
452
|
+
* @example
|
453
|
+
* <example module="ngAnimateChildren" name="ngAnimateChildren" deps="angular-animate.js" animations="true">
|
454
|
+
<file name="index.html">
|
455
|
+
<div ng-controller="mainController as main">
|
456
|
+
<label>Show container? <input type="checkbox" ng-model="main.enterElement" /></label>
|
457
|
+
<label>Animate children? <input type="checkbox" ng-model="main.animateChildren" /></label>
|
458
|
+
<hr>
|
459
|
+
<div ng-animate-children="{{main.animateChildren}}">
|
460
|
+
<div ng-if="main.enterElement" class="container">
|
461
|
+
List of items:
|
462
|
+
<div ng-repeat="item in [0, 1, 2, 3]" class="item">Item {{item}}</div>
|
463
|
+
</div>
|
464
|
+
</div>
|
465
|
+
</div>
|
466
|
+
</file>
|
467
|
+
<file name="animations.css">
|
468
|
+
|
469
|
+
.container.ng-enter,
|
470
|
+
.container.ng-leave {
|
471
|
+
transition: all ease 1.5s;
|
472
|
+
}
|
473
|
+
|
474
|
+
.container.ng-enter,
|
475
|
+
.container.ng-leave-active {
|
476
|
+
opacity: 0;
|
477
|
+
}
|
478
|
+
|
479
|
+
.container.ng-leave,
|
480
|
+
.container.ng-enter-active {
|
481
|
+
opacity: 1;
|
482
|
+
}
|
483
|
+
|
484
|
+
.item {
|
485
|
+
background: firebrick;
|
486
|
+
color: #FFF;
|
487
|
+
margin-bottom: 10px;
|
488
|
+
}
|
489
|
+
|
490
|
+
.item.ng-enter,
|
491
|
+
.item.ng-leave {
|
492
|
+
transition: transform 1.5s ease;
|
493
|
+
}
|
494
|
+
|
495
|
+
.item.ng-enter {
|
496
|
+
transform: translateX(50px);
|
497
|
+
}
|
498
|
+
|
499
|
+
.item.ng-enter-active {
|
500
|
+
transform: translateX(0);
|
501
|
+
}
|
502
|
+
</file>
|
503
|
+
<file name="script.js">
|
504
|
+
angular.module('ngAnimateChildren', ['ngAnimate'])
|
505
|
+
.controller('mainController', function() {
|
506
|
+
this.animateChildren = false;
|
507
|
+
this.enterElement = false;
|
508
|
+
});
|
509
|
+
</file>
|
510
|
+
</example>
|
511
|
+
*/
|
512
|
+
var $$AnimateChildrenDirective = ['$interpolate', function($interpolate) {
|
513
|
+
return {
|
514
|
+
link: function(scope, element, attrs) {
|
515
|
+
var val = attrs.ngAnimateChildren;
|
516
|
+
if (angular.isString(val) && val.length === 0) { //empty attribute
|
517
|
+
element.data(NG_ANIMATE_CHILDREN_DATA, true);
|
518
|
+
} else {
|
519
|
+
// Interpolate and set the value, so that it is available to
|
520
|
+
// animations that run right after compilation
|
521
|
+
setData($interpolate(val)(scope));
|
522
|
+
attrs.$observe('ngAnimateChildren', setData);
|
523
|
+
}
|
524
|
+
|
525
|
+
function setData(value) {
|
432
526
|
value = value === 'on' || value === 'true';
|
433
527
|
element.data(NG_ANIMATE_CHILDREN_DATA, value);
|
434
|
-
}
|
528
|
+
}
|
435
529
|
}
|
436
530
|
};
|
437
531
|
}];
|
@@ -603,7 +697,7 @@ var ANIMATE_TIMER_KEY = '$$animateCss';
|
|
603
697
|
* ```
|
604
698
|
*
|
605
699
|
* 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.
|
606
|
-
* 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
|
700
|
+
* 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
|
607
701
|
* applied to the element during the preparation phase). Note that all other properties such as duration, delay, transitions and keyframes are just properties
|
608
702
|
* and that changing them will not reconfigure the parameters of the animation.
|
609
703
|
*
|
@@ -640,11 +734,11 @@ var ANIMATE_TIMER_KEY = '$$animateCss';
|
|
640
734
|
* * `stagger` - A numeric time value representing the delay between successively animated elements
|
641
735
|
* ({@link ngAnimate#css-staggering-animations Click here to learn how CSS-based staggering works in ngAnimate.})
|
642
736
|
* * `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
|
643
|
-
*
|
644
|
-
* * `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
|
737
|
+
* `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
|
738
|
+
* * `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.)
|
645
739
|
* * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once
|
646
740
|
* the animation is closed. This is useful for when the styles are used purely for the sake of
|
647
|
-
* the animation and do not have a lasting visual effect on the element (e.g. a
|
741
|
+
* the animation and do not have a lasting visual effect on the element (e.g. a collapse and open animation).
|
648
742
|
* By default this value is set to `false`.
|
649
743
|
*
|
650
744
|
* @return {object} an object with start and end methods and details about the animation.
|
@@ -697,7 +791,7 @@ function computeCssStyles($window, element, properties) {
|
|
697
791
|
}
|
698
792
|
|
699
793
|
// by setting this to null in the event that the delay is not set or is set directly as 0
|
700
|
-
// then we can still allow for
|
794
|
+
// then we can still allow for negative values to be used later on and not mistake this
|
701
795
|
// value for being greater than any other negative value.
|
702
796
|
if (val === 0) {
|
703
797
|
val = null;
|
@@ -788,9 +882,9 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
788
882
|
var gcsStaggerLookup = createLocalCacheLookup();
|
789
883
|
|
790
884
|
this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
|
791
|
-
'$$forceReflow', '$sniffer', '$$rAFScheduler', '
|
885
|
+
'$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
|
792
886
|
function($window, $$jqLite, $$AnimateRunner, $timeout,
|
793
|
-
$$forceReflow, $sniffer, $$rAFScheduler,
|
887
|
+
$$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
|
794
888
|
|
795
889
|
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
|
796
890
|
|
@@ -813,7 +907,7 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
813
907
|
}
|
814
908
|
|
815
909
|
// we keep putting this in multiple times even though the value and the cacheKey are the same
|
816
|
-
// because we're keeping an
|
910
|
+
// because we're keeping an internal tally of how many duplicate animations are detected.
|
817
911
|
gcsLookup.put(cacheKey, timings);
|
818
912
|
return timings;
|
819
913
|
}
|
@@ -882,17 +976,24 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
882
976
|
return timings;
|
883
977
|
}
|
884
978
|
|
885
|
-
return function init(element,
|
979
|
+
return function init(element, initialOptions) {
|
980
|
+
// all of the animation functions should create
|
981
|
+
// a copy of the options data, however, if a
|
982
|
+
// parent service has already created a copy then
|
983
|
+
// we should stick to using that
|
984
|
+
var options = initialOptions || {};
|
985
|
+
if (!options.$$prepared) {
|
986
|
+
options = prepareAnimationOptions(copy(options));
|
987
|
+
}
|
988
|
+
|
886
989
|
var restoreStyles = {};
|
887
990
|
var node = getDomNode(element);
|
888
991
|
if (!node
|
889
992
|
|| !node.parentNode
|
890
|
-
||
|
993
|
+
|| !$$animateQueue.enabled()) {
|
891
994
|
return closeAndReturnNoopAnimator();
|
892
995
|
}
|
893
996
|
|
894
|
-
options = prepareAnimationOptions(options);
|
895
|
-
|
896
997
|
var temporaryStyles = [];
|
897
998
|
var classes = element.attr('class');
|
898
999
|
var styles = packageStyles(options);
|
@@ -905,6 +1006,8 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
905
1006
|
var maxDelayTime;
|
906
1007
|
var maxDuration;
|
907
1008
|
var maxDurationTime;
|
1009
|
+
var startTime;
|
1010
|
+
var events = [];
|
908
1011
|
|
909
1012
|
if (options.duration === 0 || (!$sniffer.animations && !$sniffer.transitions)) {
|
910
1013
|
return closeAndReturnNoopAnimator();
|
@@ -1058,7 +1161,12 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1058
1161
|
}
|
1059
1162
|
|
1060
1163
|
if (options.delay != null) {
|
1061
|
-
var delayStyle
|
1164
|
+
var delayStyle;
|
1165
|
+
if (typeof options.delay !== "boolean") {
|
1166
|
+
delayStyle = parseFloat(options.delay);
|
1167
|
+
// number in options.delay means we have to recalculate the delay for the closing timeout
|
1168
|
+
maxDelay = Math.max(delayStyle, 0);
|
1169
|
+
}
|
1062
1170
|
|
1063
1171
|
if (flags.applyTransitionDelay) {
|
1064
1172
|
temporaryStyles.push(getCssDelayStyle(delayStyle));
|
@@ -1173,6 +1281,18 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1173
1281
|
options.onDone();
|
1174
1282
|
}
|
1175
1283
|
|
1284
|
+
if (events && events.length) {
|
1285
|
+
// Remove the transitionend / animationend listener(s)
|
1286
|
+
element.off(events.join(' '), onAnimationProgress);
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
//Cancel the fallback closing timeout and remove the timer data
|
1290
|
+
var animationTimerData = element.data(ANIMATE_TIMER_KEY);
|
1291
|
+
if (animationTimerData) {
|
1292
|
+
$timeout.cancel(animationTimerData[0].timer);
|
1293
|
+
element.removeData(ANIMATE_TIMER_KEY);
|
1294
|
+
}
|
1295
|
+
|
1176
1296
|
// if the preparation function fails then the promise is not setup
|
1177
1297
|
if (runner) {
|
1178
1298
|
runner.complete(!rejected);
|
@@ -1208,6 +1328,33 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1208
1328
|
};
|
1209
1329
|
}
|
1210
1330
|
|
1331
|
+
function onAnimationProgress(event) {
|
1332
|
+
event.stopPropagation();
|
1333
|
+
var ev = event.originalEvent || event;
|
1334
|
+
|
1335
|
+
// we now always use `Date.now()` due to the recent changes with
|
1336
|
+
// event.timeStamp in Firefox, Webkit and Chrome (see #13494 for more info)
|
1337
|
+
var timeStamp = ev.$manualTimeStamp || Date.now();
|
1338
|
+
|
1339
|
+
/* Firefox (or possibly just Gecko) likes to not round values up
|
1340
|
+
* when a ms measurement is used for the animation */
|
1341
|
+
var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
|
1342
|
+
|
1343
|
+
/* $manualTimeStamp is a mocked timeStamp value which is set
|
1344
|
+
* within browserTrigger(). This is only here so that tests can
|
1345
|
+
* mock animations properly. Real events fallback to event.timeStamp,
|
1346
|
+
* or, if they don't, then a timeStamp is automatically created for them.
|
1347
|
+
* We're checking to see if the timeStamp surpasses the expected delay,
|
1348
|
+
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
1349
|
+
* pre-condition since animationPauseds sometimes close off early */
|
1350
|
+
if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
|
1351
|
+
// we set this flag to ensure that if the transition is paused then, when resumed,
|
1352
|
+
// the animation will automatically close itself since transitions cannot be paused.
|
1353
|
+
animationCompleted = true;
|
1354
|
+
close();
|
1355
|
+
}
|
1356
|
+
}
|
1357
|
+
|
1211
1358
|
function start() {
|
1212
1359
|
if (animationClosed) return;
|
1213
1360
|
if (!node.parentNode) {
|
@@ -1215,8 +1362,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1215
1362
|
return;
|
1216
1363
|
}
|
1217
1364
|
|
1218
|
-
var startTime, events = [];
|
1219
|
-
|
1220
1365
|
// even though we only pause keyframe animations here the pause flag
|
1221
1366
|
// will still happen when transitions are used. Only the transition will
|
1222
1367
|
// not be paused since that is not possible. If the animation ends when
|
@@ -1236,9 +1381,9 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1236
1381
|
}
|
1237
1382
|
};
|
1238
1383
|
|
1239
|
-
// checking the stagger duration prevents an
|
1384
|
+
// checking the stagger duration prevents an accidentally cascade of the CSS delay style
|
1240
1385
|
// being inherited from the parent. If the transition duration is zero then we can safely
|
1241
|
-
// rely that the delay value is an
|
1386
|
+
// rely that the delay value is an intentional stagger delay style.
|
1242
1387
|
var maxStagger = itemIndex > 0
|
1243
1388
|
&& ((timings.transitionDuration && stagger.transitionDuration === 0) ||
|
1244
1389
|
(timings.animationDuration && stagger.animationDuration === 0))
|
@@ -1357,7 +1502,10 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1357
1502
|
element.data(ANIMATE_TIMER_KEY, animationsData);
|
1358
1503
|
}
|
1359
1504
|
|
1360
|
-
|
1505
|
+
if (events.length) {
|
1506
|
+
element.on(events.join(' '), onAnimationProgress);
|
1507
|
+
}
|
1508
|
+
|
1361
1509
|
if (options.to) {
|
1362
1510
|
if (options.cleanupStyles) {
|
1363
1511
|
registerRestorableStyles(restoreStyles, node, Object.keys(options.to));
|
@@ -1379,30 +1527,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
|
|
1379
1527
|
element.removeData(ANIMATE_TIMER_KEY);
|
1380
1528
|
}
|
1381
1529
|
}
|
1382
|
-
|
1383
|
-
function onAnimationProgress(event) {
|
1384
|
-
event.stopPropagation();
|
1385
|
-
var ev = event.originalEvent || event;
|
1386
|
-
var timeStamp = ev.$manualTimeStamp || ev.timeStamp || Date.now();
|
1387
|
-
|
1388
|
-
/* Firefox (or possibly just Gecko) likes to not round values up
|
1389
|
-
* when a ms measurement is used for the animation */
|
1390
|
-
var elapsedTime = parseFloat(ev.elapsedTime.toFixed(ELAPSED_TIME_MAX_DECIMAL_PLACES));
|
1391
|
-
|
1392
|
-
/* $manualTimeStamp is a mocked timeStamp value which is set
|
1393
|
-
* within browserTrigger(). This is only here so that tests can
|
1394
|
-
* mock animations properly. Real events fallback to event.timeStamp,
|
1395
|
-
* or, if they don't, then a timeStamp is automatically created for them.
|
1396
|
-
* We're checking to see if the timeStamp surpasses the expected delay,
|
1397
|
-
* but we're using elapsedTime instead of the timeStamp on the 2nd
|
1398
|
-
* pre-condition since animations sometimes close off early */
|
1399
|
-
if (Math.max(timeStamp - startTime, 0) >= maxDelayTime && elapsedTime >= maxDuration) {
|
1400
|
-
// we set this flag to ensure that if the transition is paused then, when resumed,
|
1401
|
-
// the animation will automatically close itself since transitions cannot be paused.
|
1402
|
-
animationCompleted = true;
|
1403
|
-
close();
|
1404
|
-
}
|
1405
|
-
}
|
1406
1530
|
}
|
1407
1531
|
};
|
1408
1532
|
}];
|
@@ -1432,7 +1556,7 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
|
|
1432
1556
|
|
1433
1557
|
var rootBodyElement = jqLite(
|
1434
1558
|
// this is to avoid using something that exists outside of the body
|
1435
|
-
// we also special case the doc
|
1559
|
+
// we also special case the doc fragment case because our unit test code
|
1436
1560
|
// appends the $rootElement to the body after the app has been bootstrapped
|
1437
1561
|
isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode
|
1438
1562
|
);
|
@@ -1532,7 +1656,7 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
|
|
1532
1656
|
var coords = getDomNode(anchor).getBoundingClientRect();
|
1533
1657
|
|
1534
1658
|
// we iterate directly since safari messes up and doesn't return
|
1535
|
-
// all the keys for the
|
1659
|
+
// all the keys for the coords object when iterated
|
1536
1660
|
forEach(['width','height','top','left'], function(key) {
|
1537
1661
|
var value = coords[key];
|
1538
1662
|
switch (key) {
|
@@ -1687,6 +1811,8 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
|
1687
1811
|
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
|
1688
1812
|
// $animateJs(element, 'enter');
|
1689
1813
|
return function(element, event, classes, options) {
|
1814
|
+
var animationClosed = false;
|
1815
|
+
|
1690
1816
|
// the `classes` argument is optional and if it is not used
|
1691
1817
|
// then the classes will be resolved from the element's className
|
1692
1818
|
// property as well as options.addClass/options.removeClass.
|
@@ -1739,8 +1865,32 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
|
1739
1865
|
applyAnimationClasses(element, options);
|
1740
1866
|
}
|
1741
1867
|
|
1868
|
+
function close() {
|
1869
|
+
animationClosed = true;
|
1870
|
+
applyOptions();
|
1871
|
+
applyAnimationStyles(element, options);
|
1872
|
+
}
|
1873
|
+
|
1874
|
+
var runner;
|
1875
|
+
|
1742
1876
|
return {
|
1877
|
+
$$willAnimate: true,
|
1878
|
+
end: function() {
|
1879
|
+
if (runner) {
|
1880
|
+
runner.end();
|
1881
|
+
} else {
|
1882
|
+
close();
|
1883
|
+
runner = new $$AnimateRunner();
|
1884
|
+
runner.complete(true);
|
1885
|
+
}
|
1886
|
+
return runner;
|
1887
|
+
},
|
1743
1888
|
start: function() {
|
1889
|
+
if (runner) {
|
1890
|
+
return runner;
|
1891
|
+
}
|
1892
|
+
|
1893
|
+
runner = new $$AnimateRunner();
|
1744
1894
|
var closeActiveAnimations;
|
1745
1895
|
var chain = [];
|
1746
1896
|
|
@@ -1765,8 +1915,7 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
|
1765
1915
|
});
|
1766
1916
|
}
|
1767
1917
|
|
1768
|
-
|
1769
|
-
var runner = new $$AnimateRunner({
|
1918
|
+
runner.setHost({
|
1770
1919
|
end: function() {
|
1771
1920
|
endAnimations();
|
1772
1921
|
},
|
@@ -1779,9 +1928,7 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
|
|
1779
1928
|
return runner;
|
1780
1929
|
|
1781
1930
|
function onComplete(success) {
|
1782
|
-
|
1783
|
-
applyOptions();
|
1784
|
-
applyAnimationStyles(element, options);
|
1931
|
+
close(success);
|
1785
1932
|
runner.complete(success);
|
1786
1933
|
}
|
1787
1934
|
|
@@ -2001,6 +2148,7 @@ var NG_ANIMATE_PIN_DATA = '$ngAnimatePin';
|
|
2001
2148
|
var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
2002
2149
|
var PRE_DIGEST_STATE = 1;
|
2003
2150
|
var RUNNING_STATE = 2;
|
2151
|
+
var ONE_SPACE = ' ';
|
2004
2152
|
|
2005
2153
|
var rules = this.rules = {
|
2006
2154
|
skip: [],
|
@@ -2008,28 +2156,50 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2008
2156
|
join: []
|
2009
2157
|
};
|
2010
2158
|
|
2159
|
+
function makeTruthyCssClassMap(classString) {
|
2160
|
+
if (!classString) {
|
2161
|
+
return null;
|
2162
|
+
}
|
2163
|
+
|
2164
|
+
var keys = classString.split(ONE_SPACE);
|
2165
|
+
var map = Object.create(null);
|
2166
|
+
|
2167
|
+
forEach(keys, function(key) {
|
2168
|
+
map[key] = true;
|
2169
|
+
});
|
2170
|
+
return map;
|
2171
|
+
}
|
2172
|
+
|
2173
|
+
function hasMatchingClasses(newClassString, currentClassString) {
|
2174
|
+
if (newClassString && currentClassString) {
|
2175
|
+
var currentClassMap = makeTruthyCssClassMap(currentClassString);
|
2176
|
+
return newClassString.split(ONE_SPACE).some(function(className) {
|
2177
|
+
return currentClassMap[className];
|
2178
|
+
});
|
2179
|
+
}
|
2180
|
+
}
|
2181
|
+
|
2011
2182
|
function isAllowed(ruleType, element, currentAnimation, previousAnimation) {
|
2012
2183
|
return rules[ruleType].some(function(fn) {
|
2013
2184
|
return fn(element, currentAnimation, previousAnimation);
|
2014
2185
|
});
|
2015
2186
|
}
|
2016
2187
|
|
2017
|
-
function hasAnimationClasses(
|
2018
|
-
|
2019
|
-
var
|
2020
|
-
var b = (options.removeClass || '').length > 0;
|
2188
|
+
function hasAnimationClasses(animation, and) {
|
2189
|
+
var a = (animation.addClass || '').length > 0;
|
2190
|
+
var b = (animation.removeClass || '').length > 0;
|
2021
2191
|
return and ? a && b : a || b;
|
2022
2192
|
}
|
2023
2193
|
|
2024
2194
|
rules.join.push(function(element, newAnimation, currentAnimation) {
|
2025
2195
|
// if the new animation is class-based then we can just tack that on
|
2026
|
-
return !newAnimation.structural && hasAnimationClasses(newAnimation
|
2196
|
+
return !newAnimation.structural && hasAnimationClasses(newAnimation);
|
2027
2197
|
});
|
2028
2198
|
|
2029
2199
|
rules.skip.push(function(element, newAnimation, currentAnimation) {
|
2030
2200
|
// there is no need to animate anything if no classes are being added and
|
2031
2201
|
// there is no structural animation that will be triggered
|
2032
|
-
return !newAnimation.structural && !hasAnimationClasses(newAnimation
|
2202
|
+
return !newAnimation.structural && !hasAnimationClasses(newAnimation);
|
2033
2203
|
});
|
2034
2204
|
|
2035
2205
|
rules.skip.push(function(element, newAnimation, currentAnimation) {
|
@@ -2055,11 +2225,17 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2055
2225
|
});
|
2056
2226
|
|
2057
2227
|
rules.cancel.push(function(element, newAnimation, currentAnimation) {
|
2058
|
-
var
|
2059
|
-
var
|
2228
|
+
var nA = newAnimation.addClass;
|
2229
|
+
var nR = newAnimation.removeClass;
|
2230
|
+
var cA = currentAnimation.addClass;
|
2231
|
+
var cR = currentAnimation.removeClass;
|
2232
|
+
|
2233
|
+
// early detection to save the global CPU shortage :)
|
2234
|
+
if ((isUndefined(nA) && isUndefined(nR)) || (isUndefined(cA) && isUndefined(cR))) {
|
2235
|
+
return false;
|
2236
|
+
}
|
2060
2237
|
|
2061
|
-
|
2062
|
-
return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass);
|
2238
|
+
return hasMatchingClasses(nA, cR) || hasMatchingClasses(nR, cA);
|
2063
2239
|
});
|
2064
2240
|
|
2065
2241
|
this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
|
@@ -2131,10 +2307,17 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2131
2307
|
|
2132
2308
|
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
|
2133
2309
|
|
2134
|
-
function
|
2135
|
-
return
|
2310
|
+
function normalizeAnimationDetails(element, animation) {
|
2311
|
+
return mergeAnimationDetails(element, animation, {});
|
2136
2312
|
}
|
2137
2313
|
|
2314
|
+
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
|
2315
|
+
var contains = Node.prototype.contains || function(arg) {
|
2316
|
+
// jshint bitwise: false
|
2317
|
+
return this === arg || !!(this.compareDocumentPosition(arg) & 16);
|
2318
|
+
// jshint bitwise: true
|
2319
|
+
};
|
2320
|
+
|
2138
2321
|
function findCallbacks(parent, element, event) {
|
2139
2322
|
var targetNode = getDomNode(element);
|
2140
2323
|
var targetParentNode = getDomNode(parent);
|
@@ -2143,9 +2326,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2143
2326
|
var entries = callbackRegistry[event];
|
2144
2327
|
if (entries) {
|
2145
2328
|
forEach(entries, function(entry) {
|
2146
|
-
if (entry.node
|
2329
|
+
if (contains.call(entry.node, targetNode)) {
|
2147
2330
|
matches.push(entry.callback);
|
2148
|
-
} else if (event === 'leave' && entry.node
|
2331
|
+
} else if (event === 'leave' && contains.call(entry.node, targetParentNode)) {
|
2149
2332
|
matches.push(entry.callback);
|
2150
2333
|
}
|
2151
2334
|
});
|
@@ -2220,12 +2403,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2220
2403
|
bool = !recordExists;
|
2221
2404
|
} else {
|
2222
2405
|
// (element, bool) - Element setter
|
2223
|
-
|
2224
|
-
if (!bool) {
|
2225
|
-
disabledElementsLookup.put(node, true);
|
2226
|
-
} else if (recordExists) {
|
2227
|
-
disabledElementsLookup.remove(node);
|
2228
|
-
}
|
2406
|
+
disabledElementsLookup.put(node, !bool);
|
2229
2407
|
}
|
2230
2408
|
}
|
2231
2409
|
}
|
@@ -2234,7 +2412,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2234
2412
|
}
|
2235
2413
|
};
|
2236
2414
|
|
2237
|
-
function queueAnimation(element, event,
|
2415
|
+
function queueAnimation(element, event, initialOptions) {
|
2416
|
+
// we always make a copy of the options since
|
2417
|
+
// there should never be any side effects on
|
2418
|
+
// the input data when running `$animateCss`.
|
2419
|
+
var options = copy(initialOptions);
|
2420
|
+
|
2238
2421
|
var node, parent;
|
2239
2422
|
element = stripCommentsFromElement(element);
|
2240
2423
|
if (element) {
|
@@ -2294,7 +2477,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2294
2477
|
// this is a hard disable of all animations for the application or on
|
2295
2478
|
// the element itself, therefore there is no need to continue further
|
2296
2479
|
// past this point if not enabled
|
2297
|
-
|
2480
|
+
// Animations are also disabled if the document is currently hidden (page is not visible
|
2481
|
+
// to the user), because browsers slow down or do not flush calls to requestAnimationFrame
|
2482
|
+
var skipAnimations = !animationsEnabled || $document[0].hidden || disabledElementsLookup.get(node);
|
2298
2483
|
var existingAnimation = (!skipAnimations && activeAnimationsLookup.get(node)) || {};
|
2299
2484
|
var hasExistingAnimation = !!existingAnimation.state;
|
2300
2485
|
|
@@ -2317,6 +2502,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2317
2502
|
structural: isStructural,
|
2318
2503
|
element: element,
|
2319
2504
|
event: event,
|
2505
|
+
addClass: options.addClass,
|
2506
|
+
removeClass: options.removeClass,
|
2320
2507
|
close: close,
|
2321
2508
|
options: options,
|
2322
2509
|
runner: runner
|
@@ -2329,11 +2516,10 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2329
2516
|
close();
|
2330
2517
|
return runner;
|
2331
2518
|
} else {
|
2332
|
-
|
2519
|
+
mergeAnimationDetails(element, existingAnimation, newAnimation);
|
2333
2520
|
return existingAnimation.runner;
|
2334
2521
|
}
|
2335
2522
|
}
|
2336
|
-
|
2337
2523
|
var cancelAnimationFlag = isAllowed('cancel', element, newAnimation, existingAnimation);
|
2338
2524
|
if (cancelAnimationFlag) {
|
2339
2525
|
if (existingAnimation.state === RUNNING_STATE) {
|
@@ -2348,7 +2534,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2348
2534
|
existingAnimation.close();
|
2349
2535
|
} else {
|
2350
2536
|
// this will merge the new animation options into existing animation options
|
2351
|
-
|
2537
|
+
mergeAnimationDetails(element, existingAnimation, newAnimation);
|
2538
|
+
|
2352
2539
|
return existingAnimation.runner;
|
2353
2540
|
}
|
2354
2541
|
} else {
|
@@ -2358,12 +2545,12 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2358
2545
|
var joinAnimationFlag = isAllowed('join', element, newAnimation, existingAnimation);
|
2359
2546
|
if (joinAnimationFlag) {
|
2360
2547
|
if (existingAnimation.state === RUNNING_STATE) {
|
2361
|
-
|
2548
|
+
normalizeAnimationDetails(element, newAnimation);
|
2362
2549
|
} else {
|
2363
2550
|
applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
|
2364
2551
|
|
2365
2552
|
event = newAnimation.event = existingAnimation.event;
|
2366
|
-
options =
|
2553
|
+
options = mergeAnimationDetails(element, existingAnimation, newAnimation);
|
2367
2554
|
|
2368
2555
|
//we return the same runner since only the option values of this animation will
|
2369
2556
|
//be fed into the `existingAnimation`.
|
@@ -2374,7 +2561,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2374
2561
|
} else {
|
2375
2562
|
// normalization in this case means that it removes redundant CSS classes that
|
2376
2563
|
// already exist (addClass) or do not exist (removeClass) on the element
|
2377
|
-
|
2564
|
+
normalizeAnimationDetails(element, newAnimation);
|
2378
2565
|
}
|
2379
2566
|
|
2380
2567
|
// when the options are merged and cleaned up we may end up not having to do
|
@@ -2384,7 +2571,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2384
2571
|
if (!isValidAnimation) {
|
2385
2572
|
// animate (from/to) can be quickly checked first, otherwise we check if any classes are present
|
2386
2573
|
isValidAnimation = (newAnimation.event === 'animate' && Object.keys(newAnimation.options.to || {}).length > 0)
|
2387
|
-
|| hasAnimationClasses(newAnimation
|
2574
|
+
|| hasAnimationClasses(newAnimation);
|
2388
2575
|
}
|
2389
2576
|
|
2390
2577
|
if (!isValidAnimation) {
|
@@ -2414,7 +2601,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2414
2601
|
var isValidAnimation = parentElement.length > 0
|
2415
2602
|
&& (animationDetails.event === 'animate'
|
2416
2603
|
|| animationDetails.structural
|
2417
|
-
|| hasAnimationClasses(animationDetails
|
2604
|
+
|| hasAnimationClasses(animationDetails));
|
2418
2605
|
|
2419
2606
|
// this means that the previous animation was cancelled
|
2420
2607
|
// even if the follow-up animation is the same event
|
@@ -2446,7 +2633,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2446
2633
|
|
2447
2634
|
// this combined multiple class to addClass / removeClass into a setClass event
|
2448
2635
|
// so long as a structural event did not take over the animation
|
2449
|
-
event = !animationDetails.structural && hasAnimationClasses(animationDetails
|
2636
|
+
event = !animationDetails.structural && hasAnimationClasses(animationDetails, true)
|
2450
2637
|
? 'setClass'
|
2451
2638
|
: animationDetails.event;
|
2452
2639
|
|
@@ -2503,15 +2690,15 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2503
2690
|
forEach(children, function(child) {
|
2504
2691
|
var state = parseInt(child.getAttribute(NG_ANIMATE_ATTR_NAME));
|
2505
2692
|
var animationDetails = activeAnimationsLookup.get(child);
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2510
|
-
|
2511
|
-
|
2693
|
+
if (animationDetails) {
|
2694
|
+
switch (state) {
|
2695
|
+
case RUNNING_STATE:
|
2696
|
+
animationDetails.runner.end();
|
2697
|
+
/* falls through */
|
2698
|
+
case PRE_DIGEST_STATE:
|
2512
2699
|
activeAnimationsLookup.remove(child);
|
2513
|
-
|
2514
|
-
|
2700
|
+
break;
|
2701
|
+
}
|
2515
2702
|
}
|
2516
2703
|
});
|
2517
2704
|
}
|
@@ -2526,12 +2713,20 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2526
2713
|
return getDomNode(nodeOrElmA) === getDomNode(nodeOrElmB);
|
2527
2714
|
}
|
2528
2715
|
|
2716
|
+
/**
|
2717
|
+
* This fn returns false if any of the following is true:
|
2718
|
+
* a) animations on any parent element are disabled, and animations on the element aren't explicitly allowed
|
2719
|
+
* b) a parent element has an ongoing structural animation, and animateChildren is false
|
2720
|
+
* c) the element is not a child of the body
|
2721
|
+
* d) the element is not a child of the $rootElement
|
2722
|
+
*/
|
2529
2723
|
function areAnimationsAllowed(element, parentElement, event) {
|
2530
2724
|
var bodyElement = jqLite($document[0].body);
|
2531
2725
|
var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML';
|
2532
2726
|
var rootElementDetected = isMatchingElement(element, $rootElement);
|
2533
2727
|
var parentAnimationDetected = false;
|
2534
2728
|
var animateChildren;
|
2729
|
+
var elementDisabled = disabledElementsLookup.get(getDomNode(element));
|
2535
2730
|
|
2536
2731
|
var parentHost = element.data(NG_ANIMATE_PIN_DATA);
|
2537
2732
|
if (parentHost) {
|
@@ -2556,7 +2751,18 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2556
2751
|
// therefore we can't allow any animations to take place
|
2557
2752
|
// but if a parent animation is class-based then that's ok
|
2558
2753
|
if (!parentAnimationDetected) {
|
2559
|
-
|
2754
|
+
var parentElementDisabled = disabledElementsLookup.get(parentNode);
|
2755
|
+
|
2756
|
+
if (parentElementDisabled === true && elementDisabled !== false) {
|
2757
|
+
// disable animations if the user hasn't explicitly enabled animations on the
|
2758
|
+
// current element
|
2759
|
+
elementDisabled = true;
|
2760
|
+
// element is disabled via parent element, no need to check anything else
|
2761
|
+
break;
|
2762
|
+
} else if (parentElementDisabled === false) {
|
2763
|
+
elementDisabled = false;
|
2764
|
+
}
|
2765
|
+
parentAnimationDetected = details.structural;
|
2560
2766
|
}
|
2561
2767
|
|
2562
2768
|
if (isUndefined(animateChildren) || animateChildren === true) {
|
@@ -2569,28 +2775,32 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2569
2775
|
// there is no need to continue traversing at this point
|
2570
2776
|
if (parentAnimationDetected && animateChildren === false) break;
|
2571
2777
|
|
2572
|
-
if (!rootElementDetected) {
|
2573
|
-
// angular doesn't want to attempt to animate elements outside of the application
|
2574
|
-
// therefore we need to ensure that the rootElement is an ancestor of the current element
|
2575
|
-
rootElementDetected = isMatchingElement(parentElement, $rootElement);
|
2576
|
-
if (!rootElementDetected) {
|
2577
|
-
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
|
2578
|
-
if (parentHost) {
|
2579
|
-
parentElement = parentHost;
|
2580
|
-
}
|
2581
|
-
}
|
2582
|
-
}
|
2583
|
-
|
2584
2778
|
if (!bodyElementDetected) {
|
2585
|
-
// we also need to ensure that the element is or will be
|
2779
|
+
// we also need to ensure that the element is or will be a part of the body element
|
2586
2780
|
// otherwise it is pointless to even issue an animation to be rendered
|
2587
2781
|
bodyElementDetected = isMatchingElement(parentElement, bodyElement);
|
2588
2782
|
}
|
2589
2783
|
|
2784
|
+
if (bodyElementDetected && rootElementDetected) {
|
2785
|
+
// If both body and root have been found, any other checks are pointless,
|
2786
|
+
// as no animation data should live outside the application
|
2787
|
+
break;
|
2788
|
+
}
|
2789
|
+
|
2790
|
+
if (!rootElementDetected) {
|
2791
|
+
// If no rootElement is detected, check if the parentElement is pinned to another element
|
2792
|
+
parentHost = parentElement.data(NG_ANIMATE_PIN_DATA);
|
2793
|
+
if (parentHost) {
|
2794
|
+
// The pin target element becomes the next parent element
|
2795
|
+
parentElement = parentHost;
|
2796
|
+
continue;
|
2797
|
+
}
|
2798
|
+
}
|
2799
|
+
|
2590
2800
|
parentElement = parentElement.parent();
|
2591
2801
|
}
|
2592
2802
|
|
2593
|
-
var allowAnimation = !parentAnimationDetected || animateChildren;
|
2803
|
+
var allowAnimation = (!parentAnimationDetected || animateChildren) && elementDisabled !== true;
|
2594
2804
|
return allowAnimation && rootElementDetected && bodyElementDetected;
|
2595
2805
|
}
|
2596
2806
|
|
@@ -2610,171 +2820,6 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
|
|
2610
2820
|
}];
|
2611
2821
|
}];
|
2612
2822
|
|
2613
|
-
var $$AnimateAsyncRunFactory = ['$$rAF', function($$rAF) {
|
2614
|
-
var waitQueue = [];
|
2615
|
-
|
2616
|
-
function waitForTick(fn) {
|
2617
|
-
waitQueue.push(fn);
|
2618
|
-
if (waitQueue.length > 1) return;
|
2619
|
-
$$rAF(function() {
|
2620
|
-
for (var i = 0; i < waitQueue.length; i++) {
|
2621
|
-
waitQueue[i]();
|
2622
|
-
}
|
2623
|
-
waitQueue = [];
|
2624
|
-
});
|
2625
|
-
}
|
2626
|
-
|
2627
|
-
return function() {
|
2628
|
-
var passed = false;
|
2629
|
-
waitForTick(function() {
|
2630
|
-
passed = true;
|
2631
|
-
});
|
2632
|
-
return function(callback) {
|
2633
|
-
passed ? callback() : waitForTick(callback);
|
2634
|
-
};
|
2635
|
-
};
|
2636
|
-
}];
|
2637
|
-
|
2638
|
-
var $$AnimateRunnerFactory = ['$q', '$sniffer', '$$animateAsyncRun',
|
2639
|
-
function($q, $sniffer, $$animateAsyncRun) {
|
2640
|
-
|
2641
|
-
var INITIAL_STATE = 0;
|
2642
|
-
var DONE_PENDING_STATE = 1;
|
2643
|
-
var DONE_COMPLETE_STATE = 2;
|
2644
|
-
|
2645
|
-
AnimateRunner.chain = function(chain, callback) {
|
2646
|
-
var index = 0;
|
2647
|
-
|
2648
|
-
next();
|
2649
|
-
function next() {
|
2650
|
-
if (index === chain.length) {
|
2651
|
-
callback(true);
|
2652
|
-
return;
|
2653
|
-
}
|
2654
|
-
|
2655
|
-
chain[index](function(response) {
|
2656
|
-
if (response === false) {
|
2657
|
-
callback(false);
|
2658
|
-
return;
|
2659
|
-
}
|
2660
|
-
index++;
|
2661
|
-
next();
|
2662
|
-
});
|
2663
|
-
}
|
2664
|
-
};
|
2665
|
-
|
2666
|
-
AnimateRunner.all = function(runners, callback) {
|
2667
|
-
var count = 0;
|
2668
|
-
var status = true;
|
2669
|
-
forEach(runners, function(runner) {
|
2670
|
-
runner.done(onProgress);
|
2671
|
-
});
|
2672
|
-
|
2673
|
-
function onProgress(response) {
|
2674
|
-
status = status && response;
|
2675
|
-
if (++count === runners.length) {
|
2676
|
-
callback(status);
|
2677
|
-
}
|
2678
|
-
}
|
2679
|
-
};
|
2680
|
-
|
2681
|
-
function AnimateRunner(host) {
|
2682
|
-
this.setHost(host);
|
2683
|
-
|
2684
|
-
this._doneCallbacks = [];
|
2685
|
-
this._runInAnimationFrame = $$animateAsyncRun();
|
2686
|
-
this._state = 0;
|
2687
|
-
}
|
2688
|
-
|
2689
|
-
AnimateRunner.prototype = {
|
2690
|
-
setHost: function(host) {
|
2691
|
-
this.host = host || {};
|
2692
|
-
},
|
2693
|
-
|
2694
|
-
done: function(fn) {
|
2695
|
-
if (this._state === DONE_COMPLETE_STATE) {
|
2696
|
-
fn();
|
2697
|
-
} else {
|
2698
|
-
this._doneCallbacks.push(fn);
|
2699
|
-
}
|
2700
|
-
},
|
2701
|
-
|
2702
|
-
progress: noop,
|
2703
|
-
|
2704
|
-
getPromise: function() {
|
2705
|
-
if (!this.promise) {
|
2706
|
-
var self = this;
|
2707
|
-
this.promise = $q(function(resolve, reject) {
|
2708
|
-
self.done(function(status) {
|
2709
|
-
status === false ? reject() : resolve();
|
2710
|
-
});
|
2711
|
-
});
|
2712
|
-
}
|
2713
|
-
return this.promise;
|
2714
|
-
},
|
2715
|
-
|
2716
|
-
then: function(resolveHandler, rejectHandler) {
|
2717
|
-
return this.getPromise().then(resolveHandler, rejectHandler);
|
2718
|
-
},
|
2719
|
-
|
2720
|
-
'catch': function(handler) {
|
2721
|
-
return this.getPromise()['catch'](handler);
|
2722
|
-
},
|
2723
|
-
|
2724
|
-
'finally': function(handler) {
|
2725
|
-
return this.getPromise()['finally'](handler);
|
2726
|
-
},
|
2727
|
-
|
2728
|
-
pause: function() {
|
2729
|
-
if (this.host.pause) {
|
2730
|
-
this.host.pause();
|
2731
|
-
}
|
2732
|
-
},
|
2733
|
-
|
2734
|
-
resume: function() {
|
2735
|
-
if (this.host.resume) {
|
2736
|
-
this.host.resume();
|
2737
|
-
}
|
2738
|
-
},
|
2739
|
-
|
2740
|
-
end: function() {
|
2741
|
-
if (this.host.end) {
|
2742
|
-
this.host.end();
|
2743
|
-
}
|
2744
|
-
this._resolve(true);
|
2745
|
-
},
|
2746
|
-
|
2747
|
-
cancel: function() {
|
2748
|
-
if (this.host.cancel) {
|
2749
|
-
this.host.cancel();
|
2750
|
-
}
|
2751
|
-
this._resolve(false);
|
2752
|
-
},
|
2753
|
-
|
2754
|
-
complete: function(response) {
|
2755
|
-
var self = this;
|
2756
|
-
if (self._state === INITIAL_STATE) {
|
2757
|
-
self._state = DONE_PENDING_STATE;
|
2758
|
-
self._runInAnimationFrame(function() {
|
2759
|
-
self._resolve(response);
|
2760
|
-
});
|
2761
|
-
}
|
2762
|
-
},
|
2763
|
-
|
2764
|
-
_resolve: function(response) {
|
2765
|
-
if (this._state !== DONE_COMPLETE_STATE) {
|
2766
|
-
forEach(this._doneCallbacks, function(fn) {
|
2767
|
-
fn(response);
|
2768
|
-
});
|
2769
|
-
this._doneCallbacks.length = 0;
|
2770
|
-
this._state = DONE_COMPLETE_STATE;
|
2771
|
-
}
|
2772
|
-
}
|
2773
|
-
};
|
2774
|
-
|
2775
|
-
return AnimateRunner;
|
2776
|
-
}];
|
2777
|
-
|
2778
2823
|
var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
2779
2824
|
var NG_ANIMATE_REF_ATTR = 'ng-animate-ref';
|
2780
2825
|
|
@@ -2910,6 +2955,12 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
|
2910
2955
|
options.tempClasses = null;
|
2911
2956
|
}
|
2912
2957
|
|
2958
|
+
var prepareClassName;
|
2959
|
+
if (isStructural) {
|
2960
|
+
prepareClassName = 'ng-' + event + PREPARE_CLASS_SUFFIX;
|
2961
|
+
$$jqLite.addClass(element, prepareClassName);
|
2962
|
+
}
|
2963
|
+
|
2913
2964
|
animationQueue.push({
|
2914
2965
|
// this data is used by the postDigest code and passed into
|
2915
2966
|
// the driver step function
|
@@ -3074,7 +3125,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
|
3074
3125
|
};
|
3075
3126
|
|
3076
3127
|
// the anchor animations require that the from and to elements both have at least
|
3077
|
-
// one shared CSS class which
|
3128
|
+
// one shared CSS class which effectively marries the two elements together to use
|
3078
3129
|
// the same animation driver and to properly sequence the anchor animation.
|
3079
3130
|
if (group.classes.length) {
|
3080
3131
|
preparedAnimations.push(group);
|
@@ -3132,6 +3183,10 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
|
3132
3183
|
if (tempClasses) {
|
3133
3184
|
$$jqLite.addClass(element, tempClasses);
|
3134
3185
|
}
|
3186
|
+
if (prepareClassName) {
|
3187
|
+
$$jqLite.removeClass(element, prepareClassName);
|
3188
|
+
prepareClassName = null;
|
3189
|
+
}
|
3135
3190
|
}
|
3136
3191
|
|
3137
3192
|
function updateAnimationRunners(animation, newRunner) {
|
@@ -3173,12 +3228,121 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
|
3173
3228
|
}];
|
3174
3229
|
}];
|
3175
3230
|
|
3231
|
+
/**
|
3232
|
+
* @ngdoc directive
|
3233
|
+
* @name ngAnimateSwap
|
3234
|
+
* @restrict A
|
3235
|
+
* @scope
|
3236
|
+
*
|
3237
|
+
* @description
|
3238
|
+
*
|
3239
|
+
* ngAnimateSwap is a animation-oriented directive that allows for the container to
|
3240
|
+
* be removed and entered in whenever the associated expression changes. A
|
3241
|
+
* common usecase for this directive is a rotating banner component which
|
3242
|
+
* contains one image being present at a time. When the active image changes
|
3243
|
+
* then the old image will perform a `leave` animation and the new element
|
3244
|
+
* will be inserted via an `enter` animation.
|
3245
|
+
*
|
3246
|
+
* @example
|
3247
|
+
* <example name="ngAnimateSwap-directive" module="ngAnimateSwapExample"
|
3248
|
+
* deps="angular-animate.js"
|
3249
|
+
* animations="true" fixBase="true">
|
3250
|
+
* <file name="index.html">
|
3251
|
+
* <div class="container" ng-controller="AppCtrl">
|
3252
|
+
* <div ng-animate-swap="number" class="cell swap-animation" ng-class="colorClass(number)">
|
3253
|
+
* {{ number }}
|
3254
|
+
* </div>
|
3255
|
+
* </div>
|
3256
|
+
* </file>
|
3257
|
+
* <file name="script.js">
|
3258
|
+
* angular.module('ngAnimateSwapExample', ['ngAnimate'])
|
3259
|
+
* .controller('AppCtrl', ['$scope', '$interval', function($scope, $interval) {
|
3260
|
+
* $scope.number = 0;
|
3261
|
+
* $interval(function() {
|
3262
|
+
* $scope.number++;
|
3263
|
+
* }, 1000);
|
3264
|
+
*
|
3265
|
+
* var colors = ['red','blue','green','yellow','orange'];
|
3266
|
+
* $scope.colorClass = function(number) {
|
3267
|
+
* return colors[number % colors.length];
|
3268
|
+
* };
|
3269
|
+
* }]);
|
3270
|
+
* </file>
|
3271
|
+
* <file name="animations.css">
|
3272
|
+
* .container {
|
3273
|
+
* height:250px;
|
3274
|
+
* width:250px;
|
3275
|
+
* position:relative;
|
3276
|
+
* overflow:hidden;
|
3277
|
+
* border:2px solid black;
|
3278
|
+
* }
|
3279
|
+
* .container .cell {
|
3280
|
+
* font-size:150px;
|
3281
|
+
* text-align:center;
|
3282
|
+
* line-height:250px;
|
3283
|
+
* position:absolute;
|
3284
|
+
* top:0;
|
3285
|
+
* left:0;
|
3286
|
+
* right:0;
|
3287
|
+
* border-bottom:2px solid black;
|
3288
|
+
* }
|
3289
|
+
* .swap-animation.ng-enter, .swap-animation.ng-leave {
|
3290
|
+
* transition:0.5s linear all;
|
3291
|
+
* }
|
3292
|
+
* .swap-animation.ng-enter {
|
3293
|
+
* top:-250px;
|
3294
|
+
* }
|
3295
|
+
* .swap-animation.ng-enter-active {
|
3296
|
+
* top:0px;
|
3297
|
+
* }
|
3298
|
+
* .swap-animation.ng-leave {
|
3299
|
+
* top:0px;
|
3300
|
+
* }
|
3301
|
+
* .swap-animation.ng-leave-active {
|
3302
|
+
* top:250px;
|
3303
|
+
* }
|
3304
|
+
* .red { background:red; }
|
3305
|
+
* .green { background:green; }
|
3306
|
+
* .blue { background:blue; }
|
3307
|
+
* .yellow { background:yellow; }
|
3308
|
+
* .orange { background:orange; }
|
3309
|
+
* </file>
|
3310
|
+
* </example>
|
3311
|
+
*/
|
3312
|
+
var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $rootScope) {
|
3313
|
+
return {
|
3314
|
+
restrict: 'A',
|
3315
|
+
transclude: 'element',
|
3316
|
+
terminal: true,
|
3317
|
+
priority: 600, // we use 600 here to ensure that the directive is caught before others
|
3318
|
+
link: function(scope, $element, attrs, ctrl, $transclude) {
|
3319
|
+
var previousElement, previousScope;
|
3320
|
+
scope.$watchCollection(attrs.ngAnimateSwap || attrs['for'], function(value) {
|
3321
|
+
if (previousElement) {
|
3322
|
+
$animate.leave(previousElement);
|
3323
|
+
}
|
3324
|
+
if (previousScope) {
|
3325
|
+
previousScope.$destroy();
|
3326
|
+
previousScope = null;
|
3327
|
+
}
|
3328
|
+
if (value || value === 0) {
|
3329
|
+
previousScope = scope.$new();
|
3330
|
+
$transclude(previousScope, function(element) {
|
3331
|
+
previousElement = element;
|
3332
|
+
$animate.enter(element, null, $element);
|
3333
|
+
});
|
3334
|
+
}
|
3335
|
+
});
|
3336
|
+
}
|
3337
|
+
};
|
3338
|
+
}];
|
3339
|
+
|
3176
3340
|
/* global angularAnimateModule: true,
|
3177
3341
|
|
3342
|
+
ngAnimateSwapDirective,
|
3178
3343
|
$$AnimateAsyncRunFactory,
|
3179
3344
|
$$rAFSchedulerFactory,
|
3180
3345
|
$$AnimateChildrenDirective,
|
3181
|
-
$$AnimateRunnerFactory,
|
3182
3346
|
$$AnimateQueueProvider,
|
3183
3347
|
$$AnimationProvider,
|
3184
3348
|
$AnimateCssProvider,
|
@@ -3427,11 +3591,39 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
|
3427
3591
|
* the CSS class once an animation has completed.)
|
3428
3592
|
*
|
3429
3593
|
*
|
3594
|
+
* ### The `ng-[event]-prepare` class
|
3595
|
+
*
|
3596
|
+
* This is a special class that can be used to prevent unwanted flickering / flash of content before
|
3597
|
+
* the actual animation starts. The class is added as soon as an animation is initialized, but removed
|
3598
|
+
* before the actual animation starts (after waiting for a $digest).
|
3599
|
+
* It is also only added for *structural* animations (`enter`, `move`, and `leave`).
|
3600
|
+
*
|
3601
|
+
* In practice, flickering can appear when nesting elements with structural animations such as `ngIf`
|
3602
|
+
* into elements that have class-based animations such as `ngClass`.
|
3603
|
+
*
|
3604
|
+
* ```html
|
3605
|
+
* <div ng-class="{red: myProp}">
|
3606
|
+
* <div ng-class="{blue: myProp}">
|
3607
|
+
* <div class="message" ng-if="myProp"></div>
|
3608
|
+
* </div>
|
3609
|
+
* </div>
|
3610
|
+
* ```
|
3611
|
+
*
|
3612
|
+
* It is possible that during the `enter` animation, the `.message` div will be briefly visible before it starts animating.
|
3613
|
+
* In that case, you can add styles to the CSS that make sure the element stays hidden before the animation starts:
|
3614
|
+
*
|
3615
|
+
* ```css
|
3616
|
+
* .message.ng-enter-prepare {
|
3617
|
+
* opacity: 0;
|
3618
|
+
* }
|
3619
|
+
*
|
3620
|
+
* ```
|
3621
|
+
*
|
3430
3622
|
* ## JavaScript-based Animations
|
3431
3623
|
*
|
3432
3624
|
* ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
|
3433
3625
|
* CSS class that is referenced in our HTML code) but in addition we need to register the JavaScript animation on the module. By making use of the
|
3434
|
-
* `module.animation()` module function we can register the
|
3626
|
+
* `module.animation()` module function we can register the animation.
|
3435
3627
|
*
|
3436
3628
|
* Let's see an example of a enter/leave animation using `ngRepeat`:
|
3437
3629
|
*
|
@@ -3911,12 +4103,11 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
|
|
3911
4103
|
* Click here {@link ng.$animate to learn more about animations with `$animate`}.
|
3912
4104
|
*/
|
3913
4105
|
angular.module('ngAnimate', [])
|
4106
|
+
.directive('ngAnimateSwap', ngAnimateSwapDirective)
|
4107
|
+
|
3914
4108
|
.directive('ngAnimateChildren', $$AnimateChildrenDirective)
|
3915
4109
|
.factory('$$rAFScheduler', $$rAFSchedulerFactory)
|
3916
4110
|
|
3917
|
-
.factory('$$AnimateRunner', $$AnimateRunnerFactory)
|
3918
|
-
.factory('$$animateAsyncRun', $$AnimateAsyncRunFactory)
|
3919
|
-
|
3920
4111
|
.provider('$$animateQueue', $$AnimateQueueProvider)
|
3921
4112
|
.provider('$$animation', $$AnimationProvider)
|
3922
4113
|
|