angularjs-rails 1.4.4 → 1.4.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37c8e1b04bad364744d395f5bfdf6a037c367097
4
- data.tar.gz: 68c9df5a22bfa5d8aa55e44d3bd369dd4c769375
3
+ metadata.gz: 7bae5d9940bff568ab17129d188748335bd1cc9f
4
+ data.tar.gz: 9a01f2802010654a254df0e1fc59928138aa5a31
5
5
  SHA512:
6
- metadata.gz: 5602e1bf4c213d6642d2a07a13139f14c1d07efa3db4d06fbdb88a7ebda77739efacc0e068694b5fb09ea4640eb1fd10993ec94411bd41c67b4d231115659f64
7
- data.tar.gz: 43cb6417936b9847a8db5101a9eb3f74d6a6ce3e4bd4eec0faa9762e014ecfa3aed3724e8f566e9d5973e21700ed48adf2d3a064186c97f0584dd08ff5e10fba
6
+ metadata.gz: fcf4268bf060a5ab19e0244aa3f1a12e771eca9ed57b25b2dd3edf1f56552d678cc7bf829128df527e185a7f920c2708f30d86497ffe8cb83bfd9781b1d87623
7
+ data.tar.gz: 6c9efedf3be8ddd17f046264fd67495fb15ffbdd96bff38c66f289f30772e8a15260433c53daa425c7c5adc45fad530435870c82c179ac2d2f8531c6b3be1417
@@ -1,6 +1,6 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.4.4"
4
- UNSTABLE_VERSION = "2.0.0-alpha.34"
3
+ VERSION = "1.4.7"
4
+ UNSTABLE_VERSION = "2.0.0-alpha.37"
5
5
  end
6
6
  end
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.4.4
2
+ * @license AngularJS v1.4.7
3
3
  * (c) 2010-2015 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -41,7 +41,7 @@ var CSS_PREFIX = '', TRANSITION_PROP, TRANSITIONEND_EVENT, ANIMATION_PROP, ANIMA
41
41
  // Also, the only modern browser that uses vendor prefixes for transitions/keyframes is webkit
42
42
  // therefore there is no reason to test anymore for other vendor prefixes:
43
43
  // http://caniuse.com/#search=transition
44
- if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) {
44
+ if (isUndefined(window.ontransitionend) && isDefined(window.onwebkittransitionend)) {
45
45
  CSS_PREFIX = '-webkit-';
46
46
  TRANSITION_PROP = 'WebkitTransition';
47
47
  TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend';
@@ -50,7 +50,7 @@ if (window.ontransitionend === undefined && window.onwebkittransitionend !== und
50
50
  TRANSITIONEND_EVENT = 'transitionend';
51
51
  }
52
52
 
53
- if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) {
53
+ if (isUndefined(window.onanimationend) && isDefined(window.onwebkitanimationend)) {
54
54
  CSS_PREFIX = '-webkit-';
55
55
  ANIMATION_PROP = 'WebkitAnimation';
56
56
  ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend';
@@ -373,11 +373,54 @@ function concatWithSpace(a,b) {
373
373
  return a + ' ' + b;
374
374
  }
375
375
 
376
- function $$BodyProvider() {
377
- this.$get = ['$document', function($document) {
378
- return jqLite($document[0].body);
379
- }];
380
- }
376
+ var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
377
+ var queue, cancelFn;
378
+
379
+ function scheduler(tasks) {
380
+ // we make a copy since RAFScheduler mutates the state
381
+ // of the passed in array variable and this would be difficult
382
+ // to track down on the outside code
383
+ queue = queue.concat(tasks);
384
+ nextTick();
385
+ }
386
+
387
+ queue = scheduler.queue = [];
388
+
389
+ /* waitUntilQuiet does two things:
390
+ * 1. It will run the FINAL `fn` value only when an uncancelled RAF has passed through
391
+ * 2. It will delay the next wave of tasks from running until the quiet `fn` has run.
392
+ *
393
+ * The motivation here is that animation code can request more time from the scheduler
394
+ * before the next wave runs. This allows for certain DOM properties such as classes to
395
+ * be resolved in time for the next animation to run.
396
+ */
397
+ scheduler.waitUntilQuiet = function(fn) {
398
+ if (cancelFn) cancelFn();
399
+
400
+ cancelFn = $$rAF(function() {
401
+ cancelFn = null;
402
+ fn();
403
+ nextTick();
404
+ });
405
+ };
406
+
407
+ return scheduler;
408
+
409
+ function nextTick() {
410
+ if (!queue.length) return;
411
+
412
+ var items = queue.shift();
413
+ for (var i = 0; i < items.length; i++) {
414
+ items[i]();
415
+ }
416
+
417
+ if (!cancelFn) {
418
+ $$rAF(function() {
419
+ if (!cancelFn) nextTick();
420
+ });
421
+ }
422
+ }
423
+ }];
381
424
 
382
425
  var $$AnimateChildrenDirective = [function() {
383
426
  return function(scope, element, attrs) {
@@ -393,6 +436,8 @@ var $$AnimateChildrenDirective = [function() {
393
436
  };
394
437
  }];
395
438
 
439
+ var ANIMATE_TIMER_KEY = '$$animateCss';
440
+
396
441
  /**
397
442
  * @ngdoc service
398
443
  * @name $animateCss
@@ -578,7 +623,7 @@ var $$AnimateChildrenDirective = [function() {
578
623
  * * `event` - The DOM event (e.g. enter, leave, move). When used, a generated CSS class of `ng-EVENT` and `ng-EVENT-active` will be applied
579
624
  * to the element during the animation. Multiple events can be provided when spaces are used as a separator. (Note that this will not perform any DOM operation.)
580
625
  * * `easing` - The CSS easing value that will be applied to the transition or keyframe animation (or both).
581
- * * `transition` - The raw CSS transition style that will be used (e.g. `1s linear all`).
626
+ * * `transitionStyle` - The raw CSS transition style that will be used (e.g. `1s linear all`).
582
627
  * * `keyframeStyle` - The raw CSS keyframe animation style that will be used (e.g. `1s my_animation linear`).
583
628
  * * `from` - The starting CSS styles (a key/value object) that will be applied at the start of the animation.
584
629
  * * `to` - The ending CSS styles (a key/value object) that will be applied across the animation via a CSS transition.
@@ -595,6 +640,10 @@ var $$AnimateChildrenDirective = [function() {
595
640
  * * `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
596
641
  * * `stagger` option value of `0.1` is used then there will be a stagger delay of `600ms`)
597
642
  * * `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 occuring on the classes being added and removed.)
643
+ * * `cleanupStyles` - Whether or not the provided `from` and `to` styles will be removed once
644
+ * the animation is closed. This is useful for when the styles are used purely for the sake of
645
+ * the animation and do not have a lasting visual effect on the element (e.g. a colapse and open animation).
646
+ * By default this value is set to `false`.
598
647
  *
599
648
  * @return {object} an object with start and end methods and details about the animation.
600
649
  *
@@ -715,12 +764,31 @@ function createLocalCacheLookup() {
715
764
  };
716
765
  }
717
766
 
767
+ // we do not reassign an already present style value since
768
+ // if we detect the style property value again we may be
769
+ // detecting styles that were added via the `from` styles.
770
+ // We make use of `isDefined` here since an empty string
771
+ // or null value (which is what getPropertyValue will return
772
+ // for a non-existing style) will still be marked as a valid
773
+ // value for the style (a falsy value implies that the style
774
+ // is to be removed at the end of the animation). If we had a simple
775
+ // "OR" statement then it would not be enough to catch that.
776
+ function registerRestorableStyles(backup, node, properties) {
777
+ forEach(properties, function(prop) {
778
+ backup[prop] = isDefined(backup[prop])
779
+ ? backup[prop]
780
+ : node.style.getPropertyValue(prop);
781
+ });
782
+ }
783
+
718
784
  var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
719
785
  var gcsLookup = createLocalCacheLookup();
720
786
  var gcsStaggerLookup = createLocalCacheLookup();
721
787
 
722
- this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$forceReflow', '$sniffer', '$$rAF',
723
- function($window, $$jqLite, $$AnimateRunner, $timeout, $$forceReflow, $sniffer, $$rAF) {
788
+ this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
789
+ '$$forceReflow', '$sniffer', '$$rAFScheduler', '$animate',
790
+ function($window, $$jqLite, $$AnimateRunner, $timeout,
791
+ $$forceReflow, $sniffer, $$rAFScheduler, $animate) {
724
792
 
725
793
  var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
726
794
 
@@ -780,12 +848,8 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
780
848
  var cancelLastRAFRequest;
781
849
  var rafWaitQueue = [];
782
850
  function waitUntilQuiet(callback) {
783
- if (cancelLastRAFRequest) {
784
- cancelLastRAFRequest(); //cancels the request
785
- }
786
851
  rafWaitQueue.push(callback);
787
- cancelLastRAFRequest = $$rAF(function() {
788
- cancelLastRAFRequest = null;
852
+ $$rAFScheduler.waitUntilQuiet(function() {
789
853
  gcsLookup.flush();
790
854
  gcsStaggerLookup.flush();
791
855
 
@@ -802,8 +866,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
802
866
  });
803
867
  }
804
868
 
805
- return init;
806
-
807
869
  function computeTimings(node, className, cacheKey) {
808
870
  var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
809
871
  var aD = timings.animationDelay;
@@ -818,9 +880,12 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
818
880
  return timings;
819
881
  }
820
882
 
821
- function init(element, options) {
883
+ return function init(element, options) {
884
+ var restoreStyles = {};
822
885
  var node = getDomNode(element);
823
- if (!node || !node.parentNode) {
886
+ if (!node
887
+ || !node.parentNode
888
+ || !$animate.enabled()) {
824
889
  return closeAndReturnNoopAnimator();
825
890
  }
826
891
 
@@ -876,7 +941,6 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
876
941
  // there actually is a detected transition or keyframe animation
877
942
  if (options.applyClassesEarly && addRemoveClassName.length) {
878
943
  applyAnimationClasses(element, options);
879
- addRemoveClassName = '';
880
944
  }
881
945
 
882
946
  var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
@@ -991,6 +1055,18 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
991
1055
  return closeAndReturnNoopAnimator();
992
1056
  }
993
1057
 
1058
+ if (options.delay != null) {
1059
+ var delayStyle = parseFloat(options.delay);
1060
+
1061
+ if (flags.applyTransitionDelay) {
1062
+ temporaryStyles.push(getCssDelayStyle(delayStyle));
1063
+ }
1064
+
1065
+ if (flags.applyAnimationDelay) {
1066
+ temporaryStyles.push(getCssDelayStyle(delayStyle, true));
1067
+ }
1068
+ }
1069
+
994
1070
  // we need to recalculate the delay value since we used a pre-emptive negative
995
1071
  // delay value and the delay value is required for the final event checking. This
996
1072
  // property will ensure that this will happen after the RAF phase has passed.
@@ -1007,7 +1083,12 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
1007
1083
  stagger.animationDuration === 0;
1008
1084
  }
1009
1085
 
1010
- applyAnimationFromStyles(element, options);
1086
+ if (options.from) {
1087
+ if (options.cleanupStyles) {
1088
+ registerRestorableStyles(restoreStyles, node, Object.keys(options.from));
1089
+ }
1090
+ applyAnimationFromStyles(element, options);
1091
+ }
1011
1092
 
1012
1093
  if (flags.blockTransition || flags.blockKeyframeAnimation) {
1013
1094
  applyBlocking(maxDuration);
@@ -1074,6 +1155,13 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
1074
1155
  applyAnimationClasses(element, options);
1075
1156
  applyAnimationStyles(element, options);
1076
1157
 
1158
+ if (Object.keys(restoreStyles).length) {
1159
+ forEach(restoreStyles, function(value, prop) {
1160
+ value ? node.style.setProperty(prop, value)
1161
+ : node.style.removeProperty(prop);
1162
+ });
1163
+ }
1164
+
1077
1165
  // the reason why we have this option is to allow a synchronous closing callback
1078
1166
  // that is fired as SOON as the animation ends (when the CSS is removed) or if
1079
1167
  // the animation never takes off at all. A good example is a leave animation since
@@ -1105,6 +1193,8 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
1105
1193
  cancel: cancelFn
1106
1194
  });
1107
1195
 
1196
+ // should flush the cache animation
1197
+ waitUntilQuiet(noop);
1108
1198
  close();
1109
1199
 
1110
1200
  return {
@@ -1202,27 +1292,16 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
1202
1292
  flags.hasAnimations = timings.animationDuration > 0;
1203
1293
  }
1204
1294
 
1205
- if (flags.applyTransitionDelay || flags.applyAnimationDelay) {
1295
+ if (flags.applyAnimationDelay) {
1206
1296
  relativeDelay = typeof options.delay !== "boolean" && truthyTimingValue(options.delay)
1207
1297
  ? parseFloat(options.delay)
1208
1298
  : relativeDelay;
1209
1299
 
1210
1300
  maxDelay = Math.max(relativeDelay, 0);
1211
-
1212
- var delayStyle;
1213
- if (flags.applyTransitionDelay) {
1214
- timings.transitionDelay = relativeDelay;
1215
- delayStyle = getCssDelayStyle(relativeDelay);
1216
- temporaryStyles.push(delayStyle);
1217
- node.style[delayStyle[0]] = delayStyle[1];
1218
- }
1219
-
1220
- if (flags.applyAnimationDelay) {
1221
- timings.animationDelay = relativeDelay;
1222
- delayStyle = getCssDelayStyle(relativeDelay, true);
1223
- temporaryStyles.push(delayStyle);
1224
- node.style[delayStyle[0]] = delayStyle[1];
1225
- }
1301
+ timings.animationDelay = relativeDelay;
1302
+ delayStyle = getCssDelayStyle(relativeDelay, true);
1303
+ temporaryStyles.push(delayStyle);
1304
+ node.style[delayStyle[0]] = delayStyle[1];
1226
1305
  }
1227
1306
 
1228
1307
  maxDelayTime = maxDelay * ONE_SECOND;
@@ -1251,17 +1330,52 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
1251
1330
  }
1252
1331
 
1253
1332
  startTime = Date.now();
1254
- element.on(events.join(' '), onAnimationProgress);
1255
- $timeout(onAnimationExpired, maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime, false);
1333
+ var timerTime = maxDelayTime + CLOSING_TIME_BUFFER * maxDurationTime;
1334
+ var endTime = startTime + timerTime;
1335
+
1336
+ var animationsData = element.data(ANIMATE_TIMER_KEY) || [];
1337
+ var setupFallbackTimer = true;
1338
+ if (animationsData.length) {
1339
+ var currentTimerData = animationsData[0];
1340
+ setupFallbackTimer = endTime > currentTimerData.expectedEndTime;
1341
+ if (setupFallbackTimer) {
1342
+ $timeout.cancel(currentTimerData.timer);
1343
+ } else {
1344
+ animationsData.push(close);
1345
+ }
1346
+ }
1347
+
1348
+ if (setupFallbackTimer) {
1349
+ var timer = $timeout(onAnimationExpired, timerTime, false);
1350
+ animationsData[0] = {
1351
+ timer: timer,
1352
+ expectedEndTime: endTime
1353
+ };
1354
+ animationsData.push(close);
1355
+ element.data(ANIMATE_TIMER_KEY, animationsData);
1356
+ }
1256
1357
 
1257
- applyAnimationToStyles(element, options);
1358
+ element.on(events.join(' '), onAnimationProgress);
1359
+ if (options.to) {
1360
+ if (options.cleanupStyles) {
1361
+ registerRestorableStyles(restoreStyles, node, Object.keys(options.to));
1362
+ }
1363
+ applyAnimationToStyles(element, options);
1364
+ }
1258
1365
  }
1259
1366
 
1260
1367
  function onAnimationExpired() {
1261
- // although an expired animation is a failed animation, getting to
1262
- // this outcome is very easy if the CSS code screws up. Therefore we
1263
- // should still continue normally as if the animation completed correctly.
1264
- close();
1368
+ var animationsData = element.data(ANIMATE_TIMER_KEY);
1369
+
1370
+ // this will be false in the event that the element was
1371
+ // removed from the DOM (via a leave animation or something
1372
+ // similar)
1373
+ if (animationsData) {
1374
+ for (var i = 1; i < animationsData.length; i++) {
1375
+ animationsData[i]();
1376
+ }
1377
+ element.removeData(ANIMATE_TIMER_KEY);
1378
+ }
1265
1379
  }
1266
1380
 
1267
1381
  function onAnimationProgress(event) {
@@ -1288,7 +1402,7 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
1288
1402
  }
1289
1403
  }
1290
1404
  }
1291
- }
1405
+ };
1292
1406
  }];
1293
1407
  }];
1294
1408
 
@@ -1301,26 +1415,35 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
1301
1415
  var NG_OUT_ANCHOR_CLASS_NAME = 'ng-anchor-out';
1302
1416
  var NG_IN_ANCHOR_CLASS_NAME = 'ng-anchor-in';
1303
1417
 
1304
- this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$$body', '$sniffer', '$$jqLite',
1305
- function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $$body, $sniffer, $$jqLite) {
1418
+ function isDocumentFragment(node) {
1419
+ return node.parentNode && node.parentNode.nodeType === 11;
1420
+ }
1421
+
1422
+ this.$get = ['$animateCss', '$rootScope', '$$AnimateRunner', '$rootElement', '$sniffer', '$$jqLite', '$document',
1423
+ function($animateCss, $rootScope, $$AnimateRunner, $rootElement, $sniffer, $$jqLite, $document) {
1306
1424
 
1307
1425
  // only browsers that support these properties can render animations
1308
1426
  if (!$sniffer.animations && !$sniffer.transitions) return noop;
1309
1427
 
1310
- var bodyNode = getDomNode($$body);
1428
+ var bodyNode = $document[0].body;
1311
1429
  var rootNode = getDomNode($rootElement);
1312
1430
 
1313
- var rootBodyElement = jqLite(bodyNode.parentNode === rootNode ? bodyNode : rootNode);
1431
+ var rootBodyElement = jqLite(
1432
+ // this is to avoid using something that exists outside of the body
1433
+ // we also special case the doc fragement case because our unit test code
1434
+ // appends the $rootElement to the body after the app has been bootstrapped
1435
+ isDocumentFragment(rootNode) || bodyNode.contains(rootNode) ? rootNode : bodyNode
1436
+ );
1314
1437
 
1315
1438
  var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
1316
1439
 
1317
- return function initDriverFn(animationDetails, onBeforeClassesAppliedCb) {
1440
+ return function initDriverFn(animationDetails) {
1318
1441
  return animationDetails.from && animationDetails.to
1319
1442
  ? prepareFromToAnchorAnimation(animationDetails.from,
1320
1443
  animationDetails.to,
1321
1444
  animationDetails.classes,
1322
1445
  animationDetails.anchors)
1323
- : prepareRegularAnimation(animationDetails, onBeforeClassesAppliedCb);
1446
+ : prepareRegularAnimation(animationDetails);
1324
1447
  };
1325
1448
 
1326
1449
  function filterCssClasses(classes) {
@@ -1516,21 +1639,14 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
1516
1639
  };
1517
1640
  }
1518
1641
 
1519
- function prepareRegularAnimation(animationDetails, onBeforeClassesAppliedCb) {
1642
+ function prepareRegularAnimation(animationDetails) {
1520
1643
  var element = animationDetails.element;
1521
1644
  var options = animationDetails.options || {};
1522
1645
 
1523
- // since the ng-EVENT, class-ADD and class-REMOVE classes are applied inside
1524
- // of the animateQueue pre and postDigest stages then there is no need to add
1525
- // then them here as well.
1526
- options.$$skipPreparationClasses = true;
1527
-
1528
- // during the pre/post digest stages inside of animateQueue we also performed
1529
- // the blocking (transition:-9999s) so there is no point in doing that again.
1530
- options.skipBlocking = true;
1531
-
1532
1646
  if (animationDetails.structural) {
1533
1647
  options.event = animationDetails.event;
1648
+ options.structural = true;
1649
+ options.applyClassesEarly = true;
1534
1650
 
1535
1651
  // we special case the leave animation since we want to ensure that
1536
1652
  // the element is removed as soon as the animation is over. Otherwise
@@ -1540,11 +1656,6 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
1540
1656
  }
1541
1657
  }
1542
1658
 
1543
- // we apply the classes right away since the pre-digest took care of the
1544
- // preparation classes.
1545
- onBeforeClassesAppliedCb(element);
1546
- applyAnimationClasses(element, options);
1547
-
1548
1659
  // We assign the preparationClasses as the actual animation event since
1549
1660
  // the internals of $animateCss will just suffix the event token values
1550
1661
  // with `-active` to trigger the animation.
@@ -1568,8 +1679,8 @@ var $$AnimateCssDriverProvider = ['$$animationProvider', function($$animationPro
1568
1679
  // by the time...
1569
1680
 
1570
1681
  var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
1571
- this.$get = ['$injector', '$$AnimateRunner', '$$rAFMutex', '$$jqLite',
1572
- function($injector, $$AnimateRunner, $$rAFMutex, $$jqLite) {
1682
+ this.$get = ['$injector', '$$AnimateRunner', '$$jqLite',
1683
+ function($injector, $$AnimateRunner, $$jqLite) {
1573
1684
 
1574
1685
  var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
1575
1686
  // $animateJs(element, 'enter');
@@ -1949,15 +2060,33 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
1949
2060
  return (nO.addClass && nO.addClass === cO.removeClass) || (nO.removeClass && nO.removeClass === cO.addClass);
1950
2061
  });
1951
2062
 
1952
- this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$body', '$$HashMap',
2063
+ this.$get = ['$$rAF', '$rootScope', '$rootElement', '$document', '$$HashMap',
1953
2064
  '$$animation', '$$AnimateRunner', '$templateRequest', '$$jqLite', '$$forceReflow',
1954
- function($$rAF, $rootScope, $rootElement, $document, $$body, $$HashMap,
2065
+ function($$rAF, $rootScope, $rootElement, $document, $$HashMap,
1955
2066
  $$animation, $$AnimateRunner, $templateRequest, $$jqLite, $$forceReflow) {
1956
2067
 
1957
2068
  var activeAnimationsLookup = new $$HashMap();
1958
2069
  var disabledElementsLookup = new $$HashMap();
1959
2070
  var animationsEnabled = null;
1960
2071
 
2072
+ function postDigestTaskFactory() {
2073
+ var postDigestCalled = false;
2074
+ return function(fn) {
2075
+ // we only issue a call to postDigest before
2076
+ // it has first passed. This prevents any callbacks
2077
+ // from not firing once the animation has completed
2078
+ // since it will be out of the digest cycle.
2079
+ if (postDigestCalled) {
2080
+ fn();
2081
+ } else {
2082
+ $rootScope.$$postDigest(function() {
2083
+ postDigestCalled = true;
2084
+ fn();
2085
+ });
2086
+ }
2087
+ };
2088
+ }
2089
+
1961
2090
  // Wait until all directive and route-related templates are downloaded and
1962
2091
  // compiled. The $templateRequest.totalPendingRequests variable keeps track of
1963
2092
  // all of the remote templates being currently downloaded. If there are no
@@ -2020,14 +2149,6 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2020
2149
  return matches;
2021
2150
  }
2022
2151
 
2023
- function triggerCallback(event, element, phase, data) {
2024
- $$rAF(function() {
2025
- forEach(findCallbacks(element, event), function(callback) {
2026
- callback(element, phase, data);
2027
- });
2028
- });
2029
- }
2030
-
2031
2152
  return {
2032
2153
  on: function(event, container, callback) {
2033
2154
  var node = extractElementNode(container);
@@ -2122,6 +2243,9 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2122
2243
  // These methods will become available after the digest has passed
2123
2244
  var runner = new $$AnimateRunner();
2124
2245
 
2246
+ // this is used to trigger callbacks in postDigest mode
2247
+ var runInNextPostDigestOrNow = postDigestTaskFactory();
2248
+
2125
2249
  if (isArray(options.addClass)) {
2126
2250
  options.addClass = options.addClass.join(' ');
2127
2251
  }
@@ -2264,9 +2388,6 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2264
2388
  return runner;
2265
2389
  }
2266
2390
 
2267
- applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
2268
- blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
2269
-
2270
2391
  // the counter keeps track of cancelled animations
2271
2392
  var counter = (existingAnimation.counter || 0) + 1;
2272
2393
  newAnimation.counter = counter;
@@ -2325,10 +2446,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2325
2446
  : animationDetails.event;
2326
2447
 
2327
2448
  markElementAnimationState(element, RUNNING_STATE);
2328
- var realRunner = $$animation(element, event, animationDetails.options, function(e) {
2329
- $$forceReflow();
2330
- blockTransitions(getDomNode(e), false);
2331
- });
2449
+ var realRunner = $$animation(element, event, animationDetails.options);
2332
2450
 
2333
2451
  realRunner.done(function(status) {
2334
2452
  close(!status);
@@ -2348,7 +2466,20 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2348
2466
  return runner;
2349
2467
 
2350
2468
  function notifyProgress(runner, event, phase, data) {
2351
- triggerCallback(event, element, phase, data);
2469
+ runInNextPostDigestOrNow(function() {
2470
+ var callbacks = findCallbacks(element, event);
2471
+ if (callbacks.length) {
2472
+ // do not optimize this call here to RAF because
2473
+ // we don't know how heavy the callback code here will
2474
+ // be and if this code is buffered then this can
2475
+ // lead to a performance regression.
2476
+ $$rAF(function() {
2477
+ forEach(callbacks, function(callback) {
2478
+ callback(element, phase, data);
2479
+ });
2480
+ });
2481
+ }
2482
+ });
2352
2483
  runner.progress(event, phase, data);
2353
2484
  }
2354
2485
 
@@ -2391,7 +2522,8 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2391
2522
  }
2392
2523
 
2393
2524
  function areAnimationsAllowed(element, parentElement, event) {
2394
- var bodyElementDetected = isMatchingElement(element, $$body) || element[0].nodeName === 'HTML';
2525
+ var bodyElement = jqLite($document[0].body);
2526
+ var bodyElementDetected = isMatchingElement(element, bodyElement) || element[0].nodeName === 'HTML';
2395
2527
  var rootElementDetected = isMatchingElement(element, $rootElement);
2396
2528
  var parentAnimationDetected = false;
2397
2529
  var animateChildren;
@@ -2447,7 +2579,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2447
2579
  if (!bodyElementDetected) {
2448
2580
  // we also need to ensure that the element is or will be apart of the body element
2449
2581
  // otherwise it is pointless to even issue an animation to be rendered
2450
- bodyElementDetected = isMatchingElement(parentElement, $$body);
2582
+ bodyElementDetected = isMatchingElement(parentElement, bodyElement);
2451
2583
  }
2452
2584
 
2453
2585
  parentElement = parentElement.parent();
@@ -2473,19 +2605,34 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
2473
2605
  }];
2474
2606
  }];
2475
2607
 
2476
- var $$rAFMutexFactory = ['$$rAF', function($$rAF) {
2608
+ var $$AnimateAsyncRunFactory = ['$$rAF', function($$rAF) {
2609
+ var waitQueue = [];
2610
+
2611
+ function waitForTick(fn) {
2612
+ waitQueue.push(fn);
2613
+ if (waitQueue.length > 1) return;
2614
+ $$rAF(function() {
2615
+ for (var i = 0; i < waitQueue.length; i++) {
2616
+ waitQueue[i]();
2617
+ }
2618
+ waitQueue = [];
2619
+ });
2620
+ }
2621
+
2477
2622
  return function() {
2478
2623
  var passed = false;
2479
- $$rAF(function() {
2624
+ waitForTick(function() {
2480
2625
  passed = true;
2481
2626
  });
2482
- return function(fn) {
2483
- passed ? fn() : $$rAF(fn);
2627
+ return function(callback) {
2628
+ passed ? callback() : waitForTick(callback);
2484
2629
  };
2485
2630
  };
2486
2631
  }];
2487
2632
 
2488
- var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) {
2633
+ var $$AnimateRunnerFactory = ['$q', '$sniffer', '$$animateAsyncRun',
2634
+ function($q, $sniffer, $$animateAsyncRun) {
2635
+
2489
2636
  var INITIAL_STATE = 0;
2490
2637
  var DONE_PENDING_STATE = 1;
2491
2638
  var DONE_COMPLETE_STATE = 2;
@@ -2530,7 +2677,7 @@ var $$AnimateRunnerFactory = ['$q', '$$rAFMutex', function($q, $$rAFMutex) {
2530
2677
  this.setHost(host);
2531
2678
 
2532
2679
  this._doneCallbacks = [];
2533
- this._runInAnimationFrame = $$rAFMutex();
2680
+ this._runInAnimationFrame = $$animateAsyncRun();
2534
2681
  this._state = 0;
2535
2682
  }
2536
2683
 
@@ -2642,8 +2789,8 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2642
2789
  return element.data(RUNNER_STORAGE_KEY);
2643
2790
  }
2644
2791
 
2645
- this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$HashMap',
2646
- function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$HashMap) {
2792
+ this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$HashMap', '$$rAFScheduler',
2793
+ function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$HashMap, $$rAFScheduler) {
2647
2794
 
2648
2795
  var animationQueue = [];
2649
2796
  var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
@@ -2711,11 +2858,11 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2711
2858
  if (remainingLevelEntries <= 0) {
2712
2859
  remainingLevelEntries = nextLevelEntries;
2713
2860
  nextLevelEntries = 0;
2714
- result = result.concat(row);
2861
+ result.push(row);
2715
2862
  row = [];
2716
2863
  }
2717
2864
  row.push(entry.fn);
2718
- forEach(entry.children, function(childEntry) {
2865
+ entry.children.forEach(function(childEntry) {
2719
2866
  nextLevelEntries++;
2720
2867
  queue.push(childEntry);
2721
2868
  });
@@ -2723,14 +2870,15 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2723
2870
  }
2724
2871
 
2725
2872
  if (row.length) {
2726
- result = result.concat(row);
2873
+ result.push(row);
2727
2874
  }
2875
+
2728
2876
  return result;
2729
2877
  }
2730
2878
  }
2731
2879
 
2732
2880
  // TODO(matsko): document the signature in a better way
2733
- return function(element, event, options, onBeforeClassesAppliedCb) {
2881
+ return function(element, event, options) {
2734
2882
  options = prepareAnimationOptions(options);
2735
2883
  var isStructural = ['enter', 'move', 'leave'].indexOf(event) >= 0;
2736
2884
 
@@ -2782,8 +2930,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2782
2930
  // the element was destroyed early on which removed the runner
2783
2931
  // form its storage. This means we can't animate this element
2784
2932
  // at all and it already has been closed due to destruction.
2785
- var elm = entry.element;
2786
- if (getRunner(elm) && getDomNode(elm).parentNode) {
2933
+ if (getRunner(entry.element)) {
2787
2934
  animations.push(entry);
2788
2935
  } else {
2789
2936
  entry.close();
@@ -2814,7 +2961,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2814
2961
  : animationEntry.element;
2815
2962
 
2816
2963
  if (getRunner(targetElement)) {
2817
- var operation = invokeFirstDriver(animationEntry, onBeforeClassesAppliedCb);
2964
+ var operation = invokeFirstDriver(animationEntry);
2818
2965
  if (operation) {
2819
2966
  startAnimationFn = operation.start;
2820
2967
  }
@@ -2834,11 +2981,9 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2834
2981
  });
2835
2982
 
2836
2983
  // we need to sort each of the animations in order of parent to child
2837
- // relationships. This ensures that the parent to child classes are
2838
- // applied at the right time.
2839
- forEach(sortAnimations(toBeSortedAnimations), function(triggerAnimation) {
2840
- triggerAnimation();
2841
- });
2984
+ // relationships. This ensures that the child classes are applied at the
2985
+ // right time.
2986
+ $$rAFScheduler(sortAnimations(toBeSortedAnimations));
2842
2987
  });
2843
2988
 
2844
2989
  return runner;
@@ -2908,7 +3053,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2908
3053
  var lookupKey = from.animationID.toString();
2909
3054
  if (!anchorGroups[lookupKey]) {
2910
3055
  var group = anchorGroups[lookupKey] = {
2911
- // TODO(matsko): double-check this code
3056
+ structural: true,
2912
3057
  beforeStart: function() {
2913
3058
  fromAnimation.beforeStart();
2914
3059
  toAnimation.beforeStart();
@@ -2962,7 +3107,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2962
3107
  return matches.join(' ');
2963
3108
  }
2964
3109
 
2965
- function invokeFirstDriver(animationDetails, onBeforeClassesAppliedCb) {
3110
+ function invokeFirstDriver(animationDetails) {
2966
3111
  // we loop in reverse order since the more general drivers (like CSS and JS)
2967
3112
  // may attempt more elements, but custom drivers are more particular
2968
3113
  for (var i = drivers.length - 1; i >= 0; i--) {
@@ -2970,7 +3115,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
2970
3115
  if (!$injector.has(driverName)) continue; // TODO(matsko): remove this check
2971
3116
 
2972
3117
  var factory = $injector.get(driverName);
2973
- var driver = factory(animationDetails, onBeforeClassesAppliedCb);
3118
+ var driver = factory(animationDetails);
2974
3119
  if (driver) {
2975
3120
  return driver;
2976
3121
  }
@@ -3025,8 +3170,8 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3025
3170
 
3026
3171
  /* global angularAnimateModule: true,
3027
3172
 
3028
- $$BodyProvider,
3029
- $$rAFMutexFactory,
3173
+ $$AnimateAsyncRunFactory,
3174
+ $$rAFSchedulerFactory,
3030
3175
  $$AnimateChildrenDirective,
3031
3176
  $$AnimateRunnerFactory,
3032
3177
  $$AnimateQueueProvider,
@@ -3043,7 +3188,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3043
3188
  * @description
3044
3189
  *
3045
3190
  * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
3046
- * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` then the animation hooks are enabled for an Angular app.
3191
+ * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an Angular app.
3047
3192
  *
3048
3193
  * <div doc-module-components="ngAnimate"></div>
3049
3194
  *
@@ -3076,7 +3221,7 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3076
3221
  * CSS-based animations with ngAnimate are unique since they require no JavaScript code at all. By using a CSS class that we reference between our HTML
3077
3222
  * and CSS code we can create an animation that will be picked up by Angular when an the underlying directive performs an operation.
3078
3223
  *
3079
- * The example below shows how an `enter` animation can be made possible on a element using `ng-if`:
3224
+ * The example below shows how an `enter` animation can be made possible on an element using `ng-if`:
3080
3225
  *
3081
3226
  * ```html
3082
3227
  * <div ng-if="bool" class="fade">
@@ -3211,8 +3356,8 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3211
3356
  * /&#42; this will have a 100ms delay between each successive leave animation &#42;/
3212
3357
  * transition-delay: 0.1s;
3213
3358
  *
3214
- * /&#42; in case the stagger doesn't work then the duration value
3215
- * must be set to 0 to avoid an accidental CSS inheritance &#42;/
3359
+ * /&#42; As of 1.4.4, this must always be set: it signals ngAnimate
3360
+ * to not accidentally inherit a delay property from another CSS class &#42;/
3216
3361
  * transition-duration: 0s;
3217
3362
  * }
3218
3363
  * .my-animation.ng-enter.ng-enter-active {
@@ -3761,16 +3906,14 @@ var $$AnimationProvider = ['$animateProvider', function($animateProvider) {
3761
3906
  * @description
3762
3907
  * The ngAnimate `$animate` service documentation is the same for the core `$animate` service.
3763
3908
  *
3764
- * Click here {@link ng.$animate $animate to learn more about animations with `$animate`}.
3909
+ * Click here {@link ng.$animate to learn more about animations with `$animate`}.
3765
3910
  */
3766
3911
  angular.module('ngAnimate', [])
3767
- .provider('$$body', $$BodyProvider)
3768
-
3769
3912
  .directive('ngAnimateChildren', $$AnimateChildrenDirective)
3770
-
3771
- .factory('$$rAFMutex', $$rAFMutexFactory)
3913
+ .factory('$$rAFScheduler', $$rAFSchedulerFactory)
3772
3914
 
3773
3915
  .factory('$$AnimateRunner', $$AnimateRunnerFactory)
3916
+ .factory('$$animateAsyncRun', $$AnimateAsyncRunFactory)
3774
3917
 
3775
3918
  .provider('$$animateQueue', $$AnimateQueueProvider)
3776
3919
  .provider('$$animation', $$AnimationProvider)