@angular-wave/angular.ts 0.6.3 → 0.6.5

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.
Files changed (187) hide show
  1. package/dist/angular-ts.esm.js +2 -2
  2. package/dist/angular-ts.umd.js +2 -2
  3. package/package.json +1 -1
  4. package/src/angular.spec.js +2 -2
  5. package/src/animations/animate-children-directive.js +1 -1
  6. package/src/animations/animate-css-driver.js +2 -2
  7. package/src/animations/animate-css.js +1 -1
  8. package/src/animations/animate-js.js +2 -2
  9. package/src/animations/animate-queue.js +2 -2
  10. package/src/animations/animate.js +2 -2
  11. package/src/animations/animate.spec.js +3 -3
  12. package/src/animations/animation.js +3 -3
  13. package/src/binding.spec.js +1 -1
  14. package/src/core/cache/cache.js +1 -1
  15. package/src/core/compile/attributes.js +24 -7
  16. package/src/core/compile/compile.js +79 -249
  17. package/src/core/compile/compile.md +0 -8
  18. package/src/core/compile/compile.spec.js +38 -640
  19. package/src/core/controller/controller.js +2 -2
  20. package/src/core/di/injector.js +1 -1
  21. package/src/core/di/injector.spec.js +1 -1
  22. package/src/core/di/internal-injector.js +2 -2
  23. package/src/core/di/ng-module.js +1 -1
  24. package/src/core/filter/filter.js +2 -2
  25. package/src/core/interpolate/interpolate.js +1 -1
  26. package/src/core/interval/interval-factory.js +1 -1
  27. package/src/core/interval/interval.js +1 -1
  28. package/src/core/location/location.js +3 -3
  29. package/src/core/on.spec.js +1 -1
  30. package/src/core/parse/interpreter.js +1 -1
  31. package/src/core/prop.spec.js +2 -2
  32. package/src/core/q/q.js +2 -2
  33. package/src/core/root-element.spec.js +1 -1
  34. package/src/core/sanitize/sanitize-uri.js +1 -1
  35. package/src/core/sce/sce.js +3 -3
  36. package/src/core/sce/sce.spec.js +1 -1
  37. package/src/core/scope/scope.js +3 -3
  38. package/src/core/scope/scope.spec.js +1 -1
  39. package/src/core/timeout/timeout.js +2 -2
  40. package/src/core/url-utils/url-utils.js +1 -1
  41. package/src/directive/aria/aria.js +1 -1
  42. package/src/directive/aria/aria.spec.js +1 -1
  43. package/src/directive/attrs/attrs.js +3 -3
  44. package/src/directive/attrs/attrs.spec.js +1 -1
  45. package/src/directive/attrs/boolean.spec.js +1 -1
  46. package/src/directive/attrs/element-style.spec.js +1 -1
  47. package/src/directive/attrs/src.spec.js +1 -1
  48. package/src/directive/bind/bind.js +1 -1
  49. package/src/directive/bind/bind.spec.js +1 -1
  50. package/src/directive/bind/bing-html.spec.js +1 -1
  51. package/src/directive/change/change.spec.js +1 -1
  52. package/src/directive/channel/channel.js +25 -7
  53. package/src/directive/channel/channel.spec.js +17 -0
  54. package/src/directive/class/class.js +1 -1
  55. package/src/directive/class/class.spec.js +2 -2
  56. package/src/directive/cloak/cloak.spec.js +1 -1
  57. package/src/directive/controller/controller.spec.js +2 -2
  58. package/src/directive/events/click.spec.js +1 -1
  59. package/src/directive/events/event.spec.js +1 -1
  60. package/src/directive/events/events.js +3 -3
  61. package/src/directive/form/form.js +2 -2
  62. package/src/directive/form/form.spec.js +1 -1
  63. package/src/directive/if/if.js +2 -3
  64. package/src/directive/if/if.md +0 -1
  65. package/src/directive/if/if.spec.js +2 -2
  66. package/src/directive/include/include.js +3 -3
  67. package/src/directive/include/include.spec.js +2 -2
  68. package/src/directive/init/init.spec.js +1 -1
  69. package/src/directive/input/input.js +1 -1
  70. package/src/directive/input/input.spec.js +1 -1
  71. package/src/directive/messages/messages.js +1 -1
  72. package/src/directive/messages/messages.spec.js +3 -3
  73. package/src/directive/model/model.js +7 -7
  74. package/src/directive/model/model.spec.js +2 -2
  75. package/src/directive/model-options/model-options.js +1 -1
  76. package/src/directive/model-options/model-options.spec.js +2 -2
  77. package/src/directive/non-bindable/non-bindable.spec.js +1 -1
  78. package/src/directive/observe/observe.spec.js +1 -1
  79. package/src/directive/options/options.js +6 -2
  80. package/src/directive/options/options.spec.js +2 -2
  81. package/src/directive/ref/href.spec.js +2 -2
  82. package/src/directive/ref/ref.js +1 -1
  83. package/src/directive/repeat/repeat.js +263 -255
  84. package/src/directive/repeat/repeat.md +0 -22
  85. package/src/directive/repeat/repeat.spec.js +2 -115
  86. package/src/directive/script/script.spec.js +1 -1
  87. package/src/directive/select/select.js +2 -2
  88. package/src/directive/select/select.spec.js +2 -2
  89. package/src/directive/show-hide/show-hide.js +1 -3
  90. package/src/directive/show-hide/show-hide.md +0 -2
  91. package/src/directive/show-hide/show-hide.spec.js +1 -1
  92. package/src/directive/style/style.spec.js +1 -1
  93. package/src/directive/switch/switch.js +2 -4
  94. package/src/directive/switch/switch.spec.js +1 -51
  95. package/src/directive/transclude/transclude.js +2 -2
  96. package/src/directive/validators/validators.js +2 -2
  97. package/src/directive/validators/validators.spec.js +1 -1
  98. package/src/filters/filter.js +1 -1
  99. package/src/filters/filter.spec.js +2 -2
  100. package/src/filters/filters.js +1 -1
  101. package/src/filters/filters.spec.js +1 -1
  102. package/src/filters/limit-to.js +1 -1
  103. package/src/filters/limit-to.spec.js +1 -1
  104. package/src/filters/order-by.js +1 -1
  105. package/src/index.js +3 -9
  106. package/src/loader.js +12 -16
  107. package/src/router/common/coreservices.js +1 -1
  108. package/src/router/common/trace.js +1 -1
  109. package/src/router/directives/state-directives.js +1 -1
  110. package/src/router/directives/state-directives.spec.js +1 -1
  111. package/src/router/directives/view-directive.js +2 -2
  112. package/src/router/directives/view-directive.spec.js +1 -1
  113. package/src/router/hooks/redirect-to.js +1 -1
  114. package/src/router/params/param-type.js +1 -1
  115. package/src/router/params/param-types.js +1 -1
  116. package/src/router/params/param.js +1 -1
  117. package/src/router/resolve/resolvable.js +1 -1
  118. package/src/router/resolve/resolve-context.js +1 -1
  119. package/src/router/state/state-builder.js +1 -1
  120. package/src/router/state/state-matcher.js +1 -1
  121. package/src/router/state/state-object.js +1 -1
  122. package/src/router/state/state-queue-manager.js +1 -1
  123. package/src/router/state/state-registry.js +2 -2
  124. package/src/router/state/state-service.js +1 -1
  125. package/src/router/state/state.spec.js +2 -2
  126. package/src/router/state/target-state.js +1 -1
  127. package/src/router/state/views.js +1 -1
  128. package/src/router/state-provider.js +1 -1
  129. package/src/router/template-factory.js +9 -8
  130. package/src/router/template-factory.spec.js +1 -1
  131. package/src/router/transition/hook-registry.js +1 -1
  132. package/src/router/transition/transition-service.js +1 -1
  133. package/src/router/transition/transition.js +1 -1
  134. package/src/router/url/url-config.js +1 -1
  135. package/src/router/url/url-matcher.js +2 -2
  136. package/src/router/url/url-rule.js +1 -1
  137. package/src/router/url/url-rules.js +1 -1
  138. package/src/router/url/url-service.js +6 -1
  139. package/src/router/url/url-service.spec.js +1 -1
  140. package/src/router/view/view.spec.js +1 -1
  141. package/src/router/view-hook.spec.js +1 -1
  142. package/src/router/view-scroll.spec.js +1 -1
  143. package/src/services/anchor-scroll.js +1 -1
  144. package/src/services/browser.js +2 -2
  145. package/src/services/cookie-reader.js +1 -1
  146. package/src/services/http/http.js +3 -3
  147. package/src/services/http/http.spec.js +1 -1
  148. package/src/services/http-backend/http-backend.js +1 -1
  149. package/src/services/log.js +1 -1
  150. package/src/services/template-request.js +2 -2
  151. package/src/shared/common.js +1 -1
  152. package/src/shared/jqlite/jqlite.js +9 -9
  153. package/src/shared/jqlite/jqlite.spec.js +11 -11
  154. package/src/shared/min-err.spec.js +6 -1
  155. package/src/shared/predicates.js +1 -1
  156. package/src/shared/strings.js +1 -1
  157. package/src/shared/test-utils.js +1 -1
  158. package/src/shared/utils.js +1 -1
  159. package/src/shared/utils.spec.js +1 -1
  160. package/src/types.js +0 -2
  161. package/types/animations/animate-css-driver.d.ts +1 -1
  162. package/types/animations/animate-js.d.ts +1 -1
  163. package/types/animations/animate.d.ts +1 -1
  164. package/types/animations/animation.d.ts +1 -1
  165. package/types/core/cache/cache.d.ts +1 -1
  166. package/types/core/compile/attributes.d.ts +2 -2
  167. package/types/core/compile/compile.d.ts +3 -2
  168. package/types/core/controller/controller.d.ts +1 -1
  169. package/types/core/filter/filter.d.ts +1 -1
  170. package/types/core/location/location.d.ts +1 -1
  171. package/types/core/q/q.d.ts +1 -1
  172. package/types/core/sce/sce.d.ts +1 -1
  173. package/types/core/scope/scope.d.ts +1 -1
  174. package/types/core/timeout/timeout.d.ts +1 -1
  175. package/types/directive/channel/channel.d.ts +13 -4
  176. package/types/directive/model/model.d.ts +9 -9
  177. package/types/directive/repeat/repeat.d.ts +10 -8
  178. package/types/loader.d.ts +5 -6
  179. package/types/router/common/coreservices.d.ts +1 -1
  180. package/types/router/state/state-registry.d.ts +2 -2
  181. package/types/router/template-factory.d.ts +2 -2
  182. package/types/services/browser.d.ts +1 -1
  183. package/types/services/http/http.d.ts +1 -1
  184. package/types/services/template-request.d.ts +1 -1
  185. package/types/shared/jqlite/jqlite.d.ts +1 -1
  186. package/types/shared/test-utils.d.ts +1 -1
  187. package/types/types.d.ts +1 -5
@@ -1,262 +1,295 @@
1
- import { minErr, hashKey, isArrayLike } from "../../shared/utils";
2
- import { getBlockNodes } from "../../shared/jqlite/jqlite";
1
+ import {
2
+ minErr,
3
+ hashKey,
4
+ isArrayLike,
5
+ hasAnimate,
6
+ } from "../../shared/utils.js";
7
+ import { getBlockNodes, JQLite } from "../../shared/jqlite/jqlite.js";
8
+ import { domInsert } from "../../animations/animate.js";
3
9
 
4
- export const ngRepeatDirective = [
5
- "$parse",
6
- "$animate",
7
- ($parse, $animate) => {
8
- const NG_REMOVED = "$$NG_REMOVED";
9
- const ngRepeatMinErr = minErr("ngRepeat");
10
+ ngRepeatDirective.$inject = ["$parse", "$animate"];
10
11
 
11
- const updateScope = function (
12
- scope,
13
- index,
14
- valueIdentifier,
15
- value,
16
- keyIdentifier,
17
- key,
18
- arrayLength,
19
- ) {
20
- // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
21
- scope[valueIdentifier] = value;
22
- if (keyIdentifier) scope[keyIdentifier] = key;
23
- scope.$index = index;
24
- scope.$first = index === 0;
25
- scope.$last = index === arrayLength - 1;
26
- scope.$middle = !(scope.$first || scope.$last);
27
- scope.$odd = !(scope.$even = (index & 1) === 0);
28
- };
12
+ /**
13
+ *
14
+ * @param {import("../../core/parse/parse.js").ParseService} $parse
15
+ * @param {*} $animate
16
+ * @returns {import("../../types.js").Directive}
17
+ */
18
+ export function ngRepeatDirective($parse, $animate) {
19
+ const NG_REMOVED = "$$NG_REMOVED";
20
+ const ngRepeatMinErr = minErr("ngRepeat");
29
21
 
30
- const getBlockStart = function (block) {
31
- return block.clone[0];
32
- };
22
+ const updateScope = function (
23
+ scope,
24
+ index,
25
+ valueIdentifier,
26
+ value,
27
+ keyIdentifier,
28
+ key,
29
+ arrayLength,
30
+ ) {
31
+ // TODO(perf): generate setters to shave off ~40ms or 1-1.5%
32
+ scope[valueIdentifier] = value;
33
+ if (keyIdentifier) scope[keyIdentifier] = key;
34
+ scope.$index = index;
35
+ scope.$first = index === 0;
36
+ scope.$last = index === arrayLength - 1;
37
+ scope.$middle = !(scope.$first || scope.$last);
38
+ scope.$odd = !(scope.$even = (index & 1) === 0);
39
+ };
33
40
 
34
- const getBlockEnd = function (block) {
35
- return block.clone[block.clone.length - 1];
36
- };
41
+ const getBlockStart = function (block) {
42
+ return block.clone[0];
43
+ };
37
44
 
38
- const trackByIdArrayFn = function ($scope, key, value) {
39
- return hashKey(value);
40
- };
45
+ const getBlockEnd = function (block) {
46
+ return block.clone[block.clone.length - 1];
47
+ };
41
48
 
42
- const trackByIdObjFn = function ($scope, key) {
43
- return key;
44
- };
49
+ const trackByIdArrayFn = function ($scope, key, value) {
50
+ return hashKey(value);
51
+ };
45
52
 
46
- return {
47
- restrict: "A",
48
- multiElement: true,
49
- transclude: "element",
50
- priority: 1000,
51
- terminal: true,
52
- compile: function ngRepeatCompile($element, $attr) {
53
- const expression = $attr.ngRepeat;
53
+ const trackByIdObjFn = function ($scope, key) {
54
+ return key;
55
+ };
54
56
 
55
- let match = expression.match(
56
- /^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/,
57
+ return {
58
+ restrict: "A",
59
+ transclude: "element",
60
+ priority: 1000,
61
+ terminal: true,
62
+ compile: function ngRepeatCompile($element, $attr) {
63
+ const expression = $attr.ngRepeat;
64
+
65
+ let match = expression.match(
66
+ /^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/,
67
+ );
68
+
69
+ if (!match) {
70
+ throw ngRepeatMinErr(
71
+ "iexp",
72
+ "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
73
+ expression,
57
74
  );
75
+ }
58
76
 
59
- if (!match) {
60
- throw ngRepeatMinErr(
61
- "iexp",
62
- "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
63
- expression,
64
- );
65
- }
77
+ const lhs = match[1];
78
+ const rhs = match[2];
79
+ const aliasAs = match[3];
80
+ const trackByExp = match[4];
66
81
 
67
- const lhs = match[1];
68
- const rhs = match[2];
69
- const aliasAs = match[3];
70
- const trackByExp = match[4];
82
+ match = lhs.match(/^(?:(\s*[$\w]+)|\(\s*([$\w]+)\s*,\s*([$\w]+)\s*\))$/);
71
83
 
72
- match = lhs.match(
73
- /^(?:(\s*[$\w]+)|\(\s*([$\w]+)\s*,\s*([$\w]+)\s*\))$/,
84
+ if (!match) {
85
+ throw ngRepeatMinErr(
86
+ "iidexp",
87
+ "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
88
+ lhs,
74
89
  );
90
+ }
91
+ const valueIdentifier = match[3] || match[1];
92
+ const keyIdentifier = match[2];
75
93
 
76
- if (!match) {
77
- throw ngRepeatMinErr(
78
- "iidexp",
79
- "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
80
- lhs,
81
- );
82
- }
83
- const valueIdentifier = match[3] || match[1];
84
- const keyIdentifier = match[2];
85
-
86
- if (
87
- aliasAs &&
88
- (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
89
- /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(
90
- aliasAs,
91
- ))
92
- ) {
93
- throw ngRepeatMinErr(
94
- "badident",
95
- "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
94
+ if (
95
+ aliasAs &&
96
+ (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
97
+ /^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(
96
98
  aliasAs,
97
- );
98
- }
99
+ ))
100
+ ) {
101
+ throw ngRepeatMinErr(
102
+ "badident",
103
+ "alias '{0}' is invalid --- must be a valid JS identifier which is not a reserved name.",
104
+ aliasAs,
105
+ );
106
+ }
99
107
 
100
- let trackByIdExpFn;
108
+ let trackByIdExpFn;
101
109
 
102
- if (trackByExp) {
103
- var hashFnLocals = { $id: hashKey };
104
- const trackByExpGetter = $parse(trackByExp);
110
+ if (trackByExp) {
111
+ var hashFnLocals = { $id: hashKey };
112
+ const trackByExpGetter = $parse(trackByExp);
105
113
 
106
- trackByIdExpFn = function ($scope, key, value, index) {
107
- // assign key, value, and $index to the locals so that they can be used in hash functions
108
- if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
109
- hashFnLocals[valueIdentifier] = value;
110
- hashFnLocals.$index = index;
111
- return trackByExpGetter($scope, hashFnLocals);
112
- };
113
- }
114
+ trackByIdExpFn = function ($scope, key, value, index) {
115
+ // assign key, value, and $index to the locals so that they can be used in hash functions
116
+ if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
117
+ hashFnLocals[valueIdentifier] = value;
118
+ hashFnLocals.$index = index;
119
+ return trackByExpGetter($scope, hashFnLocals);
120
+ };
121
+ }
114
122
 
115
- return function ngRepeatLink(
116
- $scope,
117
- $element,
118
- $attr,
119
- ctrl,
120
- $transclude,
121
- ) {
122
- // Store a list of elements from previous run. This is a hash where key is the item from the
123
- // iterator, and the value is objects with following properties.
124
- // - scope: bound scope
125
- // - clone: previous element.
126
- // - index: position
127
- //
128
- // We are using no-proto object so that we don't need to guard against inherited props via
129
- // hasOwnProperty.
130
- let lastBlockMap = Object.create(null);
123
+ return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
124
+ // Store a list of elements from previous run. This is a hash where key is the item from the
125
+ // iterator, and the value is objects with following properties.
126
+ // - scope: bound scope
127
+ // - clone: previous element.
128
+ // - index: position
129
+ //
130
+ // We are using no-proto object so that we don't need to guard against inherited props via
131
+ // hasOwnProperty.
132
+ let lastBlockMap = Object.create(null);
131
133
 
132
- // watch props
133
- //watch props
134
- $scope.$watchCollection(rhs, (collection) => {
135
- var index,
136
- length,
137
- previousNode = $element[0], // node that cloned nodes should be inserted after
138
- // initialized to the comment node anchor
139
- nextNode,
140
- // Same as lastBlockMap but it has the current state. It will become the
141
- // lastBlockMap on the next iteration.
142
- nextBlockMap = Object.create(null),
143
- collectionLength,
144
- key,
145
- value, // key/value of iteration
146
- trackById,
147
- trackByIdFn,
148
- collectionKeys,
149
- block, // last object information {scope, element, id}
150
- nextBlockOrder,
151
- elementsToRemove;
134
+ // watch props
135
+ //watch props
136
+ $scope.$watchCollection(rhs, (collection) => {
137
+ var index,
138
+ length,
139
+ previousNode = $element[0], // node that cloned nodes should be inserted after
140
+ // initialized to the comment node anchor
141
+ nextNode,
142
+ // Same as lastBlockMap but it has the current state. It will become the
143
+ // lastBlockMap on the next iteration.
144
+ nextBlockMap = Object.create(null),
145
+ collectionLength,
146
+ key,
147
+ value, // key/value of iteration
148
+ trackById,
149
+ trackByIdFn,
150
+ collectionKeys,
151
+ block, // last object information {scope, element, id}
152
+ nextBlockOrder,
153
+ elementsToRemove;
152
154
 
153
- if (aliasAs) {
154
- $scope[aliasAs] = collection;
155
- }
155
+ if (aliasAs) {
156
+ $scope[aliasAs] = collection;
157
+ }
156
158
 
157
- if (isArrayLike(collection)) {
158
- collectionKeys = collection;
159
- trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
160
- } else {
161
- trackByIdFn = trackByIdExpFn || trackByIdObjFn;
162
- // if object, extract keys, in enumeration order, unsorted
163
- collectionKeys = [];
164
- for (var itemKey in collection) {
165
- if (
166
- Object.hasOwnProperty.call(collection, itemKey) &&
167
- itemKey.charAt(0) !== "$"
168
- ) {
169
- collectionKeys.push(itemKey);
170
- }
159
+ if (isArrayLike(collection)) {
160
+ collectionKeys = collection;
161
+ trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
162
+ } else {
163
+ trackByIdFn = trackByIdExpFn || trackByIdObjFn;
164
+ // if object, extract keys, in enumeration order, unsorted
165
+ collectionKeys = [];
166
+ for (var itemKey in collection) {
167
+ if (
168
+ Object.hasOwnProperty.call(collection, itemKey) &&
169
+ itemKey.charAt(0) !== "$"
170
+ ) {
171
+ collectionKeys.push(itemKey);
171
172
  }
172
173
  }
174
+ }
173
175
 
174
- collectionLength = collectionKeys.length;
175
- nextBlockOrder = new Array(collectionLength);
176
+ collectionLength = collectionKeys.length;
177
+ nextBlockOrder = new Array(collectionLength);
176
178
 
177
- // locate existing items
178
- for (index = 0; index < collectionLength; index++) {
179
- key =
180
- collection === collectionKeys ? index : collectionKeys[index];
181
- value = collection[key];
182
- trackById = trackByIdFn($scope, key, value, index);
183
- if (lastBlockMap[trackById]) {
184
- // found previously seen block
185
- block = lastBlockMap[trackById];
186
- delete lastBlockMap[trackById];
187
- nextBlockMap[trackById] = block;
188
- nextBlockOrder[index] = block;
189
- } else if (nextBlockMap[trackById]) {
190
- // if collision detected. restore lastBlockMap and throw an error
191
- Object.values(nextBlockOrder).forEach((block) => {
192
- if (block && block.scope) lastBlockMap[block.id] = block;
193
- });
194
- throw ngRepeatMinErr(
195
- "dupes",
196
- "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
197
- expression,
198
- trackById,
199
- value,
200
- );
201
- } else {
202
- // new never before seen block
203
- nextBlockOrder[index] = {
204
- id: trackById,
205
- scope: undefined,
206
- clone: undefined,
207
- };
208
- nextBlockMap[trackById] = true;
209
- }
179
+ // locate existing items
180
+ for (index = 0; index < collectionLength; index++) {
181
+ key = collection === collectionKeys ? index : collectionKeys[index];
182
+ value = collection[key];
183
+ trackById = trackByIdFn($scope, key, value, index);
184
+ if (lastBlockMap[trackById]) {
185
+ // found previously seen block
186
+ block = lastBlockMap[trackById];
187
+ delete lastBlockMap[trackById];
188
+ nextBlockMap[trackById] = block;
189
+ nextBlockOrder[index] = block;
190
+ } else if (nextBlockMap[trackById]) {
191
+ // if collision detected. restore lastBlockMap and throw an error
192
+ Object.values(nextBlockOrder).forEach((block) => {
193
+ if (block && block.scope) lastBlockMap[block.id] = block;
194
+ });
195
+ throw ngRepeatMinErr(
196
+ "dupes",
197
+ "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}, Duplicate value: {2}",
198
+ expression,
199
+ trackById,
200
+ value,
201
+ );
202
+ } else {
203
+ // new never before seen block
204
+ nextBlockOrder[index] = {
205
+ id: trackById,
206
+ scope: undefined,
207
+ clone: undefined,
208
+ };
209
+ nextBlockMap[trackById] = true;
210
210
  }
211
+ }
211
212
 
212
- // Clear the value property from the hashFnLocals object to prevent a reference to the last value
213
- // being leaked into the ngRepeatCompile function scope
214
- if (hashFnLocals) {
215
- hashFnLocals[valueIdentifier] = undefined;
216
- }
213
+ // Clear the value property from the hashFnLocals object to prevent a reference to the last value
214
+ // being leaked into the ngRepeatCompile function scope
215
+ if (hashFnLocals) {
216
+ hashFnLocals[valueIdentifier] = undefined;
217
+ }
217
218
 
218
- // remove leftover items
219
- for (var blockKey in lastBlockMap) {
220
- block = lastBlockMap[blockKey];
221
- elementsToRemove = getBlockNodes(block.clone);
222
- $animate.leave(elementsToRemove);
223
- if (elementsToRemove[0].parentNode) {
224
- // if the element was not removed yet because of pending animation, mark it as deleted
225
- // so that we can ignore it later
226
- for (
227
- index = 0, length = elementsToRemove.length;
228
- index < length;
229
- index++
230
- ) {
231
- elementsToRemove[index][NG_REMOVED] = true;
232
- }
219
+ // remove leftover items
220
+ for (var blockKey in lastBlockMap) {
221
+ block = lastBlockMap[blockKey];
222
+ elementsToRemove = getBlockNodes(block.clone);
223
+ $animate.leave(elementsToRemove);
224
+ if (elementsToRemove[0].parentNode) {
225
+ // if the element was not removed yet because of pending animation, mark it as deleted
226
+ // so that we can ignore it later
227
+ for (
228
+ index = 0, length = elementsToRemove.length;
229
+ index < length;
230
+ index++
231
+ ) {
232
+ elementsToRemove[index][NG_REMOVED] = true;
233
233
  }
234
- block.scope.$destroy();
235
234
  }
235
+ block.scope.$destroy();
236
+ }
237
+
238
+ // we are not using forEach for perf reasons (trying to avoid #call)
239
+ for (index = 0; index < collectionLength; index++) {
240
+ key = collection === collectionKeys ? index : collectionKeys[index];
241
+ value = collection[key];
242
+ block = nextBlockOrder[index];
236
243
 
237
- // we are not using forEach for perf reasons (trying to avoid #call)
238
- for (index = 0; index < collectionLength; index++) {
239
- key =
240
- collection === collectionKeys ? index : collectionKeys[index];
241
- value = collection[key];
242
- block = nextBlockOrder[index];
244
+ if (block.scope) {
245
+ // if we have already seen this object, then we need to reuse the
246
+ // associated scope/element
243
247
 
244
- if (block.scope) {
245
- // if we have already seen this object, then we need to reuse the
246
- // associated scope/element
248
+ nextNode = previousNode;
247
249
 
248
- nextNode = previousNode;
250
+ // skip nodes that are already pending removal via leave animation
251
+ do {
252
+ nextNode = nextNode.nextSibling;
253
+ } while (nextNode && nextNode[NG_REMOVED]);
249
254
 
250
- // skip nodes that are already pending removal via leave animation
251
- do {
252
- nextNode = nextNode.nextSibling;
253
- } while (nextNode && nextNode[NG_REMOVED]);
255
+ if (getBlockStart(block) !== nextNode) {
256
+ // existing item which got moved
257
+ $animate.move(getBlockNodes(block.clone), null, previousNode);
258
+ }
259
+ previousNode = getBlockEnd(block);
260
+ updateScope(
261
+ block.scope,
262
+ index,
263
+ valueIdentifier,
264
+ value,
265
+ keyIdentifier,
266
+ key,
267
+ collectionLength,
268
+ );
269
+ } else {
270
+ // new item which we don't know about
271
+ $transclude((clone, scope) => {
272
+ block.scope = scope;
273
+ // Removing this comment node breaks // "clobber ng-if" test
274
+ // TODO investigate
275
+ const endNode = document.createComment("");
276
+ clone[clone.length++] = endNode;
254
277
 
255
- if (getBlockStart(block) !== nextNode) {
256
- // existing item which got moved
257
- $animate.move(getBlockNodes(block.clone), null, previousNode);
278
+ if (hasAnimate(clone[0])) {
279
+ $animate.enter(clone, null, previousNode);
280
+ } else {
281
+ domInsert(
282
+ clone,
283
+ JQLite(previousNode).parent(),
284
+ JQLite(previousNode),
285
+ );
258
286
  }
259
- previousNode = getBlockEnd(block);
287
+ previousNode = endNode;
288
+ // Note: We only need the first/last node of the cloned nodes.
289
+ // However, we need to keep the reference to the jqlite wrapper as it might be changed later
290
+ // by a directive with templateUrl when its template arrives.
291
+ block.clone = clone;
292
+ nextBlockMap[block.id] = block;
260
293
  updateScope(
261
294
  block.scope,
262
295
  index,
@@ -266,37 +299,12 @@ export const ngRepeatDirective = [
266
299
  key,
267
300
  collectionLength,
268
301
  );
269
- } else {
270
- // new item which we don't know about
271
- $transclude((clone, scope) => {
272
- block.scope = scope;
273
- // Removing this comment node breaks // "clobber ng-if" test
274
- // TODO investigate
275
- const endNode = document.createComment("");
276
- clone[clone.length++] = endNode;
277
- $animate.enter(clone, null, previousNode);
278
- previousNode = endNode;
279
- // Note: We only need the first/last node of the cloned nodes.
280
- // However, we need to keep the reference to the jqlite wrapper as it might be changed later
281
- // by a directive with templateUrl when its template arrives.
282
- block.clone = clone;
283
- nextBlockMap[block.id] = block;
284
- updateScope(
285
- block.scope,
286
- index,
287
- valueIdentifier,
288
- value,
289
- keyIdentifier,
290
- key,
291
- collectionLength,
292
- );
293
- });
294
- }
302
+ });
295
303
  }
296
- lastBlockMap = nextBlockMap;
297
- });
298
- };
299
- },
300
- };
301
- },
302
- ];
304
+ }
305
+ lastBlockMap = nextBlockMap;
306
+ });
307
+ };
308
+ },
309
+ };
310
+ }
@@ -2,7 +2,6 @@
2
2
 
3
3
  - @ngdoc directive
4
4
  - @name ngRepeat
5
- - @multiElement
6
5
  - @restrict A
7
6
  -
8
7
  - @description
@@ -223,29 +222,8 @@
223
222
 
224
223
  </example>
225
224
 
226
- -
227
- - ## Special repeat start and end points
228
- - To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
229
- - the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
230
- - The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
231
- - up to and including the ending HTML tag where **ng-repeat-end** is placed.
232
- -
233
- - The example below makes use of this feature:
234
- - ```html
235
-
236
225
  ```
237
226
 
238
- - <header ng-repeat-start="item in items">
239
- - Header {{ item }}
240
- - </header>
241
- - <div class="body">
242
- - Body {{ item }}
243
- - </div>
244
- - <footer ng-repeat-end>
245
- - Footer {{ item }}
246
- - </footer>
247
- - ```
248
-
249
227
  ```
250
228
 
251
229
  -