@angular-wave/angular.ts 0.6.3 → 0.6.4
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.
- package/dist/angular-ts.esm.js +2 -2
- package/dist/angular-ts.umd.js +2 -2
- package/package.json +1 -1
- package/src/angular.spec.js +2 -2
- package/src/animations/animate-children-directive.js +1 -1
- package/src/animations/animate-css-driver.js +2 -2
- package/src/animations/animate-css.js +1 -1
- package/src/animations/animate-js.js +1 -1
- package/src/animations/animate-queue.js +2 -2
- package/src/animations/animate.js +2 -2
- package/src/animations/animate.spec.js +3 -3
- package/src/animations/animation.js +2 -2
- package/src/binding.spec.js +1 -1
- package/src/core/cache/cache.js +1 -1
- package/src/core/compile/attributes.js +3 -3
- package/src/core/compile/compile.js +13 -140
- package/src/core/compile/compile.md +0 -8
- package/src/core/compile/compile.spec.js +35 -639
- package/src/core/controller/controller.js +1 -1
- package/src/core/di/injector.js +1 -1
- package/src/core/di/injector.spec.js +1 -1
- package/src/core/di/internal-injector.js +1 -1
- package/src/core/di/ng-module.js +1 -1
- package/src/core/filter/filter.js +1 -1
- package/src/core/interpolate/interpolate.js +1 -1
- package/src/core/interval/interval-factory.js +1 -1
- package/src/core/interval/interval.js +1 -1
- package/src/core/location/location.js +3 -3
- package/src/core/on.spec.js +1 -1
- package/src/core/parse/interpreter.js +1 -1
- package/src/core/prop.spec.js +2 -2
- package/src/core/q/q.js +1 -1
- package/src/core/root-element.spec.js +1 -1
- package/src/core/sanitize/sanitize-uri.js +1 -1
- package/src/core/sce/sce.js +2 -2
- package/src/core/sce/sce.spec.js +1 -1
- package/src/core/scope/scope.js +1 -1
- package/src/core/scope/scope.spec.js +1 -1
- package/src/core/timeout/timeout.js +1 -1
- package/src/core/url-utils/url-utils.js +1 -1
- package/src/directive/aria/aria.js +1 -1
- package/src/directive/aria/aria.spec.js +1 -1
- package/src/directive/attrs/attrs.js +3 -3
- package/src/directive/attrs/attrs.spec.js +1 -1
- package/src/directive/attrs/boolean.spec.js +1 -1
- package/src/directive/attrs/element-style.spec.js +1 -1
- package/src/directive/attrs/src.spec.js +1 -1
- package/src/directive/bind/bind.js +1 -1
- package/src/directive/bind/bind.spec.js +1 -1
- package/src/directive/bind/bing-html.spec.js +1 -1
- package/src/directive/change/change.spec.js +1 -1
- package/src/directive/class/class.js +1 -1
- package/src/directive/class/class.spec.js +2 -2
- package/src/directive/cloak/cloak.spec.js +1 -1
- package/src/directive/controller/controller.spec.js +2 -2
- package/src/directive/events/click.spec.js +1 -1
- package/src/directive/events/event.spec.js +1 -1
- package/src/directive/events/events.js +2 -2
- package/src/directive/form/form.js +2 -2
- package/src/directive/form/form.spec.js +1 -1
- package/src/directive/if/if.js +2 -3
- package/src/directive/if/if.md +0 -1
- package/src/directive/if/if.spec.js +2 -2
- package/src/directive/include/include.js +3 -3
- package/src/directive/include/include.spec.js +2 -2
- package/src/directive/init/init.spec.js +1 -1
- package/src/directive/input/input.js +1 -1
- package/src/directive/input/input.spec.js +1 -1
- package/src/directive/messages/messages.js +1 -1
- package/src/directive/messages/messages.spec.js +3 -3
- package/src/directive/model/model.js +6 -6
- package/src/directive/model/model.spec.js +2 -2
- package/src/directive/model-options/model-options.js +1 -1
- package/src/directive/model-options/model-options.spec.js +2 -2
- package/src/directive/non-bindable/non-bindable.spec.js +1 -1
- package/src/directive/observe/observe.spec.js +1 -1
- package/src/directive/options/options.js +6 -2
- package/src/directive/options/options.spec.js +2 -2
- package/src/directive/ref/href.spec.js +2 -2
- package/src/directive/ref/ref.js +1 -1
- package/src/directive/repeat/repeat.js +263 -255
- package/src/directive/repeat/repeat.md +0 -22
- package/src/directive/repeat/repeat.spec.js +2 -115
- package/src/directive/script/script.spec.js +1 -1
- package/src/directive/select/select.js +2 -2
- package/src/directive/select/select.spec.js +2 -2
- package/src/directive/show-hide/show-hide.js +1 -3
- package/src/directive/show-hide/show-hide.md +0 -2
- package/src/directive/show-hide/show-hide.spec.js +1 -1
- package/src/directive/style/style.spec.js +1 -1
- package/src/directive/switch/switch.js +2 -4
- package/src/directive/switch/switch.spec.js +1 -51
- package/src/directive/transclude/transclude.js +2 -2
- package/src/directive/validators/validators.js +2 -2
- package/src/directive/validators/validators.spec.js +1 -1
- package/src/filters/filter.js +1 -1
- package/src/filters/filter.spec.js +2 -2
- package/src/filters/filters.js +1 -1
- package/src/filters/filters.spec.js +1 -1
- package/src/filters/limit-to.js +1 -1
- package/src/filters/limit-to.spec.js +1 -1
- package/src/filters/order-by.js +1 -1
- package/src/index.js +3 -9
- package/src/loader.js +10 -5
- package/src/router/common/trace.js +1 -1
- package/src/router/directives/state-directives.js +1 -1
- package/src/router/directives/state-directives.spec.js +1 -1
- package/src/router/directives/view-directive.js +2 -2
- package/src/router/directives/view-directive.spec.js +1 -1
- package/src/router/hooks/redirect-to.js +1 -1
- package/src/router/params/param-type.js +1 -1
- package/src/router/params/param-types.js +1 -1
- package/src/router/params/param.js +1 -1
- package/src/router/resolve/resolvable.js +1 -1
- package/src/router/resolve/resolve-context.js +1 -1
- package/src/router/state/state-builder.js +1 -1
- package/src/router/state/state-matcher.js +1 -1
- package/src/router/state/state-object.js +1 -1
- package/src/router/state/state-queue-manager.js +1 -1
- package/src/router/state/state-registry.js +1 -1
- package/src/router/state/state-service.js +1 -1
- package/src/router/state/state.spec.js +2 -2
- package/src/router/state/target-state.js +1 -1
- package/src/router/state/views.js +1 -1
- package/src/router/state-provider.js +1 -1
- package/src/router/template-factory.js +1 -1
- package/src/router/template-factory.spec.js +1 -1
- package/src/router/transition/hook-registry.js +1 -1
- package/src/router/transition/transition-service.js +1 -1
- package/src/router/transition/transition.js +1 -1
- package/src/router/url/url-config.js +1 -1
- package/src/router/url/url-matcher.js +1 -1
- package/src/router/url/url-rule.js +1 -1
- package/src/router/url/url-rules.js +1 -1
- package/src/router/url/url-service.js +6 -1
- package/src/router/url/url-service.spec.js +1 -1
- package/src/router/view/view.spec.js +1 -1
- package/src/router/view-hook.spec.js +1 -1
- package/src/router/view-scroll.spec.js +1 -1
- package/src/services/anchor-scroll.js +1 -1
- package/src/services/browser.js +2 -2
- package/src/services/cookie-reader.js +1 -1
- package/src/services/http/http.js +2 -2
- package/src/services/http/http.spec.js +1 -1
- package/src/services/http-backend/http-backend.js +1 -1
- package/src/services/log.js +1 -1
- package/src/services/template-request.js +1 -1
- package/src/shared/common.js +1 -1
- package/src/shared/jqlite/jqlite.js +9 -9
- package/src/shared/jqlite/jqlite.spec.js +11 -11
- package/src/shared/min-err.spec.js +6 -1
- package/src/shared/predicates.js +1 -1
- package/src/shared/strings.js +1 -1
- package/src/shared/test-utils.js +1 -1
- package/src/shared/utils.js +1 -1
- package/src/shared/utils.spec.js +1 -1
- package/src/types.js +0 -2
- package/types/animations/animate-css-driver.d.ts +1 -1
- package/types/animations/animate.d.ts +1 -1
- package/types/core/cache/cache.d.ts +1 -1
- package/types/core/compile/attributes.d.ts +2 -2
- package/types/core/compile/compile.d.ts +1 -1
- package/types/core/location/location.d.ts +1 -1
- package/types/directive/model/model.d.ts +1 -1
- package/types/directive/repeat/repeat.d.ts +0 -1
- package/types/loader.d.ts +2 -0
- package/types/services/browser.d.ts +1 -1
- package/types/shared/jqlite/jqlite.d.ts +1 -1
- package/types/shared/test-utils.d.ts +1 -1
- package/types/types.d.ts +1 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Angular } from "../../loader";
|
|
2
2
|
import { createInjector } from "../../core/di/injector";
|
|
3
|
-
import { dealoc } from "../../shared/jqlite/jqlite";
|
|
4
|
-
import { isDefined } from "../../shared/utils";
|
|
3
|
+
import { dealoc } from "../../shared/jqlite/jqlite.js";
|
|
4
|
+
import { isDefined } from "../../shared/utils.js";
|
|
5
5
|
|
|
6
6
|
describe("ngHref", () => {
|
|
7
7
|
let $rootScope;
|
package/src/directive/ref/ref.js
CHANGED
|
@@ -1,262 +1,295 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
31
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
const getBlockStart = function (block) {
|
|
42
|
+
return block.clone[0];
|
|
43
|
+
};
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
const getBlockEnd = function (block) {
|
|
46
|
+
return block.clone[block.clone.length - 1];
|
|
47
|
+
};
|
|
41
48
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
const trackByIdArrayFn = function ($scope, key, value) {
|
|
50
|
+
return hashKey(value);
|
|
51
|
+
};
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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
|
-
|
|
73
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
108
|
+
let trackByIdExpFn;
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
if (trackByExp) {
|
|
111
|
+
var hashFnLocals = { $id: hashKey };
|
|
112
|
+
const trackByExpGetter = $parse(trackByExp);
|
|
105
113
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
if (aliasAs) {
|
|
156
|
+
$scope[aliasAs] = collection;
|
|
157
|
+
}
|
|
156
158
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
+
collectionLength = collectionKeys.length;
|
|
177
|
+
nextBlockOrder = new Array(collectionLength);
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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
|
-
|
|
245
|
-
// if we have already seen this object, then we need to reuse the
|
|
246
|
-
// associated scope/element
|
|
248
|
+
nextNode = previousNode;
|
|
247
249
|
|
|
248
|
-
|
|
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
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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 (
|
|
256
|
-
|
|
257
|
-
|
|
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 =
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|