angularjs-rails 1.2.3 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.3
2
+ * @license AngularJS v1.2.4
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.2.3
2
+ * @license AngularJS v1.2.4
3
3
  * (c) 2010-2014 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -68,7 +68,7 @@ function minErr(module) {
68
68
  return match;
69
69
  });
70
70
 
71
- message = message + '\nhttp://errors.angularjs.org/1.2.3/' +
71
+ message = message + '\nhttp://errors.angularjs.org/1.2.4/' +
72
72
  (module ? module + '/' : '') + code;
73
73
  for (i = 2; i < arguments.length; i++) {
74
74
  message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
@@ -644,9 +644,9 @@ var trim = (function() {
644
644
  * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
645
645
  */
646
646
  function isElement(node) {
647
- return node &&
647
+ return !!(node &&
648
648
  (node.nodeName // we are a direct element
649
- || (node.on && node.find)); // we have an on and find method part of jQuery API
649
+ || (node.on && node.find))); // we have an on and find method part of jQuery API
650
650
  }
651
651
 
652
652
  /**
@@ -847,7 +847,7 @@ function shallowCopy(src, dst) {
847
847
 
848
848
  for(var key in src) {
849
849
  // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
850
- // so we don't need to worry hasOwnProperty here
850
+ // so we don't need to worry about using our custom hasOwnProperty here
851
851
  if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
852
852
  dst[key] = src[key];
853
853
  }
@@ -1409,23 +1409,25 @@ function getter(obj, path, bindFnToScope) {
1409
1409
  }
1410
1410
 
1411
1411
  /**
1412
- * Return the siblings between `startNode` and `endNode`, inclusive
1413
- * @param {Object} object with `startNode` and `endNode` properties
1412
+ * Return the DOM siblings between the first and last node in the given array.
1413
+ * @param {Array} array like object
1414
1414
  * @returns jQlite object containing the elements
1415
1415
  */
1416
- function getBlockElements(block) {
1417
- if (block.startNode === block.endNode) {
1418
- return jqLite(block.startNode);
1416
+ function getBlockElements(nodes) {
1417
+ var startNode = nodes[0],
1418
+ endNode = nodes[nodes.length - 1];
1419
+ if (startNode === endNode) {
1420
+ return jqLite(startNode);
1419
1421
  }
1420
1422
 
1421
- var element = block.startNode;
1423
+ var element = startNode;
1422
1424
  var elements = [element];
1423
1425
 
1424
1426
  do {
1425
1427
  element = element.nextSibling;
1426
1428
  if (!element) break;
1427
1429
  elements.push(element);
1428
- } while (element !== block.endNode);
1430
+ } while (element !== endNode);
1429
1431
 
1430
1432
  return jqLite(elements);
1431
1433
  }
@@ -1826,11 +1828,11 @@ function setupModuleLoader(window) {
1826
1828
  * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
1827
1829
  */
1828
1830
  var version = {
1829
- full: '1.2.3', // all of these placeholder strings will be replaced by grunt's
1831
+ full: '1.2.4', // all of these placeholder strings will be replaced by grunt's
1830
1832
  major: 1, // package task
1831
1833
  minor: 2,
1832
- dot: 3,
1833
- codeName: 'unicorn-zapper'
1834
+ dot: 4,
1835
+ codeName: 'wormhole-baster'
1834
1836
  };
1835
1837
 
1836
1838
 
@@ -2771,7 +2773,11 @@ forEach({
2771
2773
  },
2772
2774
 
2773
2775
  find: function(element, selector) {
2774
- return element.getElementsByTagName(selector);
2776
+ if (element.getElementsByTagName) {
2777
+ return element.getElementsByTagName(selector);
2778
+ } else {
2779
+ return [];
2780
+ }
2775
2781
  },
2776
2782
 
2777
2783
  clone: jqLiteClone,
@@ -3101,7 +3107,7 @@ function annotate(fn) {
3101
3107
  * // ...
3102
3108
  * }
3103
3109
  * // Define function dependencies
3104
- * MyController.$inject = ['$scope', '$route'];
3110
+ * MyController['$inject'] = ['$scope', '$route'];
3105
3111
  *
3106
3112
  * // Then
3107
3113
  * expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
@@ -4803,7 +4809,7 @@ function $TemplateCacheProvider() {
4803
4809
  * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
4804
4810
  * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
4805
4811
  * * `^` - Locate the required controller by searching the element's parents. Throw an error if not found.
4806
- * * `?^` - Attempt to locate the required controller by searching the element's parentsor pass `null` to the
4812
+ * * `?^` - Attempt to locate the required controller by searching the element's parents or pass `null` to the
4807
4813
  * `link` fn if not found.
4808
4814
  *
4809
4815
  *
@@ -5542,7 +5548,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
5542
5548
  createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
5543
5549
  );
5544
5550
  } else {
5545
- nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
5551
+ nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
5546
5552
  }
5547
5553
  } else if (childLinkFn) {
5548
5554
  childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
@@ -6049,13 +6055,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
6049
6055
  // we are out of sync and need to copy
6050
6056
  if (parentValue !== lastValue) {
6051
6057
  // parent changed and it has precedence
6052
- lastValue = isolateScope[scopeName] = parentValue;
6058
+ isolateScope[scopeName] = parentValue;
6053
6059
  } else {
6054
6060
  // if the parent can be assigned then do so
6055
- parentSet(scope, parentValue = lastValue = isolateScope[scopeName]);
6061
+ parentSet(scope, parentValue = isolateScope[scopeName]);
6056
6062
  }
6057
6063
  }
6058
- return parentValue;
6064
+ return lastValue = parentValue;
6059
6065
  });
6060
6066
  break;
6061
6067
 
@@ -8048,8 +8054,8 @@ function $InterpolateProvider() {
8048
8054
  *
8049
8055
  <pre>
8050
8056
  var $interpolate = ...; // injected
8051
- var exp = $interpolate('Hello {{name}}!');
8052
- expect(exp({name:'Angular'}).toEqual('Hello Angular!');
8057
+ var exp = $interpolate('Hello {{name | uppercase}}!');
8058
+ expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
8053
8059
  </pre>
8054
8060
  *
8055
8061
  *
@@ -9247,23 +9253,24 @@ function ensureSafeMemberName(name, fullExpression) {
9247
9253
 
9248
9254
  function ensureSafeObject(obj, fullExpression) {
9249
9255
  // nifty check if obj is Function that is fast and works across iframes and other contexts
9250
- if (obj && obj.constructor === obj) {
9251
- throw $parseMinErr('isecfn',
9252
- 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
9253
- fullExpression);
9254
- } else if (// isWindow(obj)
9255
- obj && obj.document && obj.location && obj.alert && obj.setInterval) {
9256
- throw $parseMinErr('isecwindow',
9257
- 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
9258
- fullExpression);
9259
- } else if (// isElement(obj)
9260
- obj && (obj.nodeName || (obj.on && obj.find))) {
9261
- throw $parseMinErr('isecdom',
9262
- 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
9263
- fullExpression);
9264
- } else {
9265
- return obj;
9256
+ if (obj) {
9257
+ if (obj.constructor === obj) {
9258
+ throw $parseMinErr('isecfn',
9259
+ 'Referencing Function in Angular expressions is disallowed! Expression: {0}',
9260
+ fullExpression);
9261
+ } else if (// isWindow(obj)
9262
+ obj.document && obj.location && obj.alert && obj.setInterval) {
9263
+ throw $parseMinErr('isecwindow',
9264
+ 'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
9265
+ fullExpression);
9266
+ } else if (// isElement(obj)
9267
+ obj.children && (obj.nodeName || (obj.on && obj.find))) {
9268
+ throw $parseMinErr('isecdom',
9269
+ 'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
9270
+ fullExpression);
9271
+ }
9266
9272
  }
9273
+ return obj;
9267
9274
  }
9268
9275
 
9269
9276
  var OPERATORS = {
@@ -11021,6 +11028,7 @@ function qFactory(nextTick, exceptionHandler) {
11021
11028
  function $RootScopeProvider(){
11022
11029
  var TTL = 10;
11023
11030
  var $rootScopeMinErr = minErr('$rootScope');
11031
+ var lastDirtyWatch = null;
11024
11032
 
11025
11033
  this.digestTtl = function(value) {
11026
11034
  if (arguments.length) {
@@ -11122,7 +11130,7 @@ function $RootScopeProvider(){
11122
11130
  *
11123
11131
  */
11124
11132
  $new: function(isolate) {
11125
- var Child,
11133
+ var ChildScope,
11126
11134
  child;
11127
11135
 
11128
11136
  if (isolate) {
@@ -11132,11 +11140,11 @@ function $RootScopeProvider(){
11132
11140
  child.$$asyncQueue = this.$$asyncQueue;
11133
11141
  child.$$postDigestQueue = this.$$postDigestQueue;
11134
11142
  } else {
11135
- Child = function() {}; // should be anonymous; This is so that when the minifier munges
11143
+ ChildScope = function() {}; // should be anonymous; This is so that when the minifier munges
11136
11144
  // the name it does not become random set of chars. This will then show up as class
11137
11145
  // name in the debugger.
11138
- Child.prototype = this;
11139
- child = new Child();
11146
+ ChildScope.prototype = this;
11147
+ child = new ChildScope();
11140
11148
  child.$id = nextUid();
11141
11149
  }
11142
11150
  child['this'] = child;
@@ -11216,7 +11224,7 @@ function $RootScopeProvider(){
11216
11224
 
11217
11225
 
11218
11226
 
11219
- // Using a listener function
11227
+ // Using a listener function
11220
11228
  var food;
11221
11229
  scope.foodCounter = 0;
11222
11230
  expect(scope.foodCounter).toEqual(0);
@@ -11241,7 +11249,7 @@ function $RootScopeProvider(){
11241
11249
  // Update food and run digest. Now the counter will increment
11242
11250
  food = 'cheeseburger';
11243
11251
  scope.$digest();
11244
- expect(scope.foodCounter).toEqual(1);
11252
+ expect(scope.foodCounter).toEqual(1);
11245
11253
 
11246
11254
  * </pre>
11247
11255
  *
@@ -11275,6 +11283,8 @@ function $RootScopeProvider(){
11275
11283
  eq: !!objectEquality
11276
11284
  };
11277
11285
 
11286
+ lastDirtyWatch = null;
11287
+
11278
11288
  // in the case user pass string, we need to compile it, do we really need this ?
11279
11289
  if (!isFunction(listener)) {
11280
11290
  var listenFn = compileToFn(listener || noop, 'listener');
@@ -11503,6 +11513,8 @@ function $RootScopeProvider(){
11503
11513
 
11504
11514
  beginPhase('$digest');
11505
11515
 
11516
+ lastDirtyWatch = null;
11517
+
11506
11518
  do { // "while dirty" loop
11507
11519
  dirty = false;
11508
11520
  current = target;
@@ -11512,10 +11524,13 @@ function $RootScopeProvider(){
11512
11524
  asyncTask = asyncQueue.shift();
11513
11525
  asyncTask.scope.$eval(asyncTask.expression);
11514
11526
  } catch (e) {
11527
+ clearPhase();
11515
11528
  $exceptionHandler(e);
11516
11529
  }
11530
+ lastDirtyWatch = null;
11517
11531
  }
11518
11532
 
11533
+ traverseScopesLoop:
11519
11534
  do { // "traverse the scopes" loop
11520
11535
  if ((watchers = current.$$watchers)) {
11521
11536
  // process our watches
@@ -11525,25 +11540,34 @@ function $RootScopeProvider(){
11525
11540
  watch = watchers[length];
11526
11541
  // Most common watches are on primitives, in which case we can short
11527
11542
  // circuit it with === operator, only when === fails do we use .equals
11528
- if (watch && (value = watch.get(current)) !== (last = watch.last) &&
11529
- !(watch.eq
11530
- ? equals(value, last)
11531
- : (typeof value == 'number' && typeof last == 'number'
11532
- && isNaN(value) && isNaN(last)))) {
11533
- dirty = true;
11534
- watch.last = watch.eq ? copy(value) : value;
11535
- watch.fn(value, ((last === initWatchVal) ? value : last), current);
11536
- if (ttl < 5) {
11537
- logIdx = 4 - ttl;
11538
- if (!watchLog[logIdx]) watchLog[logIdx] = [];
11539
- logMsg = (isFunction(watch.exp))
11540
- ? 'fn: ' + (watch.exp.name || watch.exp.toString())
11541
- : watch.exp;
11542
- logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
11543
- watchLog[logIdx].push(logMsg);
11543
+ if (watch) {
11544
+ if ((value = watch.get(current)) !== (last = watch.last) &&
11545
+ !(watch.eq
11546
+ ? equals(value, last)
11547
+ : (typeof value == 'number' && typeof last == 'number'
11548
+ && isNaN(value) && isNaN(last)))) {
11549
+ dirty = true;
11550
+ lastDirtyWatch = watch;
11551
+ watch.last = watch.eq ? copy(value) : value;
11552
+ watch.fn(value, ((last === initWatchVal) ? value : last), current);
11553
+ if (ttl < 5) {
11554
+ logIdx = 4 - ttl;
11555
+ if (!watchLog[logIdx]) watchLog[logIdx] = [];
11556
+ logMsg = (isFunction(watch.exp))
11557
+ ? 'fn: ' + (watch.exp.name || watch.exp.toString())
11558
+ : watch.exp;
11559
+ logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
11560
+ watchLog[logIdx].push(logMsg);
11561
+ }
11562
+ } else if (watch === lastDirtyWatch) {
11563
+ // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
11564
+ // have already been tested.
11565
+ dirty = false;
11566
+ break traverseScopesLoop;
11544
11567
  }
11545
11568
  }
11546
11569
  } catch (e) {
11570
+ clearPhase();
11547
11571
  $exceptionHandler(e);
11548
11572
  }
11549
11573
  }
@@ -11552,13 +11576,16 @@ function $RootScopeProvider(){
11552
11576
  // Insanity Warning: scope depth-first traversal
11553
11577
  // yes, this code is a bit crazy, but it works and we have tests to prove it!
11554
11578
  // this piece should be kept in sync with the traversal in $broadcast
11555
- if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {
11579
+ if (!(next = (current.$$childHead ||
11580
+ (current !== target && current.$$nextSibling)))) {
11556
11581
  while(current !== target && !(next = current.$$nextSibling)) {
11557
11582
  current = current.$parent;
11558
11583
  }
11559
11584
  }
11560
11585
  } while ((current = next));
11561
11586
 
11587
+ // `break traverseScopesLoop;` takes us to here
11588
+
11562
11589
  if(dirty && !(ttl--)) {
11563
11590
  clearPhase();
11564
11591
  throw $rootScopeMinErr('infdig',
@@ -11566,6 +11593,7 @@ function $RootScopeProvider(){
11566
11593
  'Watchers fired in the last 5 iterations: {1}',
11567
11594
  TTL, toJson(watchLog));
11568
11595
  }
11596
+
11569
11597
  } while (dirty || asyncQueue.length);
11570
11598
 
11571
11599
  clearPhase();
@@ -11618,11 +11646,12 @@ function $RootScopeProvider(){
11618
11646
  */
11619
11647
  $destroy: function() {
11620
11648
  // we can't destroy the root scope or a scope that has been already destroyed
11621
- if ($rootScope == this || this.$$destroyed) return;
11649
+ if (this.$$destroyed) return;
11622
11650
  var parent = this.$parent;
11623
11651
 
11624
11652
  this.$broadcast('$destroy');
11625
11653
  this.$$destroyed = true;
11654
+ if (this === $rootScope) return;
11626
11655
 
11627
11656
  if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
11628
11657
  if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
@@ -11660,7 +11689,7 @@ function $RootScopeProvider(){
11660
11689
  *
11661
11690
  * - `string`: execute using the rules as defined in {@link guide/expression expression}.
11662
11691
  * - `function(scope)`: execute the function with the current `scope` parameter.
11663
- *
11692
+ *
11664
11693
  * @param {(object)=} locals Local variables object, useful for overriding values in scope.
11665
11694
  * @returns {*} The result of evaluating the expression.
11666
11695
  */
@@ -13528,13 +13557,15 @@ function urlIsSameOrigin(requestUrl) {
13528
13557
  <doc:source>
13529
13558
  <script>
13530
13559
  function Ctrl($scope, $window) {
13531
- $scope.$window = $window;
13532
13560
  $scope.greeting = 'Hello, World!';
13561
+ $scope.doGreeting = function(greeting) {
13562
+ $window.alert(greeting);
13563
+ };
13533
13564
  }
13534
13565
  </script>
13535
13566
  <div ng-controller="Ctrl">
13536
13567
  <input type="text" ng-model="greeting" />
13537
- <button ng-click="$window.alert(greeting)">ALERT</button>
13568
+ <button ng-click="doGreeting(greeting)">ALERT</button>
13538
13569
  </div>
13539
13570
  </doc:source>
13540
13571
  <doc:scenario>
@@ -15041,9 +15072,22 @@ var nullFormCtrl = {
15041
15072
  * @property {Object} $error Is an object hash, containing references to all invalid controls or
15042
15073
  * forms, where:
15043
15074
  *
15044
- * - keys are validation tokens (error names) — such as `required`, `url` or `email`,
15045
- * - values are arrays of controls or forms that are invalid with given error.
15075
+ * - keys are validation tokens (error names),
15076
+ * - values are arrays of controls or forms that are invalid for given error name.
15046
15077
  *
15078
+ *
15079
+ * Built-in validation tokens:
15080
+ *
15081
+ * - `email`
15082
+ * - `max`
15083
+ * - `maxlength`
15084
+ * - `min`
15085
+ * - `minlength`
15086
+ * - `number`
15087
+ * - `pattern`
15088
+ * - `required`
15089
+ * - `url`
15090
+ *
15047
15091
  * @description
15048
15092
  * `FormController` keeps track of all its controls and nested forms as well as state of them,
15049
15093
  * such as being valid/invalid or dirty/pristine.
@@ -16337,39 +16381,6 @@ var VALID_CLASS = 'ng-valid',
16337
16381
  </file>
16338
16382
  * </example>
16339
16383
  *
16340
- * ## Isolated Scope Pitfall
16341
- *
16342
- * Note that if you have a directive with an isolated scope, you cannot require `ngModel`
16343
- * since the model value will be looked up on the isolated scope rather than the outer scope.
16344
- * When the directive updates the model value, calling `ngModel.$setViewValue()` the property
16345
- * on the outer scope will not be updated. However you can get around this by using $parent.
16346
- *
16347
- * Here is an example of this situation. You'll notice that the first div is not updating the input.
16348
- * However the second div can update the input properly.
16349
- *
16350
- * <example module="badIsolatedDirective">
16351
- <file name="script.js">
16352
- angular.module('badIsolatedDirective', []).directive('isolate', function() {
16353
- return {
16354
- require: 'ngModel',
16355
- scope: { },
16356
- template: '<input ng-model="innerModel">',
16357
- link: function(scope, element, attrs, ngModel) {
16358
- scope.$watch('innerModel', function(value) {
16359
- console.log(value);
16360
- ngModel.$setViewValue(value);
16361
- });
16362
- }
16363
- };
16364
- });
16365
- </file>
16366
- <file name="index.html">
16367
- <input ng-model="someModel"/>
16368
- <div isolate ng-model="someModel"></div>
16369
- <div isolate ng-model="$parent.someModel"></div>
16370
- </file>
16371
- * </example>
16372
- *
16373
16384
  *
16374
16385
  */
16375
16386
  var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',
@@ -16516,7 +16527,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
16516
16527
  * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
16517
16528
  * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
16518
16529
  * `$modelValue` and the **expression** specified in the `ng-model` attribute.
16519
- *
16530
+ *
16520
16531
  * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
16521
16532
  *
16522
16533
  * Note that calling this function does not trigger a `$digest`.
@@ -16573,6 +16584,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
16573
16584
  ctrl.$render();
16574
16585
  }
16575
16586
  }
16587
+
16588
+ return value;
16576
16589
  });
16577
16590
  }];
16578
16591
 
@@ -18066,9 +18079,12 @@ var ngIfDirective = ['$animate', function($animate) {
18066
18079
  if (!childScope) {
18067
18080
  childScope = $scope.$new();
18068
18081
  $transclude(childScope, function (clone) {
18082
+ clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
18083
+ // Note: We only need the first/last node of the cloned nodes.
18084
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
18085
+ // by a directive with templateUrl when it's template arrives.
18069
18086
  block = {
18070
- startNode: clone[0],
18071
- endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ')
18087
+ clone: clone
18072
18088
  };
18073
18089
  $animate.enter(clone, $element.parent(), $element);
18074
18090
  });
@@ -18081,7 +18097,7 @@ var ngIfDirective = ['$animate', function($animate) {
18081
18097
  }
18082
18098
 
18083
18099
  if (block) {
18084
- $animate.leave(getBlockElements(block));
18100
+ $animate.leave(getBlockElements(block.clone));
18085
18101
  block = null;
18086
18102
  }
18087
18103
  }
@@ -18324,6 +18340,8 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
18324
18340
  * to initialize values on a scope.
18325
18341
  * </div>
18326
18342
  *
18343
+ * @priority 450
18344
+ *
18327
18345
  * @element ANY
18328
18346
  * @param {expression} ngInit {@link guide/expression Expression} to eval.
18329
18347
  *
@@ -18355,6 +18373,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
18355
18373
  </doc:example>
18356
18374
  */
18357
18375
  var ngInitDirective = ngDirective({
18376
+ priority: 450,
18358
18377
  compile: function() {
18359
18378
  return {
18360
18379
  pre: function(scope, element, attrs) {
@@ -18912,7 +18931,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
18912
18931
  } else if (nextBlockMap.hasOwnProperty(trackById)) {
18913
18932
  // restore lastBlockMap
18914
18933
  forEach(nextBlockOrder, function(block) {
18915
- if (block && block.startNode) lastBlockMap[block.id] = block;
18934
+ if (block && block.scope) lastBlockMap[block.id] = block;
18916
18935
  });
18917
18936
  // This is a duplicate and we need to throw an error
18918
18937
  throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
@@ -18929,7 +18948,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
18929
18948
  // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn
18930
18949
  if (lastBlockMap.hasOwnProperty(key)) {
18931
18950
  block = lastBlockMap[key];
18932
- elementsToRemove = getBlockElements(block);
18951
+ elementsToRemove = getBlockElements(block.clone);
18933
18952
  $animate.leave(elementsToRemove);
18934
18953
  forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
18935
18954
  block.scope.$destroy();
@@ -18941,9 +18960,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
18941
18960
  key = (collection === collectionKeys) ? index : collectionKeys[index];
18942
18961
  value = collection[key];
18943
18962
  block = nextBlockOrder[index];
18944
- if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;
18963
+ if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);
18945
18964
 
18946
- if (block.startNode) {
18965
+ if (block.scope) {
18947
18966
  // if we have already seen this object, then we need to reuse the
18948
18967
  // associated scope/element
18949
18968
  childScope = block.scope;
@@ -18953,11 +18972,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
18953
18972
  nextNode = nextNode.nextSibling;
18954
18973
  } while(nextNode && nextNode[NG_REMOVED]);
18955
18974
 
18956
- if (block.startNode != nextNode) {
18975
+ if (getBlockStart(block) != nextNode) {
18957
18976
  // existing item which got moved
18958
- $animate.move(getBlockElements(block), null, jqLite(previousNode));
18977
+ $animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
18959
18978
  }
18960
- previousNode = block.endNode;
18979
+ previousNode = getBlockEnd(block);
18961
18980
  } else {
18962
18981
  // new item which we don't know about
18963
18982
  childScope = $scope.$new();
@@ -18973,14 +18992,16 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
18973
18992
  childScope.$odd = !(childScope.$even = (index&1) === 0);
18974
18993
  // jshint bitwise: true
18975
18994
 
18976
- if (!block.startNode) {
18995
+ if (!block.scope) {
18977
18996
  $transclude(childScope, function(clone) {
18978
18997
  clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
18979
18998
  $animate.enter(clone, null, jqLite(previousNode));
18980
18999
  previousNode = clone;
18981
19000
  block.scope = childScope;
18982
- block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0];
18983
- block.endNode = clone[clone.length - 1];
19001
+ // Note: We only need the first/last node of the cloned nodes.
19002
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
19003
+ // by a directive with templateUrl when it's template arrives.
19004
+ block.clone = clone;
18984
19005
  nextBlockMap[block.id] = block;
18985
19006
  });
18986
19007
  }
@@ -18989,6 +19010,14 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
18989
19010
  });
18990
19011
  }
18991
19012
  };
19013
+
19014
+ function getBlockStart(block) {
19015
+ return block.clone[0];
19016
+ }
19017
+
19018
+ function getBlockEnd(block) {
19019
+ return block.clone[block.clone.length - 1];
19020
+ }
18992
19021
  }];
18993
19022
 
18994
19023
  /**