angularjs-rails 1.6.8 → 1.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d0346663d08de97950aad209fbb29e10a07aba4e
4
- data.tar.gz: 1df11a0d515a6f1f6b89b60086ac4c1d03d99618
3
+ metadata.gz: b29491e1b540e7e1d87b0d88f3fbb5b4c9323ad1
4
+ data.tar.gz: b13e9fd5f9ac54ddf962b54cb69b14b5b2c5b0ad
5
5
  SHA512:
6
- metadata.gz: cc80cc06c5356f0d6db204b91bc19aed73200f352270bf28dbc709ee01d3a73dfe279fe2dcc7d9bb7c8d610e41d004ca5ae7bb0f06594d310b7a72b32ab04f27
7
- data.tar.gz: dc410a57c0a4c62b9921f4a44370d72368052799acf1783a3fc4ef3cd4e1134c76607a42de00fca3fcc3ab947b9d3a24491003f618362b1e62f0e1dc35ff6aba
6
+ metadata.gz: 10e912a2d702bf2ad0b87351940ae8e36fd4c6c5af5293c451dfb08ffc5184b171c66e4f527c378203a1519f28e91c2222d9f46ac700ac1b2956eaace08fa3ff
7
+ data.tar.gz: ea1946717238ceb9794c24141d470c49a681ad3937df953ebbb58d1270c025df4aeb073c61de03863a14f7a928d516c2a9a9baeb47bbbcd82aa41b10f2bc0c5e
data/README.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  angularjs-rails wraps the [Angular.js](http://angularjs.org) library for use in Rails 3.1 and above. Assets will minify automatically during production.
4
4
 
5
+ **If you find this gem useful, please consider donating - your contributions will help me keep this gem updated.**
6
+
7
+ [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=NCT7TZEFY2T9Y)
8
+
9
+
5
10
  ## Usage
6
11
 
7
12
  Add the following to your Gemfile:
@@ -29,4 +34,4 @@ The major, minor, and patch version numbers will always represent the Angular.js
29
34
 
30
35
  ## IMPORTANT: Requesting upgrades for new Angular.js versions
31
36
 
32
- Thanks to Nick Clark, we have an auto-upgrader that will upgrade the package to the latest version. To request that the latest version of Angular.JS be pushed as a gem to RubyGems, please create a new issue instead of pull requests.
37
+ To request that the latest version of Angular.JS be pushed as a gem to RubyGems, please create a new issue instead of pull requests.
@@ -1,6 +1,6 @@
1
1
  module AngularJS
2
2
  module Rails
3
- VERSION = "1.6.8"
3
+ VERSION = "1.8.0"
4
4
  UNSTABLE_VERSION = "2.0.0-beta.17"
5
5
  end
6
6
  end
@@ -1,6 +1,6 @@
1
1
  /**
2
- * @license AngularJS v1.6.8
3
- * (c) 2010-2017 Google, Inc. http://angularjs.org
2
+ * @license AngularJS v1.8.0
3
+ * (c) 2010-2020 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
6
6
  (function(window, angular) {'use strict';
@@ -306,7 +306,7 @@ function getDomNode(element) {
306
306
  return (element instanceof jqLite) ? element[0] : element;
307
307
  }
308
308
 
309
- function applyGeneratedPreparationClasses(element, event, options) {
309
+ function applyGeneratedPreparationClasses($$jqLite, element, event, options) {
310
310
  var classes = '';
311
311
  if (event) {
312
312
  classes = pendClasses(event, EVENT_CLASS_PREFIX, true);
@@ -334,15 +334,6 @@ function clearGeneratedClasses(element, options) {
334
334
  }
335
335
  }
336
336
 
337
- function blockTransitions(node, duration) {
338
- // we use a negative delay value since it performs blocking
339
- // yet it doesn't kill any existing transitions running on the
340
- // same element which makes this safe for class-based animations
341
- var value = duration ? '-' + duration + 's' : '';
342
- applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]);
343
- return [TRANSITION_DELAY_PROP, value];
344
- }
345
-
346
337
  function blockKeyframeAnimations(node, applyBlock) {
347
338
  var value = applyBlock ? 'paused' : '';
348
339
  var key = ANIMATION_PROP + ANIMATION_PLAYSTATE_KEY;
@@ -362,6 +353,17 @@ function concatWithSpace(a,b) {
362
353
  return a + ' ' + b;
363
354
  }
364
355
 
356
+ var helpers = {
357
+ blockTransitions: function(node, duration) {
358
+ // we use a negative delay value since it performs blocking
359
+ // yet it doesn't kill any existing transitions running on the
360
+ // same element which makes this safe for class-based animations
361
+ var value = duration ? '-' + duration + 's' : '';
362
+ applyInlineStyle(node, [TRANSITION_DELAY_PROP, value]);
363
+ return [TRANSITION_DELAY_PROP, value];
364
+ }
365
+ };
366
+
365
367
  var $$rAFSchedulerFactory = ['$$rAF', function($$rAF) {
366
368
  var queue, cancelFn;
367
369
 
@@ -532,7 +534,7 @@ var ANIMATE_TIMER_KEY = '$$animateCss';
532
534
  * Once again, `$animateCss` is designed to be used inside of a registered JavaScript animation that
533
535
  * is powered by ngAnimate. It is possible to use `$animateCss` directly inside of a directive, however,
534
536
  * any automatic control over cancelling animations and/or preventing animations from being run on
535
- * child elements will not be handled by Angular. For this to work as expected, please use `$animate` to
537
+ * child elements will not be handled by AngularJS. For this to work as expected, please use `$animate` to
536
538
  * trigger the animation and then setup a JavaScript animation that injects `$animateCss` to trigger
537
539
  * the CSS animation.
538
540
  *
@@ -814,33 +816,6 @@ function getCssTransitionDurationStyle(duration, applyOnlyDuration) {
814
816
  return [style, value];
815
817
  }
816
818
 
817
- function createLocalCacheLookup() {
818
- var cache = Object.create(null);
819
- return {
820
- flush: function() {
821
- cache = Object.create(null);
822
- },
823
-
824
- count: function(key) {
825
- var entry = cache[key];
826
- return entry ? entry.total : 0;
827
- },
828
-
829
- get: function(key) {
830
- var entry = cache[key];
831
- return entry && entry.value;
832
- },
833
-
834
- put: function(key, value) {
835
- if (!cache[key]) {
836
- cache[key] = { total: 1, value: value };
837
- } else {
838
- cache[key].total++;
839
- }
840
- }
841
- };
842
- }
843
-
844
819
  // we do not reassign an already present style value since
845
820
  // if we detect the style property value again we may be
846
821
  // detecting styles that were added via the `from` styles.
@@ -859,26 +834,16 @@ function registerRestorableStyles(backup, node, properties) {
859
834
  }
860
835
 
861
836
  var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animateProvider) {
862
- var gcsLookup = createLocalCacheLookup();
863
- var gcsStaggerLookup = createLocalCacheLookup();
864
837
 
865
- this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
838
+ this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$animateCache',
866
839
  '$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
867
- function($window, $$jqLite, $$AnimateRunner, $timeout,
840
+ function($window, $$jqLite, $$AnimateRunner, $timeout, $$animateCache,
868
841
  $$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
869
842
 
870
843
  var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
871
844
 
872
- var parentCounter = 0;
873
- function gcsHashFn(node, extraClasses) {
874
- var KEY = '$$ngAnimateParentKey';
875
- var parentNode = node.parentNode;
876
- var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
877
- return parentID + '-' + node.getAttribute('class') + '-' + extraClasses;
878
- }
879
-
880
- function computeCachedCssStyles(node, className, cacheKey, properties) {
881
- var timings = gcsLookup.get(cacheKey);
845
+ function computeCachedCssStyles(node, className, cacheKey, allowNoDuration, properties) {
846
+ var timings = $$animateCache.get(cacheKey);
882
847
 
883
848
  if (!timings) {
884
849
  timings = computeCssStyles($window, node, properties);
@@ -887,20 +852,26 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
887
852
  }
888
853
  }
889
854
 
855
+ // if a css animation has no duration we
856
+ // should mark that so that repeated addClass/removeClass calls are skipped
857
+ var hasDuration = allowNoDuration || (timings.transitionDuration > 0 || timings.animationDuration > 0);
858
+
890
859
  // we keep putting this in multiple times even though the value and the cacheKey are the same
891
860
  // because we're keeping an internal tally of how many duplicate animations are detected.
892
- gcsLookup.put(cacheKey, timings);
861
+ $$animateCache.put(cacheKey, timings, hasDuration);
862
+
893
863
  return timings;
894
864
  }
895
865
 
896
866
  function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
897
867
  var stagger;
868
+ var staggerCacheKey = 'stagger-' + cacheKey;
898
869
 
899
870
  // if we have one or more existing matches of matching elements
900
871
  // containing the same parent + CSS styles (which is how cacheKey works)
901
872
  // then staggering is possible
902
- if (gcsLookup.count(cacheKey) > 0) {
903
- stagger = gcsStaggerLookup.get(cacheKey);
873
+ if ($$animateCache.count(cacheKey) > 0) {
874
+ stagger = $$animateCache.get(staggerCacheKey);
904
875
 
905
876
  if (!stagger) {
906
877
  var staggerClassName = pendClasses(className, '-stagger');
@@ -915,7 +886,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
915
886
 
916
887
  $$jqLite.removeClass(node, staggerClassName);
917
888
 
918
- gcsStaggerLookup.put(cacheKey, stagger);
889
+ $$animateCache.put(staggerCacheKey, stagger, true);
919
890
  }
920
891
  }
921
892
 
@@ -926,8 +897,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
926
897
  function waitUntilQuiet(callback) {
927
898
  rafWaitQueue.push(callback);
928
899
  $$rAFScheduler.waitUntilQuiet(function() {
929
- gcsLookup.flush();
930
- gcsStaggerLookup.flush();
900
+ $$animateCache.flush();
931
901
 
932
902
  // DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
933
903
  // PLEASE EXAMINE THE `$$forceReflow` service to understand why.
@@ -942,8 +912,8 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
942
912
  });
943
913
  }
944
914
 
945
- function computeTimings(node, className, cacheKey) {
946
- var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
915
+ function computeTimings(node, className, cacheKey, allowNoDuration) {
916
+ var timings = computeCachedCssStyles(node, className, cacheKey, allowNoDuration, DETECT_CSS_PROPERTIES);
947
917
  var aD = timings.animationDelay;
948
918
  var tD = timings.transitionDelay;
949
919
  timings.maxDelay = aD && tD
@@ -1030,7 +1000,6 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1030
1000
 
1031
1001
  var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
1032
1002
  var fullClassName = classes + ' ' + preparationClasses;
1033
- var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
1034
1003
  var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
1035
1004
  var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
1036
1005
 
@@ -1043,7 +1012,12 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1043
1012
  return closeAndReturnNoopAnimator();
1044
1013
  }
1045
1014
 
1046
- var cacheKey, stagger;
1015
+ var stagger, cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
1016
+ if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
1017
+ preparationClasses = null;
1018
+ return closeAndReturnNoopAnimator();
1019
+ }
1020
+
1047
1021
  if (options.stagger > 0) {
1048
1022
  var staggerVal = parseFloat(options.stagger);
1049
1023
  stagger = {
@@ -1053,7 +1027,6 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1053
1027
  animationDuration: 0
1054
1028
  };
1055
1029
  } else {
1056
- cacheKey = gcsHashFn(node, fullClassName);
1057
1030
  stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
1058
1031
  }
1059
1032
 
@@ -1087,7 +1060,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1087
1060
  var itemIndex = stagger
1088
1061
  ? options.staggerIndex >= 0
1089
1062
  ? options.staggerIndex
1090
- : gcsLookup.count(cacheKey)
1063
+ : $$animateCache.count(cacheKey)
1091
1064
  : 0;
1092
1065
 
1093
1066
  var isFirst = itemIndex === 0;
@@ -1099,10 +1072,10 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1099
1072
  // that if there is no transition defined then nothing will happen and this will also allow
1100
1073
  // other transitions to be stacked on top of each other without any chopping them out.
1101
1074
  if (isFirst && !options.skipBlocking) {
1102
- blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
1075
+ helpers.blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
1103
1076
  }
1104
1077
 
1105
- var timings = computeTimings(node, fullClassName, cacheKey);
1078
+ var timings = computeTimings(node, fullClassName, cacheKey, !isStructural);
1106
1079
  var relativeDelay = timings.maxDelay;
1107
1080
  maxDelay = Math.max(relativeDelay, 0);
1108
1081
  maxDuration = timings.maxDuration;
@@ -1140,6 +1113,8 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1140
1113
  return closeAndReturnNoopAnimator();
1141
1114
  }
1142
1115
 
1116
+ var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
1117
+
1143
1118
  if (options.delay != null) {
1144
1119
  var delayStyle;
1145
1120
  if (typeof options.delay !== 'boolean') {
@@ -1183,7 +1158,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1183
1158
  if (flags.blockTransition || flags.blockKeyframeAnimation) {
1184
1159
  applyBlocking(maxDuration);
1185
1160
  } else if (!options.skipBlocking) {
1186
- blockTransitions(node, false);
1161
+ helpers.blockTransitions(node, false);
1187
1162
  }
1188
1163
 
1189
1164
  // TODO(matsko): for 1.5 change this code to have an animator object for better debugging
@@ -1227,13 +1202,16 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1227
1202
  animationClosed = true;
1228
1203
  animationPaused = false;
1229
1204
 
1230
- if (!options.$$skipPreparationClasses) {
1205
+ if (preparationClasses && !options.$$skipPreparationClasses) {
1231
1206
  $$jqLite.removeClass(element, preparationClasses);
1232
1207
  }
1233
- $$jqLite.removeClass(element, activeClasses);
1208
+
1209
+ if (activeClasses) {
1210
+ $$jqLite.removeClass(element, activeClasses);
1211
+ }
1234
1212
 
1235
1213
  blockKeyframeAnimations(node, false);
1236
- blockTransitions(node, false);
1214
+ helpers.blockTransitions(node, false);
1237
1215
 
1238
1216
  forEach(temporaryStyles, function(entry) {
1239
1217
  // There is only one way to remove inline style properties entirely from elements.
@@ -1284,7 +1262,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1284
1262
 
1285
1263
  function applyBlocking(duration) {
1286
1264
  if (flags.blockTransition) {
1287
- blockTransitions(node, duration);
1265
+ helpers.blockTransitions(node, duration);
1288
1266
  }
1289
1267
 
1290
1268
  if (flags.blockKeyframeAnimation) {
@@ -1414,9 +1392,9 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
1414
1392
 
1415
1393
  if (flags.recalculateTimingStyles) {
1416
1394
  fullClassName = node.getAttribute('class') + ' ' + preparationClasses;
1417
- cacheKey = gcsHashFn(node, fullClassName);
1395
+ cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
1418
1396
 
1419
- timings = computeTimings(node, fullClassName, cacheKey);
1397
+ timings = computeTimings(node, fullClassName, cacheKey, false);
1420
1398
  relativeDelay = timings.maxDelay;
1421
1399
  maxDelay = Math.max(relativeDelay, 0);
1422
1400
  maxDuration = timings.maxDuration;
@@ -2153,6 +2131,15 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2153
2131
  join: []
2154
2132
  };
2155
2133
 
2134
+ function getEventData(options) {
2135
+ return {
2136
+ addClass: options.addClass,
2137
+ removeClass: options.removeClass,
2138
+ from: options.from,
2139
+ to: options.to
2140
+ };
2141
+ }
2142
+
2156
2143
  function makeTruthyCssClassMap(classString) {
2157
2144
  if (!classString) {
2158
2145
  return null;
@@ -2251,6 +2238,10 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2251
2238
  var disabledElementsLookup = new $$Map();
2252
2239
  var animationsEnabled = null;
2253
2240
 
2241
+ function removeFromDisabledElementsLookup(evt) {
2242
+ disabledElementsLookup.delete(evt.target);
2243
+ }
2244
+
2254
2245
  function postDigestTaskFactory() {
2255
2246
  var postDigestCalled = false;
2256
2247
  return function(fn) {
@@ -2434,6 +2425,11 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2434
2425
  bool = !disabledElementsLookup.get(node);
2435
2426
  } else {
2436
2427
  // (element, bool) - Element setter
2428
+ if (!disabledElementsLookup.has(node)) {
2429
+ // The element is added to the map for the first time.
2430
+ // Create a listener to remove it on `$destroy` (to avoid memory leak).
2431
+ jqLite(element).on('$destroy', removeFromDisabledElementsLookup);
2432
+ }
2437
2433
  disabledElementsLookup.set(node, !bool);
2438
2434
  }
2439
2435
  }
@@ -2519,9 +2515,9 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2519
2515
 
2520
2516
  if (skipAnimations) {
2521
2517
  // Callbacks should fire even if the document is hidden (regression fix for issue #14120)
2522
- if (documentHidden) notifyProgress(runner, event, 'start');
2518
+ if (documentHidden) notifyProgress(runner, event, 'start', getEventData(options));
2523
2519
  close();
2524
- if (documentHidden) notifyProgress(runner, event, 'close');
2520
+ if (documentHidden) notifyProgress(runner, event, 'close', getEventData(options));
2525
2521
  return runner;
2526
2522
  }
2527
2523
 
@@ -2578,7 +2574,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2578
2574
  if (existingAnimation.state === RUNNING_STATE) {
2579
2575
  normalizeAnimationDetails(element, newAnimation);
2580
2576
  } else {
2581
- applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
2577
+ applyGeneratedPreparationClasses($$jqLite, element, isStructural ? event : null, options);
2582
2578
 
2583
2579
  event = newAnimation.event = existingAnimation.event;
2584
2580
  options = mergeAnimationDetails(element, existingAnimation, newAnimation);
@@ -2683,7 +2679,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2683
2679
  // this will update the runner's flow-control events based on
2684
2680
  // the `realRunner` object.
2685
2681
  runner.setHost(realRunner);
2686
- notifyProgress(runner, event, 'start', {});
2682
+ notifyProgress(runner, event, 'start', getEventData(options));
2687
2683
 
2688
2684
  realRunner.done(function(status) {
2689
2685
  close(!status);
@@ -2691,7 +2687,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2691
2687
  if (animationDetails && animationDetails.counter === counter) {
2692
2688
  clearElementAnimationState(node);
2693
2689
  }
2694
- notifyProgress(runner, event, 'close', {});
2690
+ notifyProgress(runner, event, 'close', getEventData(options));
2695
2691
  });
2696
2692
  });
2697
2693
 
@@ -2774,7 +2770,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2774
2770
 
2775
2771
  while (parentNode) {
2776
2772
  if (!rootNodeDetected) {
2777
- // angular doesn't want to attempt to animate elements outside of the application
2773
+ // AngularJS doesn't want to attempt to animate elements outside of the application
2778
2774
  // therefore we need to ensure that the rootElement is an ancestor of the current element
2779
2775
  rootNodeDetected = (parentNode === rootNode);
2780
2776
  }
@@ -2857,6 +2853,62 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
2857
2853
  }];
2858
2854
  }];
2859
2855
 
2856
+ /** @this */
2857
+ var $$AnimateCacheProvider = function() {
2858
+
2859
+ var KEY = '$$ngAnimateParentKey';
2860
+ var parentCounter = 0;
2861
+ var cache = Object.create(null);
2862
+
2863
+ this.$get = [function() {
2864
+ return {
2865
+ cacheKey: function(node, method, addClass, removeClass) {
2866
+ var parentNode = node.parentNode;
2867
+ var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
2868
+ var parts = [parentID, method, node.getAttribute('class')];
2869
+ if (addClass) {
2870
+ parts.push(addClass);
2871
+ }
2872
+ if (removeClass) {
2873
+ parts.push(removeClass);
2874
+ }
2875
+ return parts.join(' ');
2876
+ },
2877
+
2878
+ containsCachedAnimationWithoutDuration: function(key) {
2879
+ var entry = cache[key];
2880
+
2881
+ // nothing cached, so go ahead and animate
2882
+ // otherwise it should be a valid animation
2883
+ return (entry && !entry.isValid) || false;
2884
+ },
2885
+
2886
+ flush: function() {
2887
+ cache = Object.create(null);
2888
+ },
2889
+
2890
+ count: function(key) {
2891
+ var entry = cache[key];
2892
+ return entry ? entry.total : 0;
2893
+ },
2894
+
2895
+ get: function(key) {
2896
+ var entry = cache[key];
2897
+ return entry && entry.value;
2898
+ },
2899
+
2900
+ put: function(key, value, isValid) {
2901
+ if (!cache[key]) {
2902
+ cache[key] = { total: 1, value: value, isValid: isValid };
2903
+ } else {
2904
+ cache[key].total++;
2905
+ cache[key].value = value;
2906
+ }
2907
+ }
2908
+ };
2909
+ }];
2910
+ };
2911
+
2860
2912
  /* exported $$AnimationProvider */
2861
2913
 
2862
2914
  var $$AnimationProvider = ['$animateProvider', /** @this */ function($animateProvider) {
@@ -2865,6 +2917,7 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
2865
2917
  var drivers = this.drivers = [];
2866
2918
 
2867
2919
  var RUNNER_STORAGE_KEY = '$$animationRunner';
2920
+ var PREPARE_CLASSES_KEY = '$$animatePrepareClasses';
2868
2921
 
2869
2922
  function setRunner(element, runner) {
2870
2923
  element.data(RUNNER_STORAGE_KEY, runner);
@@ -2878,8 +2931,8 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
2878
2931
  return element.data(RUNNER_STORAGE_KEY);
2879
2932
  }
2880
2933
 
2881
- this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$Map', '$$rAFScheduler',
2882
- function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$Map, $$rAFScheduler) {
2934
+ this.$get = ['$$jqLite', '$rootScope', '$injector', '$$AnimateRunner', '$$Map', '$$rAFScheduler', '$$animateCache',
2935
+ function($$jqLite, $rootScope, $injector, $$AnimateRunner, $$Map, $$rAFScheduler, $$animateCache) {
2883
2936
 
2884
2937
  var animationQueue = [];
2885
2938
  var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
@@ -2894,6 +2947,7 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
2894
2947
  var animation = animations[i];
2895
2948
  lookup.set(animation.domNode, animations[i] = {
2896
2949
  domNode: animation.domNode,
2950
+ element: animation.element,
2897
2951
  fn: animation.fn,
2898
2952
  children: []
2899
2953
  });
@@ -2950,7 +3004,7 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
2950
3004
  result.push(row);
2951
3005
  row = [];
2952
3006
  }
2953
- row.push(entry.fn);
3007
+ row.push(entry);
2954
3008
  entry.children.forEach(function(childEntry) {
2955
3009
  nextLevelEntries++;
2956
3010
  queue.push(childEntry);
@@ -2985,8 +3039,6 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
2985
3039
  return runner;
2986
3040
  }
2987
3041
 
2988
- setRunner(element, runner);
2989
-
2990
3042
  var classes = mergeClasses(element.attr('class'), mergeClasses(options.addClass, options.removeClass));
2991
3043
  var tempClasses = options.tempClasses;
2992
3044
  if (tempClasses) {
@@ -2994,12 +3046,12 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
2994
3046
  options.tempClasses = null;
2995
3047
  }
2996
3048
 
2997
- var prepareClassName;
2998
3049
  if (isStructural) {
2999
- prepareClassName = 'ng-' + event + PREPARE_CLASS_SUFFIX;
3000
- $$jqLite.addClass(element, prepareClassName);
3050
+ element.data(PREPARE_CLASSES_KEY, 'ng-' + event + PREPARE_CLASS_SUFFIX);
3001
3051
  }
3002
3052
 
3053
+ setRunner(element, runner);
3054
+
3003
3055
  animationQueue.push({
3004
3056
  // this data is used by the postDigest code and passed into
3005
3057
  // the driver step function
@@ -3039,16 +3091,31 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
3039
3091
  var toBeSortedAnimations = [];
3040
3092
 
3041
3093
  forEach(groupedAnimations, function(animationEntry) {
3094
+ var element = animationEntry.from ? animationEntry.from.element : animationEntry.element;
3095
+ var extraClasses = options.addClass;
3096
+
3097
+ extraClasses = (extraClasses ? (extraClasses + ' ') : '') + NG_ANIMATE_CLASSNAME;
3098
+ var cacheKey = $$animateCache.cacheKey(element[0], animationEntry.event, extraClasses, options.removeClass);
3099
+
3042
3100
  toBeSortedAnimations.push({
3043
- domNode: getDomNode(animationEntry.from ? animationEntry.from.element : animationEntry.element),
3101
+ element: element,
3102
+ domNode: getDomNode(element),
3044
3103
  fn: function triggerAnimationStart() {
3104
+ var startAnimationFn, closeFn = animationEntry.close;
3105
+
3106
+ // in the event that we've cached the animation status for this element
3107
+ // and it's in fact an invalid animation (something that has duration = 0)
3108
+ // then we should skip all the heavy work from here on
3109
+ if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
3110
+ closeFn();
3111
+ return;
3112
+ }
3113
+
3045
3114
  // it's important that we apply the `ng-animate` CSS class and the
3046
3115
  // temporary classes before we do any driver invoking since these
3047
3116
  // CSS classes may be required for proper CSS detection.
3048
3117
  animationEntry.beforeStart();
3049
3118
 
3050
- var startAnimationFn, closeFn = animationEntry.close;
3051
-
3052
3119
  // in the event that the element was removed before the digest runs or
3053
3120
  // during the RAF sequencing then we should not trigger the animation.
3054
3121
  var targetElement = animationEntry.anchors
@@ -3078,7 +3145,32 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
3078
3145
  // we need to sort each of the animations in order of parent to child
3079
3146
  // relationships. This ensures that the child classes are applied at the
3080
3147
  // right time.
3081
- $$rAFScheduler(sortAnimations(toBeSortedAnimations));
3148
+ var finalAnimations = sortAnimations(toBeSortedAnimations);
3149
+ for (var i = 0; i < finalAnimations.length; i++) {
3150
+ var innerArray = finalAnimations[i];
3151
+ for (var j = 0; j < innerArray.length; j++) {
3152
+ var entry = innerArray[j];
3153
+ var element = entry.element;
3154
+
3155
+ // the RAFScheduler code only uses functions
3156
+ finalAnimations[i][j] = entry.fn;
3157
+
3158
+ // the first row of elements shouldn't have a prepare-class added to them
3159
+ // since the elements are at the top of the animation hierarchy and they
3160
+ // will be applied without a RAF having to pass...
3161
+ if (i === 0) {
3162
+ element.removeData(PREPARE_CLASSES_KEY);
3163
+ continue;
3164
+ }
3165
+
3166
+ var prepareClassName = element.data(PREPARE_CLASSES_KEY);
3167
+ if (prepareClassName) {
3168
+ $$jqLite.addClass(element, prepareClassName);
3169
+ }
3170
+ }
3171
+ }
3172
+
3173
+ $$rAFScheduler(finalAnimations);
3082
3174
  });
3083
3175
 
3084
3176
  return runner;
@@ -3216,10 +3308,10 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
3216
3308
  }
3217
3309
 
3218
3310
  function beforeStart() {
3219
- element.addClass(NG_ANIMATE_CLASSNAME);
3220
- if (tempClasses) {
3221
- $$jqLite.addClass(element, tempClasses);
3222
- }
3311
+ tempClasses = (tempClasses ? (tempClasses + ' ') : '') + NG_ANIMATE_CLASSNAME;
3312
+ $$jqLite.addClass(element, tempClasses);
3313
+
3314
+ var prepareClassName = element.data(PREPARE_CLASSES_KEY);
3223
3315
  if (prepareClassName) {
3224
3316
  $$jqLite.removeClass(element, prepareClassName);
3225
3317
  prepareClassName = null;
@@ -3259,7 +3351,6 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
3259
3351
  $$jqLite.removeClass(element, tempClasses);
3260
3352
  }
3261
3353
 
3262
- element.removeClass(NG_ANIMATE_CLASSNAME);
3263
3354
  runner.complete(!rejected);
3264
3355
  }
3265
3356
  };
@@ -3353,12 +3444,13 @@ var $$AnimationProvider = ['$animateProvider', /** @this */ function($animatePro
3353
3444
  * </file>
3354
3445
  * </example>
3355
3446
  */
3356
- var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $rootScope) {
3447
+ var ngAnimateSwapDirective = ['$animate', function($animate) {
3357
3448
  return {
3358
3449
  restrict: 'A',
3359
3450
  transclude: 'element',
3360
3451
  terminal: true,
3361
- priority: 600, // we use 600 here to ensure that the directive is caught before others
3452
+ priority: 550, // We use 550 here to ensure that the directive is caught before others,
3453
+ // but after `ngIf` (at priority 600).
3362
3454
  link: function(scope, $element, attrs, ctrl, $transclude) {
3363
3455
  var previousElement, previousScope;
3364
3456
  scope.$watchCollection(attrs.ngAnimateSwap || attrs['for'], function(value) {
@@ -3370,10 +3462,10 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
3370
3462
  previousScope = null;
3371
3463
  }
3372
3464
  if (value || value === 0) {
3373
- previousScope = scope.$new();
3374
- $transclude(previousScope, function(element) {
3375
- previousElement = element;
3376
- $animate.enter(element, null, $element);
3465
+ $transclude(function(clone, childScope) {
3466
+ previousElement = clone;
3467
+ previousScope = childScope;
3468
+ $animate.enter(clone, null, $element);
3377
3469
  });
3378
3470
  }
3379
3471
  });
@@ -3387,7 +3479,7 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
3387
3479
  * @description
3388
3480
  *
3389
3481
  * The `ngAnimate` module provides support for CSS-based animations (keyframes and transitions) as well as JavaScript-based animations via
3390
- * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an Angular app.
3482
+ * callback hooks. Animations are not enabled by default, however, by including `ngAnimate` the animation hooks are enabled for an AngularJS app.
3391
3483
  *
3392
3484
  * ## Usage
3393
3485
  * Simply put, there are two ways to make use of animations when ngAnimate is used: by using **CSS** and **JavaScript**. The former works purely based
@@ -3398,25 +3490,33 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
3398
3490
  * ## Directive Support
3399
3491
  * The following directives are "animation aware":
3400
3492
  *
3401
- * | Directive | Supported Animations |
3402
- * |----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
3403
- * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move |
3404
- * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
3405
- * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
3406
- * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
3407
- * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
3408
- * | {@link ng.directive:ngClass#animations ngClass} | add and remove (the CSS class(es) present) |
3409
- * | {@link ng.directive:ngShow#animations ngShow} & {@link ng.directive:ngHide#animations ngHide} | add and remove (the ng-hide class value) |
3410
- * | {@link ng.directive:form#animations form} & {@link ng.directive:ngModel#animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
3411
- * | {@link module:ngMessages#animations ngMessages} | add and remove (ng-active & ng-inactive) |
3412
- * | {@link module:ngMessages#animations ngMessage} | enter and leave |
3413
- *
3414
- * (More information can be found by visiting each the documentation associated with each directive.)
3493
+ * | Directive | Supported Animations |
3494
+ * |-------------------------------------------------------------------------------|---------------------------------------------------------------------------|
3495
+ * | {@link ng.directive:form#animations form / ngForm} | add and remove ({@link ng.directive:form#css-classes various classes}) |
3496
+ * | {@link ngAnimate.directive:ngAnimateSwap#animations ngAnimateSwap} | enter and leave |
3497
+ * | {@link ng.directive:ngClass#animations ngClass / {{class&#125;&#8203;&#125;} | add and remove |
3498
+ * | {@link ng.directive:ngClassEven#animations ngClassEven} | add and remove |
3499
+ * | {@link ng.directive:ngClassOdd#animations ngClassOdd} | add and remove |
3500
+ * | {@link ng.directive:ngHide#animations ngHide} | add and remove (the `ng-hide` class) |
3501
+ * | {@link ng.directive:ngIf#animations ngIf} | enter and leave |
3502
+ * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave |
3503
+ * | {@link module:ngMessages#animations ngMessage / ngMessageExp} | enter and leave |
3504
+ * | {@link module:ngMessages#animations ngMessages} | add and remove (the `ng-active`/`ng-inactive` classes) |
3505
+ * | {@link ng.directive:ngModel#animations ngModel} | add and remove ({@link ng.directive:ngModel#css-classes various classes}) |
3506
+ * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave, and move |
3507
+ * | {@link ng.directive:ngShow#animations ngShow} | add and remove (the `ng-hide` class) |
3508
+ * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave |
3509
+ * | {@link ngRoute.directive:ngView#animations ngView} | enter and leave |
3510
+ *
3511
+ * (More information can be found by visiting the documentation associated with each directive.)
3512
+ *
3513
+ * For a full breakdown of the steps involved during each animation event, refer to the
3514
+ * {@link ng.$animate `$animate` API docs}.
3415
3515
  *
3416
3516
  * ## CSS-based Animations
3417
3517
  *
3418
3518
  * 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
3419
- * and CSS code we can create an animation that will be picked up by Angular when an underlying directive performs an operation.
3519
+ * and CSS code we can create an animation that will be picked up by AngularJS when an underlying directive performs an operation.
3420
3520
  *
3421
3521
  * The example below shows how an `enter` animation can be made possible on an element using `ng-if`:
3422
3522
  *
@@ -3648,9 +3748,22 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
3648
3748
  * .message.ng-enter-prepare {
3649
3749
  * opacity: 0;
3650
3750
  * }
3651
- *
3652
3751
  * ```
3653
3752
  *
3753
+ * ### Animating between value changes
3754
+ *
3755
+ * Sometimes you need to animate between different expression states, whose values
3756
+ * don't necessary need to be known or referenced in CSS styles.
3757
+ * Unless possible with another {@link ngAnimate#directive-support "animation aware" directive},
3758
+ * that specific use case can always be covered with {@link ngAnimate.directive:ngAnimateSwap} as
3759
+ * can be seen in {@link ngAnimate.directive:ngAnimateSwap#examples this example}.
3760
+ *
3761
+ * Note that {@link ngAnimate.directive:ngAnimateSwap} is a *structural directive*, which means it
3762
+ * creates a new instance of the element (including any other/child directives it may have) and
3763
+ * links it to a new scope every time *swap* happens. In some cases this might not be desirable
3764
+ * (e.g. for performance reasons, or when you wish to retain internal state on the original
3765
+ * element instance).
3766
+ *
3654
3767
  * ## JavaScript-based Animations
3655
3768
  *
3656
3769
  * ngAnimate also allows for animations to be consumed by JavaScript code. The approach is similar to CSS-based animations (where there is a shared
@@ -3675,7 +3788,7 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
3675
3788
  * enter: function(element, doneFn) {
3676
3789
  * jQuery(element).fadeIn(1000, doneFn);
3677
3790
  *
3678
- * // remember to call doneFn so that angular
3791
+ * // remember to call doneFn so that AngularJS
3679
3792
  * // knows that the animation has concluded
3680
3793
  * },
3681
3794
  *
@@ -3723,7 +3836,7 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
3723
3836
  *
3724
3837
  * ## CSS + JS Animations Together
3725
3838
  *
3726
- * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of Angular,
3839
+ * AngularJS 1.4 and higher has taken steps to make the amalgamation of CSS and JS animations more flexible. However, unlike earlier versions of AngularJS,
3727
3840
  * defining CSS and JS animations to work off of the same CSS class will not work anymore. Therefore the example below will only result in **JS animations taking
3728
3841
  * charge of the animation**:
3729
3842
  *
@@ -4039,7 +4152,7 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
4039
4152
  *
4040
4153
  * ## Using $animate in your directive code
4041
4154
  *
4042
- * So far we've explored how to feed in animations into an Angular application, but how do we trigger animations within our own directives in our application?
4155
+ * So far we've explored how to feed in animations into an AngularJS application, but how do we trigger animations within our own directives in our application?
4043
4156
  * By injecting the `$animate` service into our directive code, we can trigger structural and class-based hooks which can then be consumed by animations. Let's
4044
4157
  * imagine we have a greeting box that shows and hides itself when the data changes
4045
4158
  *
@@ -4082,7 +4195,7 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
4082
4195
  * });
4083
4196
  * ```
4084
4197
  *
4085
- * (Note that earlier versions of Angular prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
4198
+ * (Note that earlier versions of AngularJS prior to v1.4 required the promise code to be wrapped using `$scope.$apply(...)`. This is not the case
4086
4199
  * anymore.)
4087
4200
  *
4088
4201
  * In addition to the animation promise, we can also make use of animation-related callbacks within our directives and controller code by registering
@@ -4097,7 +4210,7 @@ var ngAnimateSwapDirective = ['$animate', '$rootScope', function($animate, $root
4097
4210
  * }])
4098
4211
  * ```
4099
4212
  *
4100
- * (Note that you will need to trigger a digest within the callback to get angular to notice any scope-related changes.)
4213
+ * (Note that you will need to trigger a digest within the callback to get AngularJS to notice any scope-related changes.)
4101
4214
  */
4102
4215
 
4103
4216
  var copy;
@@ -4124,7 +4237,7 @@ var noop;
4124
4237
  * Click here {@link ng.$animate to learn more about animations with `$animate`}.
4125
4238
  */
4126
4239
  angular.module('ngAnimate', [], function initAngularHelpers() {
4127
- // Access helpers from angular core.
4240
+ // Access helpers from AngularJS core.
4128
4241
  // Do it inside a `config` block to ensure `window.angular` is available.
4129
4242
  noop = angular.noop;
4130
4243
  copy = angular.copy;
@@ -4139,13 +4252,14 @@ angular.module('ngAnimate', [], function initAngularHelpers() {
4139
4252
  isFunction = angular.isFunction;
4140
4253
  isElement = angular.isElement;
4141
4254
  })
4142
- .info({ angularVersion: '1.6.8' })
4255
+ .info({ angularVersion: '1.8.0' })
4143
4256
  .directive('ngAnimateSwap', ngAnimateSwapDirective)
4144
4257
 
4145
4258
  .directive('ngAnimateChildren', $$AnimateChildrenDirective)
4146
4259
  .factory('$$rAFScheduler', $$rAFSchedulerFactory)
4147
4260
 
4148
4261
  .provider('$$animateQueue', $$AnimateQueueProvider)
4262
+ .provider('$$animateCache', $$AnimateCacheProvider)
4149
4263
  .provider('$$animation', $$AnimationProvider)
4150
4264
 
4151
4265
  .provider('$animateCss', $AnimateCssProvider)