@angular-wave/angular.ts 0.7.5 → 0.7.7

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 (33) hide show
  1. package/@types/core/scope/scope.d.ts +0 -2
  2. package/@types/directive/setter/setter.d.ts +2 -2
  3. package/@types/shared/utils.d.ts +8 -0
  4. package/dist/angular-ts.esm.js +208 -176
  5. package/dist/angular-ts.umd.js +208 -176
  6. package/dist/angular-ts.umd.min.js +1 -1
  7. package/docs/assets/scss/index.scss +12 -0
  8. package/docs/content/_index.md +15 -4
  9. package/docs/content/docs/directive/bind.md +70 -0
  10. package/docs/content/docs/directive/click.md +3 -0
  11. package/docs/content/docs/directive/dblclick.md +3 -0
  12. package/docs/content/docs/directive/keydown.md +38 -0
  13. package/docs/content/docs/directive/keyup.md +38 -0
  14. package/docs/content/docs/directive/load.md +43 -0
  15. package/docs/static/examples/ng-bind/ng-bind.html +9 -0
  16. package/docs/static/examples/ng-keydown/ng-keydown.html +9 -0
  17. package/docs/static/examples/ng-keyup/ng-keyup.html +9 -0
  18. package/docs/static/examples/ng-load/ng-load.html +8 -0
  19. package/legacy.d.ts +0 -4
  20. package/package.json +1 -1
  21. package/src/core/location/location.js +1 -1
  22. package/src/core/scope/scope.js +0 -5
  23. package/src/directive/bind/bind.js +16 -4
  24. package/src/directive/bind/bind.spec.js +13 -0
  25. package/src/directive/events/events.js +1 -1
  26. package/src/directive/events/events.md +0 -41
  27. package/src/directive/messages/messages.js +1 -1
  28. package/src/directive/repeat/repeat.js +175 -153
  29. package/src/directive/setter/setter.js +1 -1
  30. package/src/directive/switch/switch.spec.js +1 -1
  31. package/src/router/directives/state-directives.js +4 -6
  32. package/src/services/anchor-scroll.js +1 -1
  33. package/src/shared/utils.js +19 -1
@@ -1,5 +1,12 @@
1
- import { minErr, hashKey, isArrayLike, hasOwn } from "../../shared/utils.js";
2
- import { getBlockNodes } from "../../shared/dom.js";
1
+ import {
2
+ minErr,
3
+ hashKey,
4
+ isArrayLike,
5
+ hasOwn,
6
+ isDefined,
7
+ callBackOnce,
8
+ } from "../../shared/utils.js";
9
+ import { getBlockNodes, removeElement } from "../../shared/dom.js";
3
10
  import { $injectTokens } from "../../injection-tokens.js";
4
11
 
5
12
  const NG_REMOVED = "$$NG_REMOVED";
@@ -78,7 +85,7 @@ export function ngRepeatDirective($animate) {
78
85
  transclude: "element",
79
86
  priority: 1000,
80
87
  terminal: true,
81
- compile: (_$element, $attr) => {
88
+ compile: ($element, $attr) => {
82
89
  const expression = $attr["ngRepeat"];
83
90
  const hasAnimate = !!$attr["animate"];
84
91
 
@@ -126,6 +133,14 @@ export function ngRepeatDirective($animate) {
126
133
 
127
134
  let trackByIdExpFn;
128
135
 
136
+ const swap = callBackOnce(() => {
137
+ if (isDefined($attr["lazy"]) && isDefined($attr["swap"])) {
138
+ document
139
+ .querySelectorAll($attr["swap"])
140
+ .forEach((x) => removeElement(x));
141
+ }
142
+ });
143
+
129
144
  return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
130
145
  // Store a list of elements from previous run. This is a hash where key is the item from the
131
146
  // iterator, and the value is objects with following properties.
@@ -137,174 +152,181 @@ export function ngRepeatDirective($animate) {
137
152
  // hasOwnProperty.
138
153
  let lastBlockMap = Object.create(null);
139
154
  // watch props
140
- $scope.$watch(rhs, (collection) => {
141
- let index,
142
- length,
143
- previousNode = $element, // node that cloned nodes should be inserted after
144
- // initialized to the comment node anchor
145
- nextNode;
146
- const // Same as lastBlockMap but it has the current state. It will become the
147
- // lastBlockMap on the next iteration.
148
- nextBlockMap = Object.create(null);
149
- let collectionLength,
150
- key,
151
- value, // key/value of iteration
152
- trackById,
153
- trackByIdFn,
154
- collectionKeys,
155
- block, // last object information {scope, element, id}
156
- nextBlockOrder,
157
- elementsToRemove;
155
+ $scope.$watch(
156
+ rhs,
157
+ (collection) => {
158
+ swap();
159
+ let index,
160
+ length,
161
+ previousNode = $element, // node that cloned nodes should be inserted after
162
+ // initialized to the comment node anchor
163
+ nextNode;
164
+ const // Same as lastBlockMap but it has the current state. It will become the
165
+ // lastBlockMap on the next iteration.
166
+ nextBlockMap = Object.create(null);
167
+ let collectionLength,
168
+ key,
169
+ value, // key/value of iteration
170
+ trackById,
171
+ trackByIdFn,
172
+ collectionKeys,
173
+ block, // last object information {scope, element, id}
174
+ nextBlockOrder,
175
+ elementsToRemove;
158
176
 
159
- if (aliasAs) {
160
- $scope[aliasAs] = collection;
161
- }
177
+ if (aliasAs) {
178
+ $scope[aliasAs] = collection;
179
+ }
162
180
 
163
- if (isArrayLike(collection)) {
164
- collectionKeys = collection;
165
- trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
166
- } else {
167
- trackByIdFn = trackByIdExpFn || trackByIdObjFn;
168
- // if object, extract keys, in enumeration order, unsorted
169
- collectionKeys = [];
170
- for (const itemKey in collection) {
171
- if (hasOwn(collection, itemKey) && itemKey.charAt(0) !== "$") {
172
- collectionKeys.push(itemKey);
181
+ if (isArrayLike(collection)) {
182
+ collectionKeys = collection;
183
+ trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
184
+ } else {
185
+ trackByIdFn = trackByIdExpFn || trackByIdObjFn;
186
+ // if object, extract keys, in enumeration order, unsorted
187
+ collectionKeys = [];
188
+ for (const itemKey in collection) {
189
+ if (hasOwn(collection, itemKey) && itemKey.charAt(0) !== "$") {
190
+ collectionKeys.push(itemKey);
191
+ }
173
192
  }
174
193
  }
175
- }
176
194
 
177
- collectionLength = collectionKeys.length;
178
- nextBlockOrder = new Array(collectionLength);
195
+ collectionLength = collectionKeys.length;
196
+ nextBlockOrder = new Array(collectionLength);
179
197
 
180
- // locate existing items
181
- for (index = 0; index < collectionLength; index++) {
182
- key = collection === collectionKeys ? index : collectionKeys[index];
183
- value = collection[key];
184
- trackById = trackByIdFn($scope, key, value);
185
- if (lastBlockMap[trackById]) {
186
- // found previously seen block
187
- block = lastBlockMap[trackById];
188
- delete lastBlockMap[trackById];
189
- nextBlockMap[trackById] = block;
190
- nextBlockOrder[index] = block;
191
- } else if (nextBlockMap[trackById]) {
192
- // if collision detected. restore lastBlockMap and throw an error
193
- Object.values(nextBlockOrder).forEach((block) => {
194
- if (block && block.scope) lastBlockMap[block.id] = block;
195
- });
196
- throw ngRepeatMinErr(
197
- "dupes",
198
- "Duplicates keys in a repeater are not allowed. Repeater: {0}, Duplicate key: {1} for value: {2}",
199
- expression,
200
- trackById,
201
- value,
202
- );
203
- } else {
204
- // new never before seen block
205
- nextBlockOrder[index] = {
206
- id: trackById,
207
- scope: undefined,
208
- clone: undefined,
209
- };
210
- nextBlockMap[trackById] = true;
198
+ // locate existing items
199
+ for (index = 0; index < collectionLength; index++) {
200
+ key =
201
+ collection === collectionKeys ? index : collectionKeys[index];
202
+ value = collection[key];
203
+ trackById = trackByIdFn($scope, key, value);
204
+ if (lastBlockMap[trackById]) {
205
+ // found previously seen block
206
+ block = lastBlockMap[trackById];
207
+ delete lastBlockMap[trackById];
208
+ nextBlockMap[trackById] = block;
209
+ nextBlockOrder[index] = block;
210
+ } else if (nextBlockMap[trackById]) {
211
+ // if collision detected. restore lastBlockMap and throw an error
212
+ Object.values(nextBlockOrder).forEach((block) => {
213
+ if (block && block.scope) lastBlockMap[block.id] = block;
214
+ });
215
+ throw ngRepeatMinErr(
216
+ "dupes",
217
+ "Duplicates keys in a repeater are not allowed. Repeater: {0}, Duplicate key: {1} for value: {2}",
218
+ expression,
219
+ trackById,
220
+ value,
221
+ );
222
+ } else {
223
+ // new never before seen block
224
+ nextBlockOrder[index] = {
225
+ id: trackById,
226
+ scope: undefined,
227
+ clone: undefined,
228
+ };
229
+ nextBlockMap[trackById] = true;
230
+ }
211
231
  }
212
- }
213
232
 
214
- // remove leftover items
215
- for (let blockKey in lastBlockMap) {
216
- block = lastBlockMap[blockKey];
217
- elementsToRemove = block.clone;
218
- if (hasAnimate) {
219
- $animate.leave(elementsToRemove);
220
- } else {
221
- elementsToRemove.remove();
222
- }
223
- if (elementsToRemove.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;
233
+ // remove leftover items
234
+ for (let blockKey in lastBlockMap) {
235
+ block = lastBlockMap[blockKey];
236
+ elementsToRemove = block.clone;
237
+ if (hasAnimate) {
238
+ $animate.leave(elementsToRemove);
239
+ } else {
240
+ elementsToRemove.remove();
232
241
  }
242
+ if (elementsToRemove.parentNode) {
243
+ // if the element was not removed yet because of pending animation, mark it as deleted
244
+ // so that we can ignore it later
245
+ for (
246
+ index = 0, length = elementsToRemove.length;
247
+ index < length;
248
+ index++
249
+ ) {
250
+ elementsToRemove[index][NG_REMOVED] = true;
251
+ }
252
+ }
253
+ block.scope.$destroy();
233
254
  }
234
- block.scope.$destroy();
235
- }
236
255
 
237
- for (index = 0; index < collectionLength; index++) {
238
- key = collection === collectionKeys ? index : collectionKeys[index];
239
- value = collection[key];
240
- block = nextBlockOrder[index];
256
+ for (index = 0; index < collectionLength; index++) {
257
+ key =
258
+ collection === collectionKeys ? index : collectionKeys[index];
259
+ value = collection[key];
260
+ block = nextBlockOrder[index];
241
261
 
242
- if (block.scope) {
243
- // if we have already seen this object, then we need to reuse the
244
- // associated scope/element
262
+ if (block.scope) {
263
+ // if we have already seen this object, then we need to reuse the
264
+ // associated scope/element
245
265
 
246
- nextNode = previousNode;
266
+ nextNode = previousNode;
247
267
 
248
- // skip nodes that are already pending removal via leave animation
249
- do {
250
- nextNode = nextNode.nextSibling;
251
- } while (nextNode && nextNode[NG_REMOVED]);
268
+ // skip nodes that are already pending removal via leave animation
269
+ do {
270
+ nextNode = nextNode.nextSibling;
271
+ } while (nextNode && nextNode[NG_REMOVED]);
252
272
 
253
- if (getBlockStart(block) !== nextNode) {
254
- // existing item which got moved
255
- $animate.move(getBlockNodes(block.clone), null, previousNode);
256
- }
257
- previousNode = getBlockEnd(block);
258
- updateScope(
259
- block.scope,
260
- index,
261
- valueIdentifier,
262
- value,
263
- keyIdentifier,
264
- key,
265
- collectionLength,
266
- );
267
- } else {
268
- // new item which we don't know about
269
- $transclude(
270
- /**
271
- * Clone attach function
272
- * @param {Array<NodeList>} clone
273
- * @param {import("../../core/scope/scope.js").Scope} scope
274
- */
273
+ if (getBlockStart(block) !== nextNode) {
274
+ // existing item which got moved
275
+ $animate.move(getBlockNodes(block.clone), null, previousNode);
276
+ }
277
+ previousNode = getBlockEnd(block);
278
+ updateScope(
279
+ block.scope,
280
+ index,
281
+ valueIdentifier,
282
+ value,
283
+ keyIdentifier,
284
+ key,
285
+ collectionLength,
286
+ );
287
+ } else {
288
+ // new item which we don't know about
289
+ $transclude(
290
+ /**
291
+ * Clone attach function
292
+ * @param {Array<NodeList>} clone
293
+ * @param {import("../../core/scope/scope.js").Scope} scope
294
+ */
275
295
 
276
- (clone, scope) => {
277
- block.scope = scope;
278
- const endNode = clone;
279
- if (hasAnimate) {
280
- $animate.enter(clone, null, previousNode);
281
- } else {
282
- // @ts-ignore
283
- previousNode.after(clone);
284
- }
296
+ (clone, scope) => {
297
+ block.scope = scope;
298
+ const endNode = clone;
299
+ if (hasAnimate) {
300
+ $animate.enter(clone, null, previousNode);
301
+ } else {
302
+ // @ts-ignore
303
+ previousNode.after(clone);
304
+ }
285
305
 
286
- // @ts-ignore
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 dom 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;
293
- updateScope(
294
- block.scope,
295
- index,
296
- valueIdentifier,
297
- value,
298
- keyIdentifier,
299
- key,
300
- collectionLength,
301
- );
302
- },
303
- );
306
+ // @ts-ignore
307
+ previousNode = endNode;
308
+ // Note: We only need the first/last node of the cloned nodes.
309
+ // However, we need to keep the reference to the dom wrapper as it might be changed later
310
+ // by a directive with templateUrl when its template arrives.
311
+ block.clone = clone;
312
+ nextBlockMap[block.id] = block;
313
+ updateScope(
314
+ block.scope,
315
+ index,
316
+ valueIdentifier,
317
+ value,
318
+ keyIdentifier,
319
+ key,
320
+ collectionLength,
321
+ );
322
+ },
323
+ );
324
+ }
304
325
  }
305
- }
306
- lastBlockMap = nextBlockMap;
307
- });
326
+ lastBlockMap = nextBlockMap;
327
+ },
328
+ isDefined($attr["lazy"]),
329
+ );
308
330
  };
309
331
  },
310
332
  };
@@ -2,7 +2,7 @@ ngSetterDirective.$inject = ["$parse", "$log"];
2
2
  /**
3
3
  * @param {import('../../core/parse/interface.ts').ParseService} $parse
4
4
  * @param {import('../../services/log/interface.ts').LogService} $log
5
- * @returns {import('../../interface.ts').Directive}
5
+ * @returns {import('interface.ts').Directive}
6
6
  */
7
7
  export function ngSetterDirective($parse, $log) {
8
8
  return {
@@ -209,7 +209,7 @@ describe("ngSwitch", () => {
209
209
 
210
210
  scope.$watch("value", () => {
211
211
  if (scope.value === "bar") {
212
- scope.$evalAsync(() => {
212
+ Promise.resolve().then(() => {
213
213
  scope.value = "baz";
214
214
  });
215
215
  }
@@ -382,12 +382,10 @@ export function $StateRefActiveDirective(
382
382
  const removeClasses = allClasses.filter(
383
383
  (cls) => !addClasses.includes(cls),
384
384
  );
385
- $scope.$evalAsync(() => {
386
- addClasses.forEach((className) => $element.classList.add(className));
387
- removeClasses.forEach((className) =>
388
- $element.classList.remove(className),
389
- );
390
- });
385
+ addClasses.forEach((className) => $element.classList.add(className));
386
+ removeClasses.forEach((className) =>
387
+ $element.classList.remove(className),
388
+ );
391
389
  }
392
390
  update();
393
391
  },
@@ -128,7 +128,7 @@ export class AnchorScrollProvider {
128
128
  // skip the initial scroll if $location.hash is empty
129
129
  if (newVal === oldVal && newVal === "") return;
130
130
 
131
- const action = () => $rootScope.$evalAsync(scroll);
131
+ const action = () => Promise.resolve().then(scroll);
132
132
  if (document.readyState === "complete") {
133
133
  // Force the action to be run async for consistent behavior
134
134
  // from the action's point of view
@@ -232,7 +232,7 @@ export function isWindow(obj) {
232
232
  * @returns {boolean}
233
233
  */
234
234
  export function isScope(obj) {
235
- return obj && obj.$evalAsync && obj.$watch;
235
+ return obj && obj.$watch;
236
236
  }
237
237
 
238
238
  /**
@@ -1193,3 +1193,21 @@ export function isObjectEmpty(obj) {
1193
1193
  export function hasOwn(obj, key) {
1194
1194
  return Object.prototype.hasOwnProperty.call(obj, key);
1195
1195
  }
1196
+
1197
+ /**
1198
+ * Wraps a function so it can only be called once.
1199
+ * Subsequent calls do nothing and return undefined.
1200
+ *
1201
+ * @param {Function} fn - The function to wrap.
1202
+ * @returns {Function} A new function that will call `fn` only once.
1203
+ */
1204
+ export function callBackOnce(fn) {
1205
+ let called = false;
1206
+
1207
+ return function (...args) {
1208
+ if (!called) {
1209
+ called = true;
1210
+ return fn.apply(this, args);
1211
+ }
1212
+ };
1213
+ }