angularjs-rails 1.4.8 → 1.5.0
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.
- 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
|
|