@angular-wave/angular.ts 0.7.5 → 0.7.8

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 (174) hide show
  1. package/@types/animations/raf-scheduler.d.ts +2 -2
  2. package/@types/animations/shared.d.ts +0 -1
  3. package/@types/core/compile/attributes.d.ts +3 -3
  4. package/@types/core/compile/compile.d.ts +1 -1
  5. package/@types/core/di/injector.d.ts +0 -1
  6. package/@types/core/di/internal-injector.d.ts +1 -0
  7. package/@types/core/di/ng-module.d.ts +5 -0
  8. package/@types/core/filter/filter.d.ts +11 -13
  9. package/@types/core/sanitize/sanitize-uri.d.ts +3 -6
  10. package/@types/core/scope/scope.d.ts +1 -3
  11. package/@types/directive/attrs/attrs.d.ts +7 -1
  12. package/@types/directive/events/events.d.ts +9 -3
  13. package/@types/directive/http/http.d.ts +6 -2
  14. package/@types/directive/include/include.d.ts +2 -2
  15. package/@types/directive/input/input.d.ts +2 -12
  16. package/@types/directive/messages/messages.d.ts +9 -48
  17. package/@types/directive/model/model.d.ts +3 -3
  18. package/@types/directive/options/options.d.ts +13 -20
  19. package/@types/directive/setter/setter.d.ts +2 -2
  20. package/@types/directive/switch/switch.d.ts +1 -0
  21. package/@types/directive/transclude/transclude.d.ts +10 -6
  22. package/@types/interface.d.ts +54 -18
  23. package/@types/router/common/glob.d.ts +5 -1
  24. package/@types/router/directives/view-directive.d.ts +2 -19
  25. package/@types/router/globals.d.ts +1 -2
  26. package/@types/router/state/state-registry.d.ts +1 -2
  27. package/@types/router/url/url-service.d.ts +7 -9
  28. package/@types/services/anchor-scroll.d.ts +1 -1
  29. package/@types/{core → services/exception}/exception-handler.d.ts +4 -4
  30. package/@types/{core/error-handler.d.ts → services/exception/interface.d.ts} +1 -1
  31. package/@types/services/http/http.d.ts +0 -2
  32. package/@types/services/http/interface.d.ts +2 -2
  33. package/@types/services/http-backend/http-backend.d.ts +13 -21
  34. package/@types/services/location/interface.d.ts +8 -0
  35. package/@types/{core → services}/location/location.d.ts +52 -12
  36. package/@types/{core → services}/sce/sce.d.ts +1 -1
  37. package/@types/services/template-cache/interface.d.ts +8 -2
  38. package/@types/services/template-cache/template-cache.d.ts +1 -1
  39. package/@types/services/template-request.d.ts +1 -1
  40. package/@types/shared/cache.d.ts +0 -2
  41. package/@types/shared/dom.d.ts +6 -0
  42. package/@types/shared/test-utils.d.ts +1 -0
  43. package/@types/shared/url-utils/interface.d.ts +47 -0
  44. package/@types/{core → shared}/url-utils/url-utils.d.ts +26 -13
  45. package/@types/shared/utils.d.ts +23 -0
  46. package/Makefile +3 -2
  47. package/dist/angular-ts.esm.js +1188 -1364
  48. package/dist/angular-ts.umd.js +1188 -1364
  49. package/dist/angular-ts.umd.min.js +1 -1
  50. package/docs/assets/scss/index.scss +12 -0
  51. package/docs/content/_index.md +15 -4
  52. package/docs/content/docs/directive/bind.md +72 -0
  53. package/docs/content/docs/directive/click.md +3 -0
  54. package/docs/content/docs/directive/dblclick.md +3 -0
  55. package/docs/content/docs/directive/get.md +203 -0
  56. package/docs/content/docs/directive/keydown.md +38 -0
  57. package/docs/content/docs/directive/keyup.md +38 -0
  58. package/docs/content/docs/directive/load.md +43 -0
  59. package/docs/content/docs/provider/templateCacheProvider.md +66 -1
  60. package/docs/content/docs/service/templateCache.md +2 -2
  61. package/docs/layouts/partials/hooks/head-end.html +1 -1
  62. package/docs/layouts/shortcodes/showcss.html +2 -0
  63. package/docs/static/examples/ng-bind/ng-bind.html +9 -0
  64. package/docs/static/examples/ng-keydown/ng-keydown.html +9 -0
  65. package/docs/static/examples/ng-keyup/ng-keyup.html +9 -0
  66. package/docs/static/examples/ng-load/ng-load.html +8 -0
  67. package/docs/static/typedoc/assets/hierarchy.js +1 -1
  68. package/docs/static/typedoc/assets/navigation.js +1 -1
  69. package/docs/static/typedoc/assets/search.js +1 -1
  70. package/docs/static/typedoc/classes/NgModule.html +32 -0
  71. package/docs/static/typedoc/classes/TemplateCacheProvider.html +1 -1
  72. package/docs/static/typedoc/hierarchy.html +1 -1
  73. package/docs/static/typedoc/index.html +1 -1
  74. package/docs/static/typedoc/interfaces/Directive.html +5 -4
  75. package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +1 -1
  76. package/docs/static/typedoc/interfaces/HttpResponse.html +2 -3
  77. package/docs/static/typedoc/interfaces/Provider.html +15 -10
  78. package/docs/static/typedoc/interfaces/RequestConfig.html +1 -1
  79. package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +1 -1
  80. package/docs/static/typedoc/interfaces/TemplateCache.html +7 -0
  81. package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +1 -0
  82. package/docs/static/typedoc/types/DirectiveFactory.html +1 -2
  83. package/docs/static/typedoc/types/DirectiveFactoryFn.html +1 -0
  84. package/docs/static/typedoc/types/HttpResponseStatus.html +1 -0
  85. package/docs/static/typedoc/types/{TemplateCache.html → SwapModeType.html} +1 -1
  86. package/docs/static/typedoc/variables/SwapMode.html +11 -0
  87. package/legacy.d.ts +0 -14
  88. package/package.json +1 -3
  89. package/src/animations/animate-children-directive.js +2 -2
  90. package/src/animations/raf-scheduler.js +1 -1
  91. package/src/animations/shared.js +0 -9
  92. package/src/core/compile/attributes.js +1 -1
  93. package/src/core/compile/compile.js +3 -3
  94. package/src/core/di/injector.js +4 -17
  95. package/src/core/di/internal-injector.js +4 -1
  96. package/src/core/di/ng-module.js +12 -27
  97. package/src/core/filter/filter.js +28 -28
  98. package/src/core/parse/interpreter.js +32 -38
  99. package/src/core/sanitize/sanitize-uri.js +3 -3
  100. package/src/core/scope/scope.js +2 -7
  101. package/src/directive/attrs/attrs.js +7 -4
  102. package/src/directive/bind/bind.js +16 -4
  103. package/src/directive/bind/bind.spec.js +13 -0
  104. package/src/directive/events/events.js +7 -3
  105. package/src/directive/events/events.md +0 -41
  106. package/src/directive/http/delete.spec.js +2 -0
  107. package/src/directive/http/get.spec.js +280 -3
  108. package/src/directive/http/http.js +100 -12
  109. package/src/directive/http/http.test.js +2 -2
  110. package/src/directive/http/post.spec.js +2 -0
  111. package/src/directive/http/put.spec.js +2 -0
  112. package/src/directive/include/include.js +7 -7
  113. package/src/directive/input/input.js +6 -28
  114. package/src/directive/messages/messages.js +5 -1
  115. package/src/directive/model/model.js +1 -1
  116. package/src/directive/options/options.js +454 -464
  117. package/src/directive/repeat/repeat.js +175 -153
  118. package/src/directive/setter/setter.js +13 -15
  119. package/src/directive/setter/setter.spec.js +39 -16
  120. package/src/directive/switch/switch.js +1 -0
  121. package/src/directive/switch/switch.spec.js +1 -1
  122. package/src/directive/transclude/transclude.js +87 -89
  123. package/src/injection-tokens.js +1 -1
  124. package/src/interface.ts +68 -19
  125. package/src/loader.js +4 -9
  126. package/src/public.js +9 -15
  127. package/src/router/common/glob.js +5 -0
  128. package/src/router/directives/state-directives.js +4 -6
  129. package/src/router/directives/state-directives.spec.js +1 -1
  130. package/src/router/directives/view-directive.js +9 -1
  131. package/src/router/globals.js +0 -1
  132. package/src/router/state/state-registry.js +0 -1
  133. package/src/router/state-filters.js +2 -2
  134. package/src/router/url/url-service.js +5 -9
  135. package/src/services/anchor-scroll.html +0 -7
  136. package/src/services/anchor-scroll.js +2 -2
  137. package/src/{core → services/exception}/exception-handler.js +2 -2
  138. package/src/{core/error-handler.ts → services/exception/interface.ts} +1 -1
  139. package/src/services/http/http.js +2 -13
  140. package/src/services/http/interface.ts +2 -2
  141. package/src/services/http-backend/http-backend.js +4 -14
  142. package/src/services/http-backend/http-backend.spec.js +1 -4
  143. package/src/services/location/interface.ts +8 -0
  144. package/src/{core → services}/location/location.html +4 -1
  145. package/src/{core → services}/location/location.js +129 -27
  146. package/src/{core → services}/location/location.spec.js +2 -2
  147. package/src/{core → services}/location/location.test.js +1 -1
  148. package/src/{core → services}/sce/sce.html +1 -1
  149. package/src/{core → services}/sce/sce.js +9 -3
  150. package/src/{core → services}/sce/sce.spec.js +2 -3
  151. package/src/{core → services}/sce/sce.test.js +1 -1
  152. package/src/services/template-cache/interface.ts +8 -2
  153. package/src/services/template-cache/template-cache.js +3 -1
  154. package/src/services/template-cache/template-cache.spec.js +72 -0
  155. package/src/services/template-request.js +2 -1
  156. package/src/shared/cache.js +0 -2
  157. package/src/shared/dom.js +10 -0
  158. package/src/shared/test-utils.js +1 -0
  159. package/src/shared/url-utils/interface.ts +56 -0
  160. package/src/{core → shared}/url-utils/url-utils.html +4 -1
  161. package/src/{core → shared}/url-utils/url-utils.js +26 -23
  162. package/src/{core → shared}/url-utils/url-utils.spec.js +0 -8
  163. package/src/{core → shared}/url-utils/url-utils.test.js +1 -1
  164. package/src/shared/utils.js +47 -1
  165. package/utils/express.js +9 -1
  166. package/@types/core/task-tracker-factory.d.ts +0 -76
  167. package/@types/services/browser.d.ts +0 -101
  168. package/docs/static/typedoc/types/SwapInsertPosition.html +0 -2
  169. package/jsdoc.json +0 -22
  170. package/src/core/task-tracker-factory.js +0 -145
  171. package/src/services/browser.js +0 -212
  172. /package/src/{core → services}/location/location.md +0 -0
  173. /package/src/{core → services}/sce/sce.md +0 -0
  174. /package/src/{core → shared}/url-utils/url-utils.md +0 -0
@@ -1,4 +1,4 @@
1
- /* Version: 0.7.5 - July 12, 2025 01:24:05 */
1
+ /* Version: 0.7.8 - July 17, 2025 02:51:18 */
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
4
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
@@ -247,7 +247,7 @@
247
247
  * @returns {boolean}
248
248
  */
249
249
  function isScope(obj) {
250
- return obj && obj.$evalAsync && obj.$watch;
250
+ return obj && obj.$watch;
251
251
  }
252
252
 
253
253
  /**
@@ -1136,11 +1136,55 @@
1136
1136
  return Object.prototype.hasOwnProperty.call(obj, key);
1137
1137
  }
1138
1138
 
1139
+ /**
1140
+ * Wraps a function so it can only be called once.
1141
+ * Subsequent calls do nothing and return undefined.
1142
+ *
1143
+ * @param {Function} fn - The function to wrap.
1144
+ * @returns {Function} A new function that will call `fn` only once.
1145
+ */
1146
+ function callBackOnce(fn) {
1147
+ let called = false;
1148
+
1149
+ return function (...args) {
1150
+ if (!called) {
1151
+ called = true;
1152
+ return fn.apply(this, args);
1153
+ }
1154
+ };
1155
+ }
1156
+
1157
+ /**
1158
+ * Wraps a function so it will only be called starting from the second invocation.
1159
+ * The first call does nothing and returns undefined.
1160
+ *
1161
+ * @param {Function} fn - The function to wrap.
1162
+ * @returns {Function} A new function that will skip the first call.
1163
+ */
1164
+ function callBackAfterFirst(fn) {
1165
+ let calledOnce = false;
1166
+
1167
+ return function (...args) {
1168
+ if (calledOnce) {
1169
+ return fn.apply(this, args);
1170
+ }
1171
+ calledOnce = true;
1172
+ };
1173
+ }
1174
+
1175
+ /**
1176
+ * Delays execution for a specified number of milliseconds.
1177
+ *
1178
+ * @param {number} [t=0] - The number of milliseconds to wait. Defaults to 0.
1179
+ * @returns {Promise<void>} A promise that resolves after the delay.
1180
+ */
1181
+ function wait(t = 0) {
1182
+ return new Promise((resolve) => setTimeout(resolve, t));
1183
+ }
1184
+
1139
1185
  /**
1140
1186
  * Expando cache for adding properties to DOM nodes with JavaScript.
1141
1187
  * This used to be an Object in JQLite decorator, but swapped out for a Map
1142
- * for performance reasons and convenience methods. A proxy is available for
1143
- * additional logic handling.
1144
1188
  *
1145
1189
  * @type {Map<number, import('../interface.ts').ExpandoStore>}
1146
1190
  */
@@ -1693,6 +1737,16 @@
1693
1737
  }
1694
1738
  }
1695
1739
 
1740
+ /**
1741
+ * Returns the base href of the document.
1742
+ *
1743
+ * @returns {string} The base href.
1744
+ */
1745
+ function getBaseHref() {
1746
+ const href = document.querySelector("base")?.getAttribute("href");
1747
+ return href ? href.replace(/^(https?:)?\/\/[^/]*/, "") : "";
1748
+ }
1749
+
1696
1750
  /**
1697
1751
  * A helper list of tokens matching the standard injectables that come predefined in the core `ng` module.
1698
1752
  * These string tokens are commonly injected into services, directives, or components via `$inject`.
@@ -1725,7 +1779,7 @@
1725
1779
  $animate: "$animate",
1726
1780
  $animateCss: "$animateCss",
1727
1781
  $aria: "$aria",
1728
- $browser: "$browser",
1782
+ $compile: "$compile",
1729
1783
  $controller: "$controller",
1730
1784
  $eventBus: "$eventBus",
1731
1785
  $exceptionHandler: "$exceptionHandler",
@@ -1768,10 +1822,15 @@
1768
1822
  return services.map((x) => x + "Provider");
1769
1823
  }
1770
1824
 
1825
+ /** @private */
1771
1826
  const INJECTOR_LITERAL = "$injector";
1827
+ /** @private */
1772
1828
  const COMPILE_LITERAL = "$compileProvider";
1829
+ /** @private */
1773
1830
  const ANIMATION_LITERAL = "$animateProvider";
1831
+ /** @private */
1774
1832
  const FILTER_LITERAL = "$filterProvider";
1833
+ /** @private */
1775
1834
  const CONTROLLER_LITERAL = "$controllerProvider";
1776
1835
 
1777
1836
  /**
@@ -1838,11 +1897,7 @@
1838
1897
  * @returns {NgModule}
1839
1898
  */
1840
1899
  constant(name, object) {
1841
- this.invokeQueue.unshift([
1842
- $injectTokens.$provide,
1843
- "constant",
1844
- [name, object],
1845
- ]);
1900
+ this.invokeQueue.unshift([$injectTokens.$provide, "constant", [name, object]]);
1846
1901
  return this;
1847
1902
  }
1848
1903
 
@@ -1887,11 +1942,7 @@
1887
1942
  if (providerFunction && isFunction(providerFunction)) {
1888
1943
  providerFunction.$$moduleName = name;
1889
1944
  }
1890
- this.invokeQueue.push([
1891
- $injectTokens.$provide,
1892
- "factory",
1893
- [name, providerFunction],
1894
- ]);
1945
+ this.invokeQueue.push([$injectTokens.$provide, "factory", [name, providerFunction]]);
1895
1946
  return this;
1896
1947
  }
1897
1948
 
@@ -1904,11 +1955,7 @@
1904
1955
  if (serviceFunction && isFunction(serviceFunction)) {
1905
1956
  serviceFunction.$$moduleName = name;
1906
1957
  }
1907
- this.invokeQueue.push([
1908
- $injectTokens.$provide,
1909
- "service",
1910
- [name, serviceFunction],
1911
- ]);
1958
+ this.invokeQueue.push([$injectTokens.$provide, "service", [name, serviceFunction]]);
1912
1959
  return this;
1913
1960
  }
1914
1961
 
@@ -1921,11 +1968,7 @@
1921
1968
  if (providerType && isFunction(providerType)) {
1922
1969
  providerType.$$moduleName = name;
1923
1970
  }
1924
- this.invokeQueue.push([
1925
- $injectTokens.$provide,
1926
- "provider",
1927
- [name, providerType],
1928
- ]);
1971
+ this.invokeQueue.push([$injectTokens.$provide, "provider", [name, providerType]]);
1929
1972
  return this;
1930
1973
  }
1931
1974
 
@@ -1938,11 +1981,7 @@
1938
1981
  if (decorFn && isFunction(decorFn)) {
1939
1982
  decorFn.$$moduleName = name;
1940
1983
  }
1941
- this.configBlocks.push([
1942
- $injectTokens.$provide,
1943
- "decorator",
1944
- [name, decorFn],
1945
- ]);
1984
+ this.configBlocks.push([$injectTokens.$provide, "decorator", [name, decorFn]]);
1946
1985
  return this;
1947
1986
  }
1948
1987
 
@@ -2187,8 +2226,11 @@
2187
2226
  */
2188
2227
  constructor(providerInjector, strictDi) {
2189
2228
  super(strictDi);
2229
+
2230
+ /** @type {ProviderInjector} */
2190
2231
  this.providerInjector = providerInjector;
2191
- this.modules = this.providerInjector.modules;
2232
+ /** @type {Object.<string, import("./ng-module.js").NgModule>} */
2233
+ this.modules = providerInjector.modules;
2192
2234
  }
2193
2235
 
2194
2236
  /**
@@ -2305,9 +2347,6 @@
2305
2347
  const loadedModules = new Map(); // Keep track of loaded modules to avoid circular dependencies
2306
2348
 
2307
2349
  const providerCache = {
2308
- /**
2309
- * @type {import('../../interface.ts').Provider}
2310
- */
2311
2350
  $provide: {
2312
2351
  provider: supportObject(provider),
2313
2352
  factory: supportObject(factory),
@@ -2334,15 +2373,10 @@
2334
2373
  const runBlocks = loadModules(modulesToLoad);
2335
2374
  instanceInjector = protoInstanceInjector.get(INJECTOR_LITERAL);
2336
2375
 
2337
- runBlocks.forEach((fn) => {
2338
- if (fn) instanceInjector.invoke(fn);
2339
- });
2376
+ runBlocks.forEach((fn) => fn && instanceInjector.invoke(fn));
2340
2377
 
2341
- instanceInjector.loadNewModules = function (mods) {
2342
- loadModules(mods).forEach((fn) => {
2343
- if (fn) instanceInjector.invoke(fn);
2344
- });
2345
- };
2378
+ instanceInjector.loadNewModules = (mods) =>
2379
+ loadModules(mods).forEach((fn) => fn && instanceInjector.invoke(fn));
2346
2380
 
2347
2381
  return instanceInjector;
2348
2382
 
@@ -2471,7 +2505,7 @@
2471
2505
 
2472
2506
  try {
2473
2507
  if (isString(module)) {
2474
- /** @type {import('./ng-module').NgModule} */
2508
+ /** @type {import('./ng-module.js').NgModule} */
2475
2509
  const moduleFn = window["angular"].module(module);
2476
2510
  instanceInjector.modules[/** @type {string } */ (module)] = moduleFn;
2477
2511
  runBlocks = runBlocks
@@ -2537,7 +2571,6 @@
2537
2571
  }
2538
2572
 
2539
2573
  /**
2540
- *
2541
2574
  * @param {any} fn
2542
2575
  * @param {boolean} [strictDi]
2543
2576
  * @param {String} [name]
@@ -2576,10 +2609,6 @@
2576
2609
  return $inject;
2577
2610
  }
2578
2611
 
2579
- /**
2580
- * @param {function(string, any):any} delegate
2581
- * @returns {any}
2582
- */
2583
2612
  function supportObject(delegate) {
2584
2613
  return function (key, value) {
2585
2614
  if (isObject(key)) {
@@ -2995,32 +3024,25 @@
2995
3024
  }
2996
3025
  }
2997
3026
 
2998
- /**
2999
- * HTTP protocol
3000
- * @typedef {"http"|"https"} HttpProtocol
3001
- */
3002
-
3003
3027
  const urlParsingNode = document.createElement("a");
3004
3028
  const originUrl = urlResolve(window.location.href);
3005
3029
  let baseUrlParsingNode;
3006
3030
 
3007
3031
  urlParsingNode.href = "http://[::1]";
3008
3032
 
3033
+ /**
3034
+ * @param {import("./interface.js").ResolvableUrl} url
3035
+ * @return {import("./interface.js").ParsedUrl}
3036
+ */
3009
3037
  function urlResolve(url) {
3010
- if (!isString(url)) return url;
3038
+ if (!isString(url))
3039
+ return /** @type {import("./interface.js").ParsedUrl} */ (url);
3011
3040
 
3012
- const href = url;
3041
+ urlParsingNode.setAttribute("href", /** @type {string} */ (url));
3013
3042
 
3014
- urlParsingNode.setAttribute("href", href);
3015
-
3016
- let { hostname } = urlParsingNode;
3017
- // Support: IE 9-11 only, Edge 16-17 only (fixed in 18 Preview)
3018
- // IE/Edge don't wrap IPv6 addresses' hostnames in square brackets
3019
- // when parsed out of an anchor element.
3020
- const ipv6InBrackets = urlParsingNode.hostname === "[::1]";
3021
- if (!ipv6InBrackets && hostname.indexOf(":") > -1) {
3022
- hostname = `[${hostname}]`;
3023
- }
3043
+ const hostname = urlParsingNode.hostname.includes(":")
3044
+ ? `[${urlParsingNode.hostname}]`
3045
+ : urlParsingNode.hostname;
3024
3046
 
3025
3047
  return {
3026
3048
  href: urlParsingNode.href,
@@ -3045,7 +3067,7 @@
3045
3067
  * Parse a request URL and determine whether this is a same-origin request as the application
3046
3068
  * document.
3047
3069
  *
3048
- * @param {string|object} requestUrl The url of the request as a string that will be resolved
3070
+ * @param {import("./interface.js").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3049
3071
  * or a parsed URL object.
3050
3072
  * @returns {boolean} Whether the request is for the same origin as the application document.
3051
3073
  */
@@ -3059,7 +3081,7 @@
3059
3081
  * Note: The base URL is usually the same as the document location (`location.href`) but can
3060
3082
  * be overriden by using the `<base>` tag.
3061
3083
  *
3062
- * @param {string|object} requestUrl The url of the request as a string that will be resolved
3084
+ * @param {import("./interface.js").ResolvableUrl} requestUrl The url of the request as a string that will be resolved
3063
3085
  * or a parsed URL object.
3064
3086
  * @returns {boolean} Whether the URL is same-origin as the document base URL.
3065
3087
  */
@@ -3073,7 +3095,7 @@
3073
3095
  *
3074
3096
  * @param {string[]} trustedOriginUrls - A list of URLs (strings), whose origins are trusted.
3075
3097
  *
3076
- * @returns {Function} - A function that receives a URL (string or parsed URL object) and returns
3098
+ * @returns {(url: import("./interface.js").ResolvableUrl) => boolean } - A function that receives a URL (string or parsed URL object) and returns
3077
3099
  * whether it is of an allowed origin.
3078
3100
  */
3079
3101
  function urlIsAllowedOriginFactory(trustedOriginUrls) {
@@ -3086,7 +3108,7 @@
3086
3108
  * based on a list of trusted-origin URLs. The current location's origin is implicitly
3087
3109
  * trusted.
3088
3110
  *
3089
- * @param {string|Object} requestUrl - The URL to be checked (provided as a string that will be
3111
+ * @param {import("./interface.js").ResolvableUrl} requestUrl - The URL to be checked (provided as a string that will be
3090
3112
  * resolved or a parsed URL object).
3091
3113
  *
3092
3114
  * @returns {boolean} - Whether the specified URL is of an allowed origin.
@@ -3102,9 +3124,9 @@
3102
3124
  /**
3103
3125
  * Determine if two URLs share the same origin.
3104
3126
  *
3105
- * @param {string|Object} url1 - First URL to compare as a string or a normalized URL in the form of
3127
+ * @param {import("./interface.js").ResolvableUrl} url1 - First URL to compare as a string or a normalized URL in the form of
3106
3128
  * a dictionary object returned by `urlResolve()`.
3107
- * @param {string|object} url2 - Second URL to compare as a string or a normalized URL in the form
3129
+ * @param {import("./interface.js").ResolvableUrl} url2 - Second URL to compare as a string or a normalized URL in the form
3108
3130
  * of a dictionary object returned by `urlResolve()`.
3109
3131
  *
3110
3132
  * @returns {boolean} - True if both URLs have the same origin, and false otherwise.
@@ -3137,7 +3159,17 @@
3137
3159
  return baseUrlParsingNode.href;
3138
3160
  }
3139
3161
 
3140
- /** @typedef {import("../error-handler.ts").ErrorHandler } ErrorHandler */
3162
+ /**
3163
+ * Removes a trailing hash ('#') from the given URL if it exists.
3164
+ *
3165
+ * @param {string} url
3166
+ * @returns {string}
3167
+ */
3168
+ function trimEmptyHash(url) {
3169
+ return url.replace(/#$/, "");
3170
+ }
3171
+
3172
+ /** @typedef {import("../exception/interface.ts").Interface } ErrorHandler */
3141
3173
 
3142
3174
  const $sceMinErr = minErr("$sce");
3143
3175
 
@@ -3193,6 +3225,7 @@
3193
3225
  .replace(/\\\*/g, "[^:/.?&;]*");
3194
3226
  return new RegExp(`^${matcher}$`);
3195
3227
  }
3228
+
3196
3229
  if (isRegExp(matcher)) {
3197
3230
  // The only other type of matcher allowed is a Regexp.
3198
3231
  // Match entire URL / disallow partial matches.
@@ -3454,6 +3487,11 @@
3454
3487
  htmlSanitizer = $injector.get("$sanitize");
3455
3488
  }
3456
3489
 
3490
+ /**
3491
+ * @param {string|RegExp} matcher
3492
+ * @param {import("../../shared/url-utils/interface").ParsedUrl} parsedUrl
3493
+ * @return {boolean}
3494
+ */
3457
3495
  function matchUrl(matcher, parsedUrl) {
3458
3496
  if (matcher === "self") {
3459
3497
  return (
@@ -3461,7 +3499,7 @@
3461
3499
  );
3462
3500
  }
3463
3501
  // definitely a regex. See adjustMatchers()
3464
- return !!matcher.exec(parsedUrl.href);
3502
+ return !!(/** @type {RegExp} */ (matcher).exec(parsedUrl.href));
3465
3503
  }
3466
3504
 
3467
3505
  function isResourceUrlAllowedByPolicy(url) {
@@ -3966,9 +4004,13 @@
3966
4004
  * A collection of directives that allows creation of custom event handlers that are defined as
3967
4005
  * AngularTS expressions and are compiled and executed within the current scope.
3968
4006
  */
4007
+
4008
+ /**
4009
+ * @type {Record<string, import("../../interface.js").DirectiveFactory>}
4010
+ */
3969
4011
  const ngEventDirectives = {};
3970
4012
 
3971
- "click copy cut dblclick focus blur keydown keyup keypress load mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup paste submit touchstart touchend touchmove"
4013
+ "click copy cut dblclick focus blur keydown keyup load mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup paste submit touchstart touchend touchmove"
3972
4014
  .split(" ")
3973
4015
  .forEach((eventName) => {
3974
4016
  const directiveName = directiveNormalize(`ng-${eventName}`);
@@ -3977,7 +4019,7 @@
3977
4019
  "$exceptionHandler",
3978
4020
  /**
3979
4021
  * @param {import("../../core/parse/interface.ts").ParseService} $parse
3980
- * @param {import('../../core/exception-handler.js').ErrorHandler} $exceptionHandler
4022
+ * @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
3981
4023
  * @returns
3982
4024
  */
3983
4025
  ($parse, $exceptionHandler) => {
@@ -3994,7 +4036,7 @@
3994
4036
  /**
3995
4037
  *
3996
4038
  * @param {import("../../core/parse/interface.ts").ParseService} $parse
3997
- * @param {import('../../core/exception-handler.js').ErrorHandler} $exceptionHandler
4039
+ * @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
3998
4040
  * @param {string} directiveName
3999
4041
  * @param {string} eventName
4000
4042
  * @returns {import("../../interface.ts").Directive}
@@ -4035,7 +4077,7 @@
4035
4077
  /**
4036
4078
  * @param {import('../scope/scope.js').Scope} $rootScope
4037
4079
  * @param {*} $animate
4038
- * @param {import("../exception-handler.js").ErrorHandler} $exceptionHandler
4080
+ * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
4039
4081
  * @param {*} $sce
4040
4082
  * @param {import("../../shared/noderef.js").NodeRef} [nodeRef]
4041
4083
  * @param {Object} [attributesToCopy]
@@ -4633,7 +4675,7 @@
4633
4675
  "$exceptionHandler",
4634
4676
  /**
4635
4677
  * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
4636
- * @param {import('../exception-handler.js').ErrorHandler} $exceptionHandler
4678
+ * @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
4637
4679
  */
4638
4680
  function ($injector, $exceptionHandler) {
4639
4681
  const directives = [];
@@ -4961,7 +5003,7 @@
4961
5003
  /**
4962
5004
  * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
4963
5005
  * @param {*} $interpolate
4964
- * @param {import("../exception-handler.js").ErrorHandler} $exceptionHandler
5006
+ * @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
4965
5007
  * @param {*} $templateRequest
4966
5008
  * @param {import("../parse/interface.ts").ParseService} $parse
4967
5009
  * @param {*} $controller
@@ -8446,7 +8488,7 @@
8446
8488
 
8447
8489
  /**
8448
8490
  * @param {import('../../core/scope/scope.js').Scope} $scope
8449
- * @param {import('../../core/exception-handler.js').ErrorHandler} $exceptionHandler
8491
+ * @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
8450
8492
  * @param {import('../../core/compile/attributes.js').Attributes} $attr
8451
8493
  * @param {Element} $element
8452
8494
  * @param {import("../../core/parse/interface.ts").ParseService} $parse
@@ -9843,7 +9885,6 @@
9843
9885
  element,
9844
9886
  attr,
9845
9887
  ctrl,
9846
- $browser,
9847
9888
  $filter,
9848
9889
  $parse,
9849
9890
  ) {
@@ -10120,15 +10161,7 @@
10120
10161
  return (value - stepBase) % step === 0;
10121
10162
  }
10122
10163
 
10123
- function numberInputType(
10124
- scope,
10125
- element,
10126
- attr,
10127
- ctrl,
10128
- $browser,
10129
- $filter,
10130
- $parse,
10131
- ) {
10164
+ function numberInputType(scope, element, attr, ctrl, $filter, $parse) {
10132
10165
  badInputChecker(scope, element, attr, ctrl, "number");
10133
10166
  numberFormatterParser(ctrl);
10134
10167
  baseInputType(scope, element, attr, ctrl);
@@ -10444,15 +10477,7 @@
10444
10477
  return fallback;
10445
10478
  }
10446
10479
 
10447
- function checkboxInputType(
10448
- scope,
10449
- element,
10450
- attr,
10451
- ctrl,
10452
- $browser,
10453
- $filter,
10454
- $parse,
10455
- ) {
10480
+ function checkboxInputType(scope, element, attr, ctrl, $filter, $parse) {
10456
10481
  const trueValue = parseConstantExpr(
10457
10482
  $parse,
10458
10483
  scope,
@@ -10490,30 +10515,25 @@
10490
10515
  ctrl.$parsers.push((value) => (value ? trueValue : falseValue));
10491
10516
  }
10492
10517
 
10493
- /**
10494
- * @returns {import('../../interface.ts').Directive}
10495
- */
10496
- inputDirective.$inject = ["$browser", "$filter", "$parse"];
10518
+ inputDirective.$inject = ["$filter", "$parse"];
10497
10519
 
10498
10520
  /**
10499
- * @param {import('../../services/browser').Browser} $browser
10500
10521
  * @param {*} $filter
10501
10522
  * @param {*} $parse
10502
- * @returns
10523
+ * @returns {import('../../interface.ts').Directive}
10503
10524
  */
10504
- function inputDirective($browser, $filter, $parse) {
10525
+ function inputDirective($filter, $parse) {
10505
10526
  return {
10506
10527
  restrict: "E",
10507
10528
  require: ["?ngModel"],
10508
10529
  link: {
10509
10530
  pre(scope, element, attr, ctrls) {
10510
10531
  if (ctrls[0]) {
10511
- (inputType[lowercase(attr.type)] || inputType.text)(
10532
+ (inputType[lowercase(attr["type"])] || inputType.text)(
10512
10533
  scope,
10513
10534
  element,
10514
10535
  attr,
10515
10536
  ctrls[0],
10516
- $browser,
10517
10537
  $filter,
10518
10538
  $parse,
10519
10539
  );
@@ -11222,9 +11242,15 @@
11222
11242
  * @param {import('../../core/compile/attributes.js').Attributes} attr
11223
11243
  */
11224
11244
  link(scope, element, attr) {
11225
- scope.$watch(attr["ngBind"], (value) => {
11226
- element.textContent = stringify$1(isProxy(value) ? value.$target : value);
11227
- });
11245
+ scope.$watch(
11246
+ attr["ngBind"],
11247
+ (value) => {
11248
+ element.textContent = stringify$1(
11249
+ isProxy(value) ? value.$target : value,
11250
+ );
11251
+ },
11252
+ isDefined(attr["lazy"]),
11253
+ );
11228
11254
  },
11229
11255
  };
11230
11256
  }
@@ -11626,7 +11652,7 @@
11626
11652
  * @param {*} $templateRequest
11627
11653
  * @param {import("../../services/anchor-scroll.js").AnchorScrollFunction} $anchorScroll
11628
11654
  * @param {*} $animate
11629
- * @param {import('../../core/error-handler.js').ErrorHandler} $exceptionHandler
11655
+ * @param {import('../../services/exception/interface.ts').Interface} $exceptionHandler
11630
11656
  * @returns {import('../../interface.js').Directive}
11631
11657
  */
11632
11658
  function ngIncludeDirective(
@@ -11745,7 +11771,7 @@
11745
11771
  // We need this directive so that the element content is already filled when
11746
11772
  // the link function of another directive on the same element as ngInclude
11747
11773
  // is called.
11748
- ngIncludeFillContentDirective.$inject = ["$compile"];
11774
+ ngIncludeFillContentDirective.$inject = [$injectTokens.$compile];
11749
11775
 
11750
11776
  /**
11751
11777
  * @param {import("../../core/compile/compile.js").CompileFn} $compile
@@ -11951,7 +11977,7 @@
11951
11977
  transclude: "element",
11952
11978
  priority: 1000,
11953
11979
  terminal: true,
11954
- compile: (_$element, $attr) => {
11980
+ compile: ($element, $attr) => {
11955
11981
  const expression = $attr["ngRepeat"];
11956
11982
  const hasAnimate = !!$attr["animate"];
11957
11983
 
@@ -11997,6 +12023,14 @@
11997
12023
  );
11998
12024
  }
11999
12025
 
12026
+ const swap = callBackOnce(() => {
12027
+ if (isDefined($attr["lazy"]) && isDefined($attr["swap"])) {
12028
+ document
12029
+ .querySelectorAll($attr["swap"])
12030
+ .forEach((x) => removeElement(x));
12031
+ }
12032
+ });
12033
+
12000
12034
  return function ngRepeatLink($scope, $element, $attr, ctrl, $transclude) {
12001
12035
  // Store a list of elements from previous run. This is a hash where key is the item from the
12002
12036
  // iterator, and the value is objects with following properties.
@@ -12008,174 +12042,181 @@
12008
12042
  // hasOwnProperty.
12009
12043
  let lastBlockMap = Object.create(null);
12010
12044
  // watch props
12011
- $scope.$watch(rhs, (collection) => {
12012
- let index,
12013
- length,
12014
- previousNode = $element, // node that cloned nodes should be inserted after
12015
- // initialized to the comment node anchor
12016
- nextNode;
12017
- const // Same as lastBlockMap but it has the current state. It will become the
12018
- // lastBlockMap on the next iteration.
12019
- nextBlockMap = Object.create(null);
12020
- let collectionLength,
12021
- key,
12022
- value, // key/value of iteration
12023
- trackById,
12024
- trackByIdFn,
12025
- collectionKeys,
12026
- block, // last object information {scope, element, id}
12027
- nextBlockOrder,
12028
- elementsToRemove;
12029
-
12030
- if (aliasAs) {
12031
- $scope[aliasAs] = collection;
12032
- }
12033
-
12034
- if (isArrayLike(collection)) {
12035
- collectionKeys = collection;
12036
- trackByIdFn = trackByIdArrayFn;
12037
- } else {
12038
- trackByIdFn = trackByIdObjFn;
12039
- // if object, extract keys, in enumeration order, unsorted
12040
- collectionKeys = [];
12041
- for (const itemKey in collection) {
12042
- if (hasOwn(collection, itemKey) && itemKey.charAt(0) !== "$") {
12043
- collectionKeys.push(itemKey);
12044
- }
12045
+ $scope.$watch(
12046
+ rhs,
12047
+ (collection) => {
12048
+ swap();
12049
+ let index,
12050
+ length,
12051
+ previousNode = $element, // node that cloned nodes should be inserted after
12052
+ // initialized to the comment node anchor
12053
+ nextNode;
12054
+ const // Same as lastBlockMap but it has the current state. It will become the
12055
+ // lastBlockMap on the next iteration.
12056
+ nextBlockMap = Object.create(null);
12057
+ let collectionLength,
12058
+ key,
12059
+ value, // key/value of iteration
12060
+ trackById,
12061
+ trackByIdFn,
12062
+ collectionKeys,
12063
+ block, // last object information {scope, element, id}
12064
+ nextBlockOrder,
12065
+ elementsToRemove;
12066
+
12067
+ if (aliasAs) {
12068
+ $scope[aliasAs] = collection;
12045
12069
  }
12046
- }
12047
12070
 
12048
- collectionLength = collectionKeys.length;
12049
- nextBlockOrder = new Array(collectionLength);
12050
-
12051
- // locate existing items
12052
- for (index = 0; index < collectionLength; index++) {
12053
- key = collection === collectionKeys ? index : collectionKeys[index];
12054
- value = collection[key];
12055
- trackById = trackByIdFn($scope, key, value);
12056
- if (lastBlockMap[trackById]) {
12057
- // found previously seen block
12058
- block = lastBlockMap[trackById];
12059
- delete lastBlockMap[trackById];
12060
- nextBlockMap[trackById] = block;
12061
- nextBlockOrder[index] = block;
12062
- } else if (nextBlockMap[trackById]) {
12063
- // if collision detected. restore lastBlockMap and throw an error
12064
- Object.values(nextBlockOrder).forEach((block) => {
12065
- if (block && block.scope) lastBlockMap[block.id] = block;
12066
- });
12067
- throw ngRepeatMinErr(
12068
- "dupes",
12069
- "Duplicates keys in a repeater are not allowed. Repeater: {0}, Duplicate key: {1} for value: {2}",
12070
- expression,
12071
- trackById,
12072
- value,
12073
- );
12071
+ if (isArrayLike(collection)) {
12072
+ collectionKeys = collection;
12073
+ trackByIdFn = trackByIdArrayFn;
12074
12074
  } else {
12075
- // new never before seen block
12076
- nextBlockOrder[index] = {
12077
- id: trackById,
12078
- scope: undefined,
12079
- clone: undefined,
12080
- };
12081
- nextBlockMap[trackById] = true;
12075
+ trackByIdFn = trackByIdObjFn;
12076
+ // if object, extract keys, in enumeration order, unsorted
12077
+ collectionKeys = [];
12078
+ for (const itemKey in collection) {
12079
+ if (hasOwn(collection, itemKey) && itemKey.charAt(0) !== "$") {
12080
+ collectionKeys.push(itemKey);
12081
+ }
12082
+ }
12082
12083
  }
12083
- }
12084
12084
 
12085
- // remove leftover items
12086
- for (let blockKey in lastBlockMap) {
12087
- block = lastBlockMap[blockKey];
12088
- elementsToRemove = block.clone;
12089
- if (hasAnimate) {
12090
- $animate.leave(elementsToRemove);
12091
- } else {
12092
- elementsToRemove.remove();
12085
+ collectionLength = collectionKeys.length;
12086
+ nextBlockOrder = new Array(collectionLength);
12087
+
12088
+ // locate existing items
12089
+ for (index = 0; index < collectionLength; index++) {
12090
+ key =
12091
+ collection === collectionKeys ? index : collectionKeys[index];
12092
+ value = collection[key];
12093
+ trackById = trackByIdFn($scope, key, value);
12094
+ if (lastBlockMap[trackById]) {
12095
+ // found previously seen block
12096
+ block = lastBlockMap[trackById];
12097
+ delete lastBlockMap[trackById];
12098
+ nextBlockMap[trackById] = block;
12099
+ nextBlockOrder[index] = block;
12100
+ } else if (nextBlockMap[trackById]) {
12101
+ // if collision detected. restore lastBlockMap and throw an error
12102
+ Object.values(nextBlockOrder).forEach((block) => {
12103
+ if (block && block.scope) lastBlockMap[block.id] = block;
12104
+ });
12105
+ throw ngRepeatMinErr(
12106
+ "dupes",
12107
+ "Duplicates keys in a repeater are not allowed. Repeater: {0}, Duplicate key: {1} for value: {2}",
12108
+ expression,
12109
+ trackById,
12110
+ value,
12111
+ );
12112
+ } else {
12113
+ // new never before seen block
12114
+ nextBlockOrder[index] = {
12115
+ id: trackById,
12116
+ scope: undefined,
12117
+ clone: undefined,
12118
+ };
12119
+ nextBlockMap[trackById] = true;
12120
+ }
12093
12121
  }
12094
- if (elementsToRemove.parentNode) {
12095
- // if the element was not removed yet because of pending animation, mark it as deleted
12096
- // so that we can ignore it later
12097
- for (
12098
- index = 0, length = elementsToRemove.length;
12099
- index < length;
12100
- index++
12101
- ) {
12102
- elementsToRemove[index][NG_REMOVED] = true;
12122
+
12123
+ // remove leftover items
12124
+ for (let blockKey in lastBlockMap) {
12125
+ block = lastBlockMap[blockKey];
12126
+ elementsToRemove = block.clone;
12127
+ if (hasAnimate) {
12128
+ $animate.leave(elementsToRemove);
12129
+ } else {
12130
+ elementsToRemove.remove();
12103
12131
  }
12132
+ if (elementsToRemove.parentNode) {
12133
+ // if the element was not removed yet because of pending animation, mark it as deleted
12134
+ // so that we can ignore it later
12135
+ for (
12136
+ index = 0, length = elementsToRemove.length;
12137
+ index < length;
12138
+ index++
12139
+ ) {
12140
+ elementsToRemove[index][NG_REMOVED] = true;
12141
+ }
12142
+ }
12143
+ block.scope.$destroy();
12104
12144
  }
12105
- block.scope.$destroy();
12106
- }
12107
12145
 
12108
- for (index = 0; index < collectionLength; index++) {
12109
- key = collection === collectionKeys ? index : collectionKeys[index];
12110
- value = collection[key];
12111
- block = nextBlockOrder[index];
12146
+ for (index = 0; index < collectionLength; index++) {
12147
+ key =
12148
+ collection === collectionKeys ? index : collectionKeys[index];
12149
+ value = collection[key];
12150
+ block = nextBlockOrder[index];
12112
12151
 
12113
- if (block.scope) {
12114
- // if we have already seen this object, then we need to reuse the
12115
- // associated scope/element
12152
+ if (block.scope) {
12153
+ // if we have already seen this object, then we need to reuse the
12154
+ // associated scope/element
12116
12155
 
12117
- nextNode = previousNode;
12156
+ nextNode = previousNode;
12118
12157
 
12119
- // skip nodes that are already pending removal via leave animation
12120
- do {
12121
- nextNode = nextNode.nextSibling;
12122
- } while (nextNode && nextNode[NG_REMOVED]);
12158
+ // skip nodes that are already pending removal via leave animation
12159
+ do {
12160
+ nextNode = nextNode.nextSibling;
12161
+ } while (nextNode && nextNode[NG_REMOVED]);
12123
12162
 
12124
- if (getBlockStart(block) !== nextNode) {
12125
- // existing item which got moved
12126
- $animate.move(getBlockNodes(block.clone), null, previousNode);
12127
- }
12128
- previousNode = getBlockEnd(block);
12129
- updateScope(
12130
- block.scope,
12131
- index,
12132
- valueIdentifier,
12133
- value,
12134
- keyIdentifier,
12135
- key,
12136
- collectionLength,
12137
- );
12138
- } else {
12139
- // new item which we don't know about
12140
- $transclude(
12141
- /**
12142
- * Clone attach function
12143
- * @param {Array<NodeList>} clone
12144
- * @param {import("../../core/scope/scope.js").Scope} scope
12145
- */
12146
-
12147
- (clone, scope) => {
12148
- block.scope = scope;
12149
- const endNode = clone;
12150
- if (hasAnimate) {
12151
- $animate.enter(clone, null, previousNode);
12152
- } else {
12153
- // @ts-ignore
12154
- previousNode.after(clone);
12155
- }
12163
+ if (getBlockStart(block) !== nextNode) {
12164
+ // existing item which got moved
12165
+ $animate.move(getBlockNodes(block.clone), null, previousNode);
12166
+ }
12167
+ previousNode = getBlockEnd(block);
12168
+ updateScope(
12169
+ block.scope,
12170
+ index,
12171
+ valueIdentifier,
12172
+ value,
12173
+ keyIdentifier,
12174
+ key,
12175
+ collectionLength,
12176
+ );
12177
+ } else {
12178
+ // new item which we don't know about
12179
+ $transclude(
12180
+ /**
12181
+ * Clone attach function
12182
+ * @param {Array<NodeList>} clone
12183
+ * @param {import("../../core/scope/scope.js").Scope} scope
12184
+ */
12156
12185
 
12157
- // @ts-ignore
12158
- previousNode = endNode;
12159
- // Note: We only need the first/last node of the cloned nodes.
12160
- // However, we need to keep the reference to the dom wrapper as it might be changed later
12161
- // by a directive with templateUrl when its template arrives.
12162
- block.clone = clone;
12163
- nextBlockMap[block.id] = block;
12164
- updateScope(
12165
- block.scope,
12166
- index,
12167
- valueIdentifier,
12168
- value,
12169
- keyIdentifier,
12170
- key,
12171
- collectionLength,
12172
- );
12173
- },
12174
- );
12186
+ (clone, scope) => {
12187
+ block.scope = scope;
12188
+ const endNode = clone;
12189
+ if (hasAnimate) {
12190
+ $animate.enter(clone, null, previousNode);
12191
+ } else {
12192
+ // @ts-ignore
12193
+ previousNode.after(clone);
12194
+ }
12195
+
12196
+ // @ts-ignore
12197
+ previousNode = endNode;
12198
+ // Note: We only need the first/last node of the cloned nodes.
12199
+ // However, we need to keep the reference to the dom wrapper as it might be changed later
12200
+ // by a directive with templateUrl when its template arrives.
12201
+ block.clone = clone;
12202
+ nextBlockMap[block.id] = block;
12203
+ updateScope(
12204
+ block.scope,
12205
+ index,
12206
+ valueIdentifier,
12207
+ value,
12208
+ keyIdentifier,
12209
+ key,
12210
+ collectionLength,
12211
+ );
12212
+ },
12213
+ );
12214
+ }
12175
12215
  }
12176
- }
12177
- lastBlockMap = nextBlockMap;
12178
- });
12216
+ lastBlockMap = nextBlockMap;
12217
+ },
12218
+ isDefined($attr["lazy"]),
12219
+ );
12179
12220
  };
12180
12221
  },
12181
12222
  };
@@ -12212,6 +12253,7 @@
12212
12253
  ngSwitchDirective.$inject = ["$animate"];
12213
12254
 
12214
12255
  /**
12256
+ * @param {*} $animate
12215
12257
  * @returns {import('../../interface.ts').Directive}
12216
12258
  */
12217
12259
  function ngSwitchDirective($animate) {
@@ -12359,525 +12401,515 @@
12359
12401
  // 8: collection expression
12360
12402
  // 9: track by expression
12361
12403
 
12362
- const ngOptionsDirective = [
12363
- "$compile",
12364
- "$parse",
12404
+ ngOptionsDirective.$inject = ["$compile", "$parse"];
12405
+ /**
12406
+ *
12407
+ * @param {import("../../core/compile/compile.js").CompileFn} $compile
12408
+ * @param {import("../../core/parse/interface.ts").ParseService} $parse
12409
+ * @returns {import("../../interface.ts").Directive}
12410
+ */
12411
+ function ngOptionsDirective($compile, $parse) {
12365
12412
  /**
12366
- *
12367
- * @param {import("../../core/compile/compile.js").CompileFn} $compile
12368
- * @param {import("../../core/parse/interface.ts").ParseService} $parse
12413
+ * @param {import('../../interface.ts').Expression} optionsExp
12414
+ * @param {HTMLSelectElement} selectElement
12415
+ * @param {import('../../core/scope/scope.js').Scope} scope
12369
12416
  * @returns
12370
12417
  */
12371
- function ($compile, $parse) {
12372
- /**
12373
- * @param {import('../../interface.ts').Expression} optionsExp
12374
- * @param {HTMLSelectElement} selectElement
12375
- * @param {import('../../core/scope/scope.js').Scope} scope
12376
- * @returns
12377
- */
12378
- function parseOptionsExpression(optionsExp, selectElement, scope) {
12379
- const match = optionsExp.match(NG_OPTIONS_REGEXP);
12380
- if (!match) {
12381
- throw ngOptionsMinErr(
12382
- "iexp",
12383
- "Expected expression in form of " +
12384
- "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
12385
- " but got '{0}'. Element: {1}",
12386
- optionsExp,
12387
- startingTag(selectElement),
12388
- );
12389
- }
12390
- // Extract the parts from the ngOptions expression
12391
-
12392
- // The variable name for the value of the item in the collection
12393
- const valueName = match[5] || match[7];
12394
- // The variable name for the key of the item in the collection
12395
- const keyName = match[6];
12396
-
12397
- // An expression that generates the viewValue for an option if there is a label expression
12398
- const selectAs = / as /.test(match[0]) && match[1];
12399
- // An expression that is used to track the id of each object in the options collection
12400
- const trackBy = match[9];
12401
- // An expression that generates the viewValue for an option if there is no label expression
12402
- const valueFn = $parse(match[2] ? match[1] : valueName);
12403
- const selectAsFn = selectAs && $parse(selectAs);
12404
- const viewValueFn = selectAsFn || valueFn;
12405
- const trackByFn = trackBy && $parse(trackBy);
12406
-
12407
- // Get the value by which we are going to track the option
12408
- // if we have a trackFn then use that (passing scope and locals)
12409
- // otherwise just hash the given viewValue
12410
- const getTrackByValueFn = trackBy
12411
- ? function (value, locals) {
12412
- return trackByFn(scope, locals);
12413
- }
12414
- : function getHashOfValue(value) {
12415
- return hashKey(value);
12416
- };
12417
- const getTrackByValue = function (value, key) {
12418
- return getTrackByValueFn(value, getLocals(value, key));
12419
- };
12418
+ function parseOptionsExpression(optionsExp, selectElement, scope) {
12419
+ const match = optionsExp.match(NG_OPTIONS_REGEXP);
12420
+ if (!match) {
12421
+ throw ngOptionsMinErr(
12422
+ "iexp",
12423
+ "Expected expression in form of " +
12424
+ "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
12425
+ " but got '{0}'. Element: {1}",
12426
+ optionsExp,
12427
+ startingTag(selectElement),
12428
+ );
12429
+ }
12430
+ // Extract the parts from the ngOptions expression
12431
+
12432
+ // The variable name for the value of the item in the collection
12433
+ const valueName = match[5] || match[7];
12434
+ // The variable name for the key of the item in the collection
12435
+ const keyName = match[6];
12436
+
12437
+ // An expression that generates the viewValue for an option if there is a label expression
12438
+ const selectAs = / as /.test(match[0]) && match[1];
12439
+ // An expression that is used to track the id of each object in the options collection
12440
+ const trackBy = match[9];
12441
+ // An expression that generates the viewValue for an option if there is no label expression
12442
+ const valueFn = $parse(match[2] ? match[1] : valueName);
12443
+ const selectAsFn = selectAs && $parse(selectAs);
12444
+ const viewValueFn = selectAsFn || valueFn;
12445
+ const trackByFn = trackBy && $parse(trackBy);
12446
+
12447
+ // Get the value by which we are going to track the option
12448
+ // if we have a trackFn then use that (passing scope and locals)
12449
+ // otherwise just hash the given viewValue
12450
+ const getTrackByValueFn = trackBy
12451
+ ? function (value, locals) {
12452
+ return trackByFn(scope, locals);
12453
+ }
12454
+ : function getHashOfValue(value) {
12455
+ return hashKey(value);
12456
+ };
12457
+ const getTrackByValue = function (value, key) {
12458
+ return getTrackByValueFn(value, getLocals(value, key));
12459
+ };
12420
12460
 
12421
- const displayFn = $parse(match[2] || match[1]);
12422
- const groupByFn = $parse(match[3] || "");
12423
- const disableWhenFn = $parse(match[4] || "");
12424
- const valuesFn = $parse(match[8]);
12425
-
12426
- const locals = {};
12427
- let getLocals = keyName
12428
- ? function (value, key) {
12429
- locals[keyName] = key;
12430
- locals[valueName] = value;
12431
- return locals;
12432
- }
12433
- : function (value) {
12434
- locals[valueName] = value;
12435
- return locals;
12436
- };
12461
+ const displayFn = $parse(match[2] || match[1]);
12462
+ const groupByFn = $parse(match[3] || "");
12463
+ const disableWhenFn = $parse(match[4] || "");
12464
+ const valuesFn = $parse(match[8]);
12465
+
12466
+ const locals = {};
12467
+ let getLocals = keyName
12468
+ ? function (value, key) {
12469
+ locals[keyName] = key;
12470
+ locals[valueName] = value;
12471
+ return locals;
12472
+ }
12473
+ : function (value) {
12474
+ locals[valueName] = value;
12475
+ return locals;
12476
+ };
12437
12477
 
12438
- class Option {
12439
- constructor(selectValue, viewValue, label, group, disabled) {
12440
- this.selectValue = selectValue;
12441
- this.viewValue = viewValue;
12442
- this.label = label;
12443
- this.group = group;
12444
- this.disabled = disabled;
12445
- }
12478
+ class Option {
12479
+ constructor(selectValue, viewValue, label, group, disabled) {
12480
+ this.selectValue = selectValue;
12481
+ this.viewValue = viewValue;
12482
+ this.label = label;
12483
+ this.group = group;
12484
+ this.disabled = disabled;
12446
12485
  }
12486
+ }
12447
12487
 
12448
- function getOptionValuesKeys(optionValues) {
12449
- let optionValuesKeys;
12488
+ function getOptionValuesKeys(optionValues) {
12489
+ let optionValuesKeys;
12450
12490
 
12451
- if (!keyName && isArrayLike(optionValues)) {
12452
- optionValuesKeys = optionValues;
12453
- } else {
12454
- // if object, extract keys, in enumeration order, unsorted
12455
- optionValuesKeys = [];
12456
- for (const itemKey in optionValues) {
12457
- if (hasOwn(optionValues, itemKey) && itemKey.charAt(0) !== "$") {
12458
- optionValuesKeys.push(itemKey);
12459
- }
12491
+ if (!keyName && isArrayLike(optionValues)) {
12492
+ optionValuesKeys = optionValues;
12493
+ } else {
12494
+ // if object, extract keys, in enumeration order, unsorted
12495
+ optionValuesKeys = [];
12496
+ for (const itemKey in optionValues) {
12497
+ if (hasOwn(optionValues, itemKey) && itemKey.charAt(0) !== "$") {
12498
+ optionValuesKeys.push(itemKey);
12460
12499
  }
12461
12500
  }
12462
- return optionValuesKeys;
12463
12501
  }
12502
+ return optionValuesKeys;
12503
+ }
12464
12504
 
12465
- return {
12466
- trackBy,
12467
- getTrackByValue,
12468
- getWatchables: $parse(valuesFn, (optionValues) => {
12469
- // Create a collection of things that we would like to watch (watchedArray)
12470
- // so that they can all be watched using a single $watchCollection
12471
- // that only runs the handler once if anything changes
12472
- const watchedArray = [];
12473
- optionValues = optionValues || [];
12474
-
12475
- const optionValuesKeys = getOptionValuesKeys(optionValues);
12476
- const optionValuesLength = optionValuesKeys.length;
12477
- for (let index = 0; index < optionValuesLength; index++) {
12478
- const key =
12479
- optionValues === optionValuesKeys
12480
- ? index
12481
- : optionValuesKeys[index];
12482
- const value = optionValues[key];
12483
-
12484
- const locals = getLocals(value, key);
12485
- const selectValue = getTrackByValueFn(value, locals);
12486
- watchedArray.push(selectValue);
12487
-
12488
- // Only need to watch the displayFn if there is a specific label expression
12489
- if (match[2] || match[1]) {
12490
- const label = displayFn(scope, locals);
12491
- watchedArray.push(label);
12492
- }
12493
-
12494
- // Only need to watch the disableWhenFn if there is a specific disable expression
12495
- if (match[4]) {
12496
- const disableWhen = disableWhenFn(scope, locals);
12497
- watchedArray.push(disableWhen);
12498
- }
12499
- }
12500
- return watchedArray;
12501
- }),
12502
-
12503
- getOptions() {
12504
- /** @type {Option[]} */
12505
- const optionItems = [];
12506
- /** @type {Object.<string, Option>} */
12507
- const selectValueMap = {};
12508
-
12509
- // The option values were already computed in the `getWatchables` fn,
12510
- // which must have been called to trigger `getOptions`
12511
- const optionValues = valuesFn(scope) || [];
12512
- const optionValuesKeys = getOptionValuesKeys(optionValues);
12513
- const optionValuesLength = optionValuesKeys.length;
12514
-
12515
- for (let index = 0; index < optionValuesLength; index++) {
12516
- const key =
12517
- optionValues === optionValuesKeys
12518
- ? index
12519
- : optionValuesKeys[index];
12520
- const value = optionValues[key];
12521
- const locals = getLocals(value, key);
12522
- const viewValue = viewValueFn(scope, locals);
12523
- const selectValue = getTrackByValueFn(viewValue, locals);
12505
+ return {
12506
+ trackBy,
12507
+ getTrackByValue,
12508
+ getWatchables: $parse(valuesFn, (optionValues) => {
12509
+ // Create a collection of things that we would like to watch (watchedArray)
12510
+ // so that they can all be watched using a single $watchCollection
12511
+ // that only runs the handler once if anything changes
12512
+ const watchedArray = [];
12513
+ optionValues = optionValues || [];
12514
+
12515
+ const optionValuesKeys = getOptionValuesKeys(optionValues);
12516
+ const optionValuesLength = optionValuesKeys.length;
12517
+ for (let index = 0; index < optionValuesLength; index++) {
12518
+ const key =
12519
+ optionValues === optionValuesKeys ? index : optionValuesKeys[index];
12520
+ const value = optionValues[key];
12521
+
12522
+ const locals = getLocals(value, key);
12523
+ const selectValue = getTrackByValueFn(value, locals);
12524
+ watchedArray.push(selectValue);
12525
+
12526
+ // Only need to watch the displayFn if there is a specific label expression
12527
+ if (match[2] || match[1]) {
12524
12528
  const label = displayFn(scope, locals);
12525
- const group = groupByFn(scope, locals);
12526
- const disabled = disableWhenFn(scope, locals);
12527
- const optionItem = new Option(
12528
- selectValue,
12529
- viewValue,
12530
- label,
12531
- group,
12532
- disabled,
12533
- );
12529
+ watchedArray.push(label);
12530
+ }
12531
+
12532
+ // Only need to watch the disableWhenFn if there is a specific disable expression
12533
+ if (match[4]) {
12534
+ const disableWhen = disableWhenFn(scope, locals);
12535
+ watchedArray.push(disableWhen);
12536
+ }
12537
+ }
12538
+ return watchedArray;
12539
+ }),
12540
+
12541
+ getOptions() {
12542
+ /** @type {Option[]} */
12543
+ const optionItems = [];
12544
+ /** @type {Object.<string, Option>} */
12545
+ const selectValueMap = {};
12546
+
12547
+ // The option values were already computed in the `getWatchables` fn,
12548
+ // which must have been called to trigger `getOptions`
12549
+ const optionValues = valuesFn(scope) || [];
12550
+ const optionValuesKeys = getOptionValuesKeys(optionValues);
12551
+ const optionValuesLength = optionValuesKeys.length;
12552
+
12553
+ for (let index = 0; index < optionValuesLength; index++) {
12554
+ const key =
12555
+ optionValues === optionValuesKeys ? index : optionValuesKeys[index];
12556
+ const value = optionValues[key];
12557
+ const locals = getLocals(value, key);
12558
+ const viewValue = viewValueFn(scope, locals);
12559
+ const selectValue = getTrackByValueFn(viewValue, locals);
12560
+ const label = displayFn(scope, locals);
12561
+ const group = groupByFn(scope, locals);
12562
+ const disabled = disableWhenFn(scope, locals);
12563
+ const optionItem = new Option(
12564
+ selectValue,
12565
+ viewValue,
12566
+ label,
12567
+ group,
12568
+ disabled,
12569
+ );
12534
12570
 
12535
- optionItems.push(optionItem);
12536
- selectValueMap[selectValue] = optionItem;
12537
- }
12571
+ optionItems.push(optionItem);
12572
+ selectValueMap[selectValue] = optionItem;
12573
+ }
12538
12574
 
12539
- return {
12540
- items: optionItems,
12541
- selectValueMap,
12542
- getOptionFromViewValue(value) {
12543
- return selectValueMap[getTrackByValue(value)];
12544
- },
12545
- getViewValueFromOption(option) {
12546
- // If the viewValue could be an object that may be mutated by the application,
12547
- // we need to make a copy and not return the reference to the value on the option.
12548
- return trackBy
12549
- ? structuredClone(option.viewValue)
12550
- : option.viewValue;
12551
- },
12552
- };
12553
- },
12554
- };
12555
- }
12575
+ return {
12576
+ items: optionItems,
12577
+ selectValueMap,
12578
+ getOptionFromViewValue(value) {
12579
+ return selectValueMap[getTrackByValue(value)];
12580
+ },
12581
+ getViewValueFromOption(option) {
12582
+ // If the viewValue could be an object that may be mutated by the application,
12583
+ // we need to make a copy and not return the reference to the value on the option.
12584
+ return trackBy
12585
+ ? structuredClone(option.viewValue)
12586
+ : option.viewValue;
12587
+ },
12588
+ };
12589
+ },
12590
+ };
12591
+ }
12556
12592
 
12557
- /**
12558
- *
12559
- * @param {import("../../core/scope/scope.js").Scope} scope
12560
- * @param {HTMLSelectElement} selectElement
12561
- * @param {import("../../core/compile/attributes.js").Attributes} attr
12562
- * @param {*} ctrls
12563
- */
12564
- function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
12565
- const selectCtrl = ctrls[0];
12566
- const ngModelCtrl = ctrls[1];
12567
- const multiple = attr["multiple"];
12568
-
12569
- // The emptyOption allows the application developer to provide their own custom "empty"
12570
- // option when the viewValue does not match any of the option values.
12571
- for (
12572
- let i = 0, children = selectElement.childNodes, ii = children.length;
12573
- i < ii;
12574
- i++
12575
- ) {
12576
- if (/** @type {HTMLOptionElement} */ (children[i]).value === "") {
12577
- selectCtrl.hasEmptyOption = true;
12578
- selectCtrl.emptyOption = children[i];
12579
- break;
12580
- }
12593
+ /**
12594
+ *
12595
+ * @param {import("../../core/scope/scope.js").Scope} scope
12596
+ * @param {HTMLSelectElement} selectElement
12597
+ * @param {import("../../core/compile/attributes.js").Attributes} attr
12598
+ * @param {*} ctrls
12599
+ */
12600
+ function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
12601
+ const selectCtrl = ctrls[0];
12602
+ const ngModelCtrl = ctrls[1];
12603
+ const multiple = attr["multiple"];
12604
+
12605
+ // The emptyOption allows the application developer to provide their own custom "empty"
12606
+ // option when the viewValue does not match any of the option values.
12607
+ for (
12608
+ let i = 0, children = selectElement.childNodes, ii = children.length;
12609
+ i < ii;
12610
+ i++
12611
+ ) {
12612
+ if (/** @type {HTMLOptionElement} */ (children[i]).value === "") {
12613
+ selectCtrl.hasEmptyOption = true;
12614
+ selectCtrl.emptyOption = children[i];
12615
+ break;
12581
12616
  }
12617
+ }
12582
12618
 
12583
- // The empty option will be compiled and rendered before we first generate the options
12584
- emptyElement(selectElement);
12619
+ // The empty option will be compiled and rendered before we first generate the options
12620
+ emptyElement(selectElement);
12585
12621
 
12586
- const providedEmptyOption = !!selectCtrl.emptyOption;
12622
+ const providedEmptyOption = !!selectCtrl.emptyOption;
12587
12623
 
12588
- const unknownOption = optionTemplate.cloneNode(false);
12589
- // TODO double check
12590
- unknownOption.nodeValue = "?";
12624
+ const unknownOption = optionTemplate.cloneNode(false);
12625
+ // TODO double check
12626
+ unknownOption.nodeValue = "?";
12591
12627
 
12592
- let options;
12593
- const ngOptions = parseOptionsExpression(
12594
- attr["ngOptions"],
12595
- selectElement,
12596
- scope,
12597
- );
12598
- // This stores the newly created options before they are appended to the select.
12599
- // Since the contents are removed from the fragment when it is appended,
12600
- // we only need to create it once.
12601
- const listFragment = document.createDocumentFragment();
12602
-
12603
- // Overwrite the implementation. ngOptions doesn't use hashes
12604
- selectCtrl.generateUnknownOptionValue = () => "?";
12605
-
12606
- // Update the controller methods for multiple selectable options
12607
- if (!multiple) {
12608
- selectCtrl.writeValue = function writeNgOptionsValue(value) {
12609
- // The options might not be defined yet when ngModel tries to render
12610
- if (!options) return;
12611
-
12612
- const selectedOption =
12613
- selectElement.options[selectElement.selectedIndex];
12614
- const option = options.getOptionFromViewValue(value);
12615
-
12616
- // Make sure to remove the selected attribute from the previously selected option
12617
- // Otherwise, screen readers might get confused
12618
- if (selectedOption) selectedOption.removeAttribute("selected");
12619
-
12620
- if (option) {
12621
- // Don't update the option when it is already selected.
12622
- // For example, the browser will select the first option by default. In that case,
12623
- // most properties are set automatically - except the `selected` attribute, which we
12624
- // set always
12625
-
12626
- if (selectElement.value !== option.selectValue) {
12627
- selectCtrl.removeUnknownOption();
12628
-
12629
- selectElement.value = option.selectValue;
12630
- option.element.selected = true;
12631
- }
12628
+ let options;
12629
+ const ngOptions = parseOptionsExpression(
12630
+ attr["ngOptions"],
12631
+ selectElement,
12632
+ scope,
12633
+ );
12634
+ // This stores the newly created options before they are appended to the select.
12635
+ // Since the contents are removed from the fragment when it is appended,
12636
+ // we only need to create it once.
12637
+ const listFragment = document.createDocumentFragment();
12638
+
12639
+ // Overwrite the implementation. ngOptions doesn't use hashes
12640
+ selectCtrl.generateUnknownOptionValue = () => "?";
12641
+
12642
+ // Update the controller methods for multiple selectable options
12643
+ if (!multiple) {
12644
+ selectCtrl.writeValue = function writeNgOptionsValue(value) {
12645
+ // The options might not be defined yet when ngModel tries to render
12646
+ if (!options) return;
12647
+
12648
+ const selectedOption =
12649
+ selectElement.options[selectElement.selectedIndex];
12650
+ const option = options.getOptionFromViewValue(value);
12651
+
12652
+ // Make sure to remove the selected attribute from the previously selected option
12653
+ // Otherwise, screen readers might get confused
12654
+ if (selectedOption) selectedOption.removeAttribute("selected");
12655
+
12656
+ if (option) {
12657
+ // Don't update the option when it is already selected.
12658
+ // For example, the browser will select the first option by default. In that case,
12659
+ // most properties are set automatically - except the `selected` attribute, which we
12660
+ // set always
12661
+
12662
+ if (selectElement.value !== option.selectValue) {
12663
+ selectCtrl.removeUnknownOption();
12632
12664
 
12633
- option.element.setAttribute("selected", "selected");
12634
- } else {
12635
- selectCtrl.selectUnknownOrEmptyOption(value);
12665
+ selectElement.value = option.selectValue;
12666
+ option.element.selected = true;
12636
12667
  }
12637
- };
12638
12668
 
12639
- selectCtrl.readValue = function readNgOptionsValue() {
12640
- const selectedOption = options.selectValueMap[selectElement.value];
12669
+ option.element.setAttribute("selected", "selected");
12670
+ } else {
12671
+ selectCtrl.selectUnknownOrEmptyOption(value);
12672
+ }
12673
+ };
12641
12674
 
12642
- if (selectedOption && !selectedOption.disabled) {
12643
- selectCtrl.unselectEmptyOption();
12644
- selectCtrl.removeUnknownOption();
12645
- return options.getViewValueFromOption(selectedOption);
12646
- }
12647
- return null;
12648
- };
12675
+ selectCtrl.readValue = function readNgOptionsValue() {
12676
+ const selectedOption = options.selectValueMap[selectElement.value];
12649
12677
 
12650
- // If we are using `track by` then we must watch the tracked value on the model
12651
- // since ngModel only watches for object identity change
12652
- // FIXME: When a user selects an option, this watch will fire needlessly
12653
- if (ngOptions.trackBy) {
12654
- scope.$watch(
12655
- ngOptions.getTrackByValue(ngModelCtrl.$viewValue),
12656
- () => {
12657
- ngModelCtrl.$render();
12658
- },
12659
- );
12678
+ if (selectedOption && !selectedOption.disabled) {
12679
+ selectCtrl.unselectEmptyOption();
12680
+ selectCtrl.removeUnknownOption();
12681
+ return options.getViewValueFromOption(selectedOption);
12660
12682
  }
12661
- } else {
12662
- selectCtrl.writeValue = function writeNgOptionsMultiple(values) {
12663
- // The options might not be defined yet when ngModel tries to render
12664
- if (!options) return;
12665
-
12666
- // Only set `<option>.selected` if necessary, in order to prevent some browsers from
12667
- // scrolling to `<option>` elements that are outside the `<select>` element's viewport.
12668
- const selectedOptions =
12669
- (values && values.map(getAndUpdateSelectedOption)) || [];
12670
-
12671
- options.items.forEach((option) => {
12672
- if (option.element.selected && !includes(selectedOptions, option)) {
12673
- option.element.selected = false;
12674
- }
12675
- });
12676
- };
12683
+ return null;
12684
+ };
12677
12685
 
12678
- selectCtrl.readValue = function readNgOptionsMultiple() {
12679
- const selectedValues = selectElement.value || [];
12680
- const selections = [];
12681
- // @ts-ignore
12682
- selectedValues.forEach((value) => {
12683
- const option = options.selectValueMap[value];
12684
- if (option && !option.disabled)
12685
- selections.push(options.getViewValueFromOption(option));
12686
- });
12686
+ // If we are using `track by` then we must watch the tracked value on the model
12687
+ // since ngModel only watches for object identity change
12688
+ // FIXME: When a user selects an option, this watch will fire needlessly
12689
+ if (ngOptions.trackBy) {
12690
+ scope.$watch(ngOptions.getTrackByValue(ngModelCtrl.$viewValue), () => {
12691
+ ngModelCtrl.$render();
12692
+ });
12693
+ }
12694
+ } else {
12695
+ selectCtrl.writeValue = function writeNgOptionsMultiple(values) {
12696
+ // The options might not be defined yet when ngModel tries to render
12697
+ if (!options) return;
12687
12698
 
12688
- return selections;
12689
- };
12699
+ // Only set `<option>.selected` if necessary, in order to prevent some browsers from
12700
+ // scrolling to `<option>` elements that are outside the `<select>` element's viewport.
12701
+ const selectedOptions =
12702
+ (values && values.map(getAndUpdateSelectedOption)) || [];
12690
12703
 
12691
- // If we are using `track by` then we must watch these tracked values on the model
12692
- // since ngModel only watches for object identity change
12693
- // if (ngOptions.trackBy) {
12694
- // scope.$watchCollection(
12695
- // () => {
12696
- // if (Array.isArray(ngModelCtrl.$viewValue)) {
12697
- // return ngModelCtrl.$viewValue.map((value) =>
12698
- // ngOptions.getTrackByValue(value),
12699
- // );
12700
- // }
12701
- // },
12702
- // () => {
12703
- // ngModelCtrl.$render();
12704
- // },
12705
- // );
12706
- // }
12707
- }
12704
+ options.items.forEach((option) => {
12705
+ if (option.element.selected && !includes(selectedOptions, option)) {
12706
+ option.element.selected = false;
12707
+ }
12708
+ });
12709
+ };
12708
12710
 
12709
- if (providedEmptyOption) {
12710
- // compile the element since there might be bindings in it
12711
- const linkFn = $compile(selectCtrl.emptyOption);
12712
- assertArg$1(linkFn, "LinkFn required");
12713
- selectElement.prepend(selectCtrl.emptyOption);
12714
- linkFn(scope);
12711
+ selectCtrl.readValue = function readNgOptionsMultiple() {
12712
+ const selectedValues = selectElement.value || [];
12713
+ const selections = [];
12714
+ // @ts-ignore
12715
+ selectedValues.forEach((value) => {
12716
+ const option = options.selectValueMap[value];
12717
+ if (option && !option.disabled)
12718
+ selections.push(options.getViewValueFromOption(option));
12719
+ });
12720
+
12721
+ return selections;
12722
+ };
12715
12723
 
12716
- if (selectCtrl.emptyOption.nodeType === Node.COMMENT_NODE) {
12717
- // This means the empty option has currently no actual DOM node, probably because
12718
- // it has been modified by a transclusion directive.
12719
- selectCtrl.hasEmptyOption = false;
12724
+ // If we are using `track by` then we must watch these tracked values on the model
12725
+ // since ngModel only watches for object identity change
12726
+ // if (ngOptions.trackBy) {
12727
+ // scope.$watchCollection(
12728
+ // () => {
12729
+ // if (Array.isArray(ngModelCtrl.$viewValue)) {
12730
+ // return ngModelCtrl.$viewValue.map((value) =>
12731
+ // ngOptions.getTrackByValue(value),
12732
+ // );
12733
+ // }
12734
+ // },
12735
+ // () => {
12736
+ // ngModelCtrl.$render();
12737
+ // },
12738
+ // );
12739
+ // }
12740
+ }
12720
12741
 
12721
- // Redefine the registerOption function, which will catch
12722
- // options that are added by ngIf etc. (rendering of the node is async because of
12723
- // lazy transclusion)
12724
- selectCtrl.registerOption = function (optionScope, optionEl) {
12725
- if (optionEl.value === "") {
12726
- selectCtrl.hasEmptyOption = true;
12727
- selectCtrl.emptyOption = optionEl;
12728
- // This ensures the new empty option is selected if previously no option was selected
12729
- ngModelCtrl.$render();
12742
+ if (providedEmptyOption) {
12743
+ // compile the element since there might be bindings in it
12744
+ const linkFn = $compile(selectCtrl.emptyOption);
12745
+ assertArg$1(linkFn, "LinkFn required");
12746
+ selectElement.prepend(selectCtrl.emptyOption);
12747
+ linkFn(scope);
12748
+
12749
+ if (selectCtrl.emptyOption.nodeType === Node.COMMENT_NODE) {
12750
+ // This means the empty option has currently no actual DOM node, probably because
12751
+ // it has been modified by a transclusion directive.
12752
+ selectCtrl.hasEmptyOption = false;
12753
+
12754
+ // Redefine the registerOption function, which will catch
12755
+ // options that are added by ngIf etc. (rendering of the node is async because of
12756
+ // lazy transclusion)
12757
+ selectCtrl.registerOption = function (optionScope, optionEl) {
12758
+ if (optionEl.value === "") {
12759
+ selectCtrl.hasEmptyOption = true;
12760
+ selectCtrl.emptyOption = optionEl;
12761
+ // This ensures the new empty option is selected if previously no option was selected
12762
+ ngModelCtrl.$render();
12730
12763
 
12731
- optionEl.addEventListener("$destroy", () => {
12732
- const needsRerender = selectCtrl.$isEmptyOptionSelected();
12764
+ optionEl.addEventListener("$destroy", () => {
12765
+ const needsRerender = selectCtrl.$isEmptyOptionSelected();
12733
12766
 
12734
- selectCtrl.hasEmptyOption = false;
12735
- selectCtrl.emptyOption = undefined;
12767
+ selectCtrl.hasEmptyOption = false;
12768
+ selectCtrl.emptyOption = undefined;
12736
12769
 
12737
- if (needsRerender) ngModelCtrl.$render();
12738
- });
12739
- }
12740
- };
12741
- }
12770
+ if (needsRerender) ngModelCtrl.$render();
12771
+ });
12772
+ }
12773
+ };
12742
12774
  }
12775
+ }
12743
12776
 
12744
- // We will re-render the option elements if the option values or labels change
12777
+ // We will re-render the option elements if the option values or labels change
12745
12778
 
12746
- // let watchables = ngOptions.getWatchables();
12747
- // watchables.forEach((i) => {
12748
- // scope.$watch(i, updateOptions);
12749
- // });
12750
- scope.$watch(
12751
- ngOptions.getWatchables.decoratedNode.body[0].expression.name,
12752
- updateOptions,
12753
- );
12779
+ // let watchables = ngOptions.getWatchables();
12780
+ // watchables.forEach((i) => {
12781
+ // scope.$watch(i, updateOptions);
12782
+ // });
12783
+ scope.$watch(
12784
+ ngOptions.getWatchables.decoratedNode.body[0].expression.name,
12785
+ updateOptions,
12786
+ );
12754
12787
 
12755
- // ------------------------------------------------------------------ //
12788
+ // ------------------------------------------------------------------ //
12756
12789
 
12757
- function addOptionElement(option, parent) {
12758
- /**
12759
- * @type {HTMLOptionElement}
12760
- */
12761
- const optionElement = /** @type {HTMLOptionElement} */ (
12762
- optionTemplate.cloneNode(false)
12763
- );
12764
- parent.appendChild(optionElement);
12765
- updateOptionElement(option, optionElement);
12766
- }
12790
+ function addOptionElement(option, parent) {
12791
+ /**
12792
+ * @type {HTMLOptionElement}
12793
+ */
12794
+ const optionElement = /** @type {HTMLOptionElement} */ (
12795
+ optionTemplate.cloneNode(false)
12796
+ );
12797
+ parent.appendChild(optionElement);
12798
+ updateOptionElement(option, optionElement);
12799
+ }
12767
12800
 
12768
- function getAndUpdateSelectedOption(viewValue) {
12769
- const option = options.getOptionFromViewValue(viewValue);
12770
- const element = option && option.element;
12801
+ function getAndUpdateSelectedOption(viewValue) {
12802
+ const option = options.getOptionFromViewValue(viewValue);
12803
+ const element = option && option.element;
12771
12804
 
12772
- if (element && !element.selected) element.selected = true;
12805
+ if (element && !element.selected) element.selected = true;
12773
12806
 
12774
- return option;
12775
- }
12807
+ return option;
12808
+ }
12776
12809
 
12777
- function updateOptionElement(option, element) {
12778
- option.element = element;
12779
- element.disabled = option.disabled;
12780
- // Support: IE 11 only, Edge 12-13 only
12781
- // NOTE: The label must be set before the value, otherwise IE 11 & Edge create unresponsive
12782
- // selects in certain circumstances when multiple selects are next to each other and display
12783
- // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
12784
- // See https://github.com/angular/angular.js/issues/11314 for more info.
12785
- // This is unfortunately untestable with unit / e2e tests
12786
- if (option.label !== element.label) {
12787
- element.label = option.label;
12788
- element.textContent = option.label;
12789
- }
12790
- element.value = option.selectValue;
12810
+ function updateOptionElement(option, element) {
12811
+ option.element = element;
12812
+ element.disabled = option.disabled;
12813
+ // Support: IE 11 only, Edge 12-13 only
12814
+ // NOTE: The label must be set before the value, otherwise IE 11 & Edge create unresponsive
12815
+ // selects in certain circumstances when multiple selects are next to each other and display
12816
+ // the option list in listbox style, i.e. the select is [multiple], or specifies a [size].
12817
+ // See https://github.com/angular/angular.js/issues/11314 for more info.
12818
+ // This is unfortunately untestable with unit / e2e tests
12819
+ if (option.label !== element.label) {
12820
+ element.label = option.label;
12821
+ element.textContent = option.label;
12791
12822
  }
12823
+ element.value = option.selectValue;
12824
+ }
12792
12825
 
12793
- function updateOptions() {
12794
- const previousValue = options && selectCtrl.readValue();
12826
+ function updateOptions() {
12827
+ const previousValue = options && selectCtrl.readValue();
12795
12828
 
12796
- // We must remove all current options, but cannot simply set innerHTML = null
12797
- // since the providedEmptyOption might have an ngIf on it that inserts comments which we
12798
- // must preserve.
12799
- // Instead, iterate over the current option elements and remove them or their optgroup
12800
- // parents
12801
- if (options) {
12802
- for (let i = options.items.length - 1; i >= 0; i--) {
12803
- const option = options.items[i];
12804
- if (isDefined(option.group)) {
12805
- removeElement(option.element.parentNode);
12806
- } else {
12807
- removeElement(option.element);
12808
- }
12829
+ // We must remove all current options, but cannot simply set innerHTML = null
12830
+ // since the providedEmptyOption might have an ngIf on it that inserts comments which we
12831
+ // must preserve.
12832
+ // Instead, iterate over the current option elements and remove them or their optgroup
12833
+ // parents
12834
+ if (options) {
12835
+ for (let i = options.items.length - 1; i >= 0; i--) {
12836
+ const option = options.items[i];
12837
+ if (isDefined(option.group)) {
12838
+ removeElement(option.element.parentNode);
12839
+ } else {
12840
+ removeElement(option.element);
12809
12841
  }
12810
12842
  }
12843
+ }
12811
12844
 
12812
- options = ngOptions.getOptions();
12845
+ options = ngOptions.getOptions();
12813
12846
 
12814
- const groupElementMap = {};
12847
+ const groupElementMap = {};
12815
12848
 
12816
- options.items.forEach((option) => {
12817
- let groupElement;
12849
+ options.items.forEach((option) => {
12850
+ let groupElement;
12818
12851
 
12819
- if (isDefined(option.group)) {
12820
- // This option is to live in a group
12821
- // See if we have already created this group
12822
- groupElement = groupElementMap[option.group];
12823
-
12824
- if (!groupElement) {
12825
- groupElement = optGroupTemplate.cloneNode(false);
12826
- listFragment.appendChild(groupElement);
12827
-
12828
- // Update the label on the group element
12829
- // "null" is special cased because of Safari
12830
- /** @type {HTMLOptGroupElement} */
12831
- (groupElement).label =
12832
- option.group === null ? "null" : option.group;
12833
-
12834
- // Store it for use later
12835
- groupElementMap[option.group] = groupElement;
12836
- }
12852
+ if (isDefined(option.group)) {
12853
+ // This option is to live in a group
12854
+ // See if we have already created this group
12855
+ groupElement = groupElementMap[option.group];
12837
12856
 
12838
- addOptionElement(option, groupElement);
12839
- } else {
12840
- // This option is not in a group
12841
- addOptionElement(option, listFragment);
12857
+ if (!groupElement) {
12858
+ groupElement = optGroupTemplate.cloneNode(false);
12859
+ listFragment.appendChild(groupElement);
12860
+
12861
+ // Update the label on the group element
12862
+ // "null" is special cased because of Safari
12863
+ /** @type {HTMLOptGroupElement} */
12864
+ (groupElement).label =
12865
+ option.group === null ? "null" : option.group;
12866
+
12867
+ // Store it for use later
12868
+ groupElementMap[option.group] = groupElement;
12842
12869
  }
12843
- });
12844
12870
 
12845
- selectElement.appendChild(listFragment);
12871
+ addOptionElement(option, groupElement);
12872
+ } else {
12873
+ // This option is not in a group
12874
+ addOptionElement(option, listFragment);
12875
+ }
12876
+ });
12846
12877
 
12847
- ngModelCtrl.$render();
12878
+ selectElement.appendChild(listFragment);
12848
12879
 
12849
- // Check to see if the value has changed due to the update to the options
12850
- if (!ngModelCtrl.$isEmpty(previousValue)) {
12851
- const nextValue = selectCtrl.readValue();
12852
- const isNotPrimitive = ngOptions.trackBy || multiple;
12853
- if (
12854
- isNotPrimitive
12855
- ? !equals$1(previousValue, nextValue)
12856
- : previousValue !== nextValue
12857
- ) {
12858
- ngModelCtrl.$setViewValue(nextValue);
12859
- ngModelCtrl.$render();
12860
- }
12880
+ ngModelCtrl.$render();
12881
+
12882
+ // Check to see if the value has changed due to the update to the options
12883
+ if (!ngModelCtrl.$isEmpty(previousValue)) {
12884
+ const nextValue = selectCtrl.readValue();
12885
+ const isNotPrimitive = ngOptions.trackBy || multiple;
12886
+ if (
12887
+ isNotPrimitive
12888
+ ? !equals$1(previousValue, nextValue)
12889
+ : previousValue !== nextValue
12890
+ ) {
12891
+ ngModelCtrl.$setViewValue(nextValue);
12892
+ ngModelCtrl.$render();
12861
12893
  }
12862
12894
  }
12863
12895
  }
12896
+ }
12864
12897
 
12865
- return {
12866
- restrict: "A",
12867
- terminal: true,
12868
- require: ["select", "ngModel"],
12869
- link: {
12870
- pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
12871
- // Deactivate the SelectController.register method to prevent
12872
- // option directives from accidentally registering themselves
12873
- // (and unwanted $destroy handlers etc.)
12874
- ctrls[0].registerOption = () => {};
12875
- },
12876
- post: ngOptionsPostLink,
12898
+ return {
12899
+ restrict: "A",
12900
+ terminal: true,
12901
+ require: ["select", "ngModel"],
12902
+ link: {
12903
+ pre: function ngOptionsPreLink(scope, selectElement, attr, ctrls) {
12904
+ // Deactivate the SelectController.register method to prevent
12905
+ // option directives from accidentally registering themselves
12906
+ // (and unwanted $destroy handlers etc.)
12907
+ ctrls[0].registerOption = () => {};
12877
12908
  },
12878
- };
12879
- },
12880
- ];
12909
+ post: ngOptionsPostLink,
12910
+ },
12911
+ };
12912
+ }
12881
12913
 
12882
12914
  /**
12883
12915
  * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
@@ -12896,113 +12928,114 @@
12896
12928
  * or its value is the same as the name of the attribute then the default slot is used.
12897
12929
  */
12898
12930
  const ngTranscludeMinErr = minErr("ngTransclude");
12899
- const ngTranscludeDirective = [
12900
- "$compile",
12901
12931
 
12902
- /**
12903
- * @param {import("../../core/compile/compile.js").CompileFn} $compile
12904
- * @returns {import("../../interface.ts").Directive}
12905
- */
12906
- function ($compile) {
12907
- return {
12908
- compile: function ngTranscludeCompile(tElement) {
12909
- // Remove and cache any original content to act as a fallback
12910
- const fallbackLinkFn = $compile(tElement.childNodes);
12911
- emptyElement(tElement);
12932
+ ngTranscludeDirective.$inject = ["$compile"];
12933
+ /**
12934
+ * @param {import("../../core/compile/compile.js").CompileFn} $compile
12935
+ * @returns {import("../../interface.ts").Directive}
12936
+ */
12937
+ function ngTranscludeDirective($compile) {
12938
+ return {
12939
+ compile: function ngTranscludeCompile(tElement) {
12940
+ // Remove and cache any original content to act as a fallback
12941
+ const fallbackLinkFn = $compile(tElement.childNodes);
12942
+ emptyElement(tElement);
12912
12943
 
12913
- /**
12914
- *
12915
- * @param {import("../../core/scope/scope.js").Scope} $scope
12916
- * @param {Element} $element
12917
- * @param {import("../../core/compile/attributes.js").Attributes} $attrs
12918
- * @param {*} _controller
12919
- * @param {*} $transclude
12920
- */
12921
- function ngTranscludePostLink(
12922
- $scope,
12923
- $element,
12924
- $attrs,
12925
- _controller,
12926
- $transclude,
12927
- ) {
12928
- if (!$transclude) {
12929
- throw ngTranscludeMinErr(
12930
- "orphan",
12931
- "Illegal use of ngTransclude directive in the template! " +
12932
- "No parent directive that requires a transclusion found. " +
12933
- "Element: {0}",
12934
- startingTag($element),
12935
- );
12936
- }
12944
+ /**
12945
+ *
12946
+ * @param {import("../../core/scope/scope.js").Scope} $scope
12947
+ * @param {Element} $element
12948
+ * @param {import("../../core/compile/attributes.js").Attributes} $attrs
12949
+ * @param {*} _controller
12950
+ * @param {*} $transclude
12951
+ */
12952
+ function ngTranscludePostLink(
12953
+ $scope,
12954
+ $element,
12955
+ $attrs,
12956
+ _controller,
12957
+ $transclude,
12958
+ ) {
12959
+ if (!$transclude) {
12960
+ throw ngTranscludeMinErr(
12961
+ "orphan",
12962
+ "Illegal use of ngTransclude directive in the template! " +
12963
+ "No parent directive that requires a transclusion found. " +
12964
+ "Element: {0}",
12965
+ startingTag($element),
12966
+ );
12967
+ }
12937
12968
 
12938
- // If the attribute is of the form: `ng-transclude="ng-transclude"` then treat it like the default
12939
- if ($attrs["ngTransclude"] === $attrs.$attr.ngTransclude) {
12940
- $attrs["ngTransclude"] = "";
12941
- }
12942
- const slotName = $attrs["ngTransclude"] || $attrs["ngTranscludeSlot"];
12969
+ // If the attribute is of the form: `ng-transclude="ng-transclude"` then treat it like the default
12970
+ if ($attrs["ngTransclude"] === $attrs.$attr.ngTransclude) {
12971
+ $attrs["ngTransclude"] = "";
12972
+ }
12973
+ const slotName = $attrs["ngTransclude"] || $attrs["ngTranscludeSlot"];
12943
12974
 
12944
- // If the slot is required and no transclusion content is provided then this call will throw an error
12945
- $transclude(ngTranscludeCloneAttachFn, null, slotName);
12975
+ // If the slot is required and no transclusion content is provided then this call will throw an error
12976
+ $transclude(ngTranscludeCloneAttachFn, null, slotName);
12946
12977
 
12947
- // If the slot is optional and no transclusion content is provided then use the fallback content
12948
- if (slotName && !$transclude.isSlotFilled(slotName)) {
12949
- useFallbackContent();
12950
- }
12978
+ // If the slot is optional and no transclusion content is provided then use the fallback content
12979
+ if (slotName && !$transclude.isSlotFilled(slotName)) {
12980
+ useFallbackContent();
12981
+ }
12951
12982
 
12952
- /**
12953
- * @param {NodeList | Node} clone
12954
- * @param {import("../../core/scope/scope.js").Scope} transcludedScope
12955
- */
12956
- function ngTranscludeCloneAttachFn(clone, transcludedScope) {
12957
- if (notWhitespace(clone)) {
12958
- if (clone instanceof NodeList) {
12959
- Array.from(clone).forEach((el) => {
12960
- $element.append(el);
12961
- });
12962
- } else {
12963
- $element.append(/** @type {Node} */ (clone));
12964
- }
12983
+ /**
12984
+ * @param {NodeList | Node} clone
12985
+ * @param {import("../../core/scope/scope.js").Scope} transcludedScope
12986
+ */
12987
+ function ngTranscludeCloneAttachFn(clone, transcludedScope) {
12988
+ if (notWhitespace(clone)) {
12989
+ if (clone instanceof NodeList) {
12990
+ Array.from(clone).forEach((el) => {
12991
+ $element.append(el);
12992
+ });
12965
12993
  } else {
12966
- useFallbackContent();
12967
- // There is nothing linked against the transcluded scope since no content was available,
12968
- // so it should be safe to clean up the generated scope.
12969
- transcludedScope.$destroy();
12994
+ $element.append(/** @type {Node} */ (clone));
12970
12995
  }
12996
+ } else {
12997
+ useFallbackContent();
12998
+ // There is nothing linked against the transcluded scope since no content was available,
12999
+ // so it should be safe to clean up the generated scope.
13000
+ transcludedScope.$destroy();
12971
13001
  }
13002
+ }
12972
13003
 
12973
- function useFallbackContent() {
12974
- // Since this is the fallback content rather than the transcluded content,
12975
- // we link against the scope of this directive rather than the transcluded scope
12976
- fallbackLinkFn(
12977
- $scope,
13004
+ function useFallbackContent() {
13005
+ // Since this is the fallback content rather than the transcluded content,
13006
+ // we link against the scope of this directive rather than the transcluded scope
13007
+ fallbackLinkFn(
13008
+ $scope,
12978
13009
 
12979
- (clone) => {
12980
- // @ts-ignore
12981
- $element.append(clone);
12982
- },
12983
- );
12984
- }
13010
+ (clone) => {
13011
+ // @ts-ignore
13012
+ $element.append(clone);
13013
+ },
13014
+ );
13015
+ }
12985
13016
 
12986
- function notWhitespace(node) {
12987
- if (node instanceof Array) {
12988
- return false;
12989
- } else if (
12990
- node.nodeType !== Node.TEXT_NODE ||
12991
- node.nodeValue.trim()
12992
- ) {
12993
- return true;
12994
- }
13017
+ function notWhitespace(node) {
13018
+ if (node instanceof Array) {
13019
+ return false;
13020
+ } else if (
13021
+ node.nodeType !== Node.TEXT_NODE ||
13022
+ node.nodeValue.trim()
13023
+ ) {
13024
+ return true;
12995
13025
  }
12996
13026
  }
13027
+ }
12997
13028
 
12998
- return ngTranscludePostLink;
12999
- },
13000
- };
13001
- },
13002
- ];
13029
+ return ngTranscludePostLink;
13030
+ },
13031
+ };
13032
+ }
13003
13033
 
13004
13034
  const REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
13005
13035
 
13036
+ /**
13037
+ * @type {Record<string, import("../../interface.js").DirectiveFactory>}
13038
+ */
13006
13039
  const ngAttributeAliasDirectives = {};
13007
13040
 
13008
13041
  // boolean attrs are evaluated
@@ -13045,10 +13078,10 @@
13045
13078
  link(scope, element, attr) {
13046
13079
  // special case ngPattern when a literal regular expression value
13047
13080
  // is used as the expression (this way we don't have to watch anything).
13048
- if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) === "/") {
13049
- const match = attr.ngPattern.match(REGEX_STRING_REGEXP);
13081
+ if (ngAttr === "ngPattern" && attr["ngPattern"].charAt(0) === "/") {
13082
+ const match = attr["ngPattern"].match(REGEX_STRING_REGEXP);
13050
13083
  if (match) {
13051
- attr.$set("ngPattern", new RegExp(match[1], match[2]));
13084
+ attr.$set("ngPattern", new RegExp(match[1], match[2]).toString());
13052
13085
  return;
13053
13086
  }
13054
13087
  }
@@ -13074,7 +13107,7 @@
13074
13107
 
13075
13108
  if (
13076
13109
  attrName === "href" &&
13077
- toString.call(element.href) === "[object SVGAnimatedString]"
13110
+ toString.call(element["href"]) === "[object SVGAnimatedString]"
13078
13111
  ) {
13079
13112
  name = "xlinkHref";
13080
13113
  attr.$attr[name] = "href";
@@ -13460,7 +13493,7 @@
13460
13493
  "$rootScope",
13461
13494
  /**
13462
13495
  *
13463
- * @param {import('../core/location/location.js').Location} $location
13496
+ * @param {import('../services/location/location.js').Location} $location
13464
13497
  * @param {import('../core/scope/scope.js').Scope} $rootScope
13465
13498
  * @returns
13466
13499
  */
@@ -13559,7 +13592,7 @@
13559
13592
  // skip the initial scroll if $location.hash is empty
13560
13593
  if (newVal === oldVal && newVal === "") return;
13561
13594
 
13562
- const action = () => $rootScope.$evalAsync(scroll);
13595
+ const action = () => Promise.resolve().then(scroll);
13563
13596
  if (document.readyState === "complete") {
13564
13597
  // Force the action to be run async for consistent behavior
13565
13598
  // from the action's point of view
@@ -14478,216 +14511,6 @@
14478
14511
  ];
14479
14512
  }
14480
14513
 
14481
- /**
14482
- * Removes a trailing hash ('#') from the given URL if it exists.
14483
- *
14484
- * @param {string} url
14485
- * @returns {string}
14486
- */
14487
- function trimEmptyHash(url) {
14488
- return url.replace(/#$/, "");
14489
- }
14490
-
14491
- /**
14492
- * @typedef {function(string, string|null): any} UrlChangeListener
14493
- */
14494
-
14495
- /**
14496
- * This object has two goals:
14497
- *
14498
- * - hide all the global state in the browser caused by the window object
14499
- * - abstract away all the browser specific features and inconsistencies
14500
- */
14501
- class Browser {
14502
- /**
14503
- * @param {import('../core/task-tracker-factory.js').TaskTracker} taskTracker
14504
- */
14505
- constructor(taskTracker) {
14506
- /**
14507
- * @type {import('../core/task-tracker-factory.js').TaskTracker} taskTracker
14508
- */
14509
- this.taskTracker = taskTracker;
14510
- this.pendingDeferIds = {};
14511
- /** @type {Array<UrlChangeListener>} */
14512
- this.urlChangeListeners = [];
14513
- this.urlChangeInit = false;
14514
-
14515
- /** @type {any} */
14516
- this.cachedState = null;
14517
- /** @type {any} */
14518
- this.lastHistoryState = null;
14519
- /** @type {string} */
14520
- this.lastBrowserUrl = window.location.href;
14521
- /** @type {HTMLBaseElement | null} */
14522
- this.baseElement = document.querySelector("base");
14523
-
14524
- // Task-tracking API
14525
- this.$$completeOutstandingRequest =
14526
- this.taskTracker.completeTask.bind(taskTracker);
14527
- this.$$incOutstandingRequestCount =
14528
- this.taskTracker.incTaskCount.bind(taskTracker);
14529
- this.notifyWhenNoOutstandingRequests =
14530
- this.taskTracker.notifyWhenNoPendingTasks.bind(taskTracker);
14531
-
14532
- this.cacheState();
14533
- }
14534
-
14535
- /// ///////////////////////////////////////////////////////////
14536
- // URL API
14537
- /// ///////////////////////////////////////////////////////////
14538
-
14539
- url(url, state) {
14540
- if (state === undefined) {
14541
- state = null;
14542
- }
14543
-
14544
- // setter
14545
- if (url) {
14546
- url = urlResolve(url).href;
14547
-
14548
- if (this.lastBrowserUrl === url && this.lastHistoryState === state) {
14549
- return this;
14550
- }
14551
-
14552
- this.lastBrowserUrl = url;
14553
- this.lastHistoryState = state;
14554
- history.pushState(state, "", url);
14555
- this.cacheState();
14556
- return this;
14557
- }
14558
-
14559
- // getter
14560
- return trimEmptyHash(window.location.href);
14561
- }
14562
-
14563
- /**
14564
- * Returns the cached state.
14565
- *
14566
- * @returns {any} The cached state.
14567
- */
14568
- state() {
14569
- return this.cachedState;
14570
- }
14571
-
14572
- /**
14573
- * Caches the current state and fires the URL change event.
14574
- *
14575
- * @private
14576
- */
14577
- cacheStateAndFireUrlChange() {
14578
- this.fireStateOrUrlChange();
14579
- }
14580
-
14581
- /**
14582
- * Caches the current state.
14583
- *
14584
- * @private
14585
- */
14586
- cacheState() {
14587
- const currentState = history.state ?? null;
14588
- if (!equals$1(currentState, this.lastCachedState)) {
14589
- this.cachedState = currentState;
14590
- this.lastCachedState = currentState;
14591
- this.lastHistoryState = currentState;
14592
- }
14593
- }
14594
-
14595
- /**
14596
- * Fires the state or URL change event.
14597
- *
14598
- * @private
14599
- */
14600
- fireStateOrUrlChange() {
14601
- const prevLastHistoryState = this.lastHistoryState;
14602
- this.cacheState();
14603
-
14604
- if (
14605
- this.lastBrowserUrl === this.url() &&
14606
- prevLastHistoryState === this.cachedState
14607
- ) {
14608
- return;
14609
- }
14610
-
14611
- this.lastBrowserUrl = /** @type {string} */ (this.url());
14612
- this.lastHistoryState = this.cachedState;
14613
- this.urlChangeListeners.forEach((listener) => {
14614
- listener(trimEmptyHash(window.location.href), this.cachedState);
14615
- });
14616
- }
14617
-
14618
- /**
14619
- * Registers a callback to be called when the URL changes.
14620
- *
14621
- * @param {UrlChangeListener} callback - The callback function to register.
14622
- * @returns {UrlChangeListener} The registered callback function.
14623
- */
14624
- onUrlChange(callback) {
14625
- if (!this.urlChangeInit) {
14626
- window.addEventListener(
14627
- "popstate",
14628
- this.cacheStateAndFireUrlChange.bind(this),
14629
- );
14630
- window.addEventListener(
14631
- "hashchange",
14632
- this.cacheStateAndFireUrlChange.bind(this),
14633
- );
14634
-
14635
- this.urlChangeInit = true;
14636
- }
14637
-
14638
- this.urlChangeListeners.push(callback);
14639
- return callback;
14640
- }
14641
-
14642
- $$applicationDestroyed() {
14643
- window.removeEventListener(
14644
- "popstate",
14645
- this.cacheStateAndFireUrlChange.bind(this),
14646
- );
14647
- window.removeEventListener(
14648
- "hashchange",
14649
- this.cacheStateAndFireUrlChange.bind(this),
14650
- );
14651
- }
14652
-
14653
- $$checkUrlChange() {
14654
- this.fireStateOrUrlChange();
14655
- }
14656
-
14657
- /// ///////////////////////////////////////////////////////////
14658
- // Misc API
14659
- /// ///////////////////////////////////////////////////////////
14660
-
14661
- /**
14662
- * Returns the base href of the document.
14663
- *
14664
- * @returns {string} The base href.
14665
- */
14666
- baseHref() {
14667
- const href = this.baseElement?.getAttribute("href");
14668
- return href ? href.replace(/^(https?:)?\/\/[^/]*/, "") : "";
14669
- }
14670
- }
14671
-
14672
- /**
14673
- * This object has two goals:
14674
- *
14675
- * - hide all the global state in the browser caused by the window object
14676
- * - abstract away all the browser specific features and inconsistencies
14677
- *
14678
- * Remove this in the future
14679
- */
14680
- class BrowserProvider {
14681
- $get = [
14682
- "$$taskTrackerFactory",
14683
- /**
14684
- * @param {import('../core/task-tracker-factory.js').TaskTracker} $$taskTrackerFactory
14685
- * @returns {Browser}
14686
- */
14687
- ($$taskTrackerFactory) => new Browser($$taskTrackerFactory),
14688
- ];
14689
- }
14690
-
14691
14514
  function AnimateAsyncRunFactoryProvider() {
14692
14515
  this.$get = [
14693
14516
  function () {
@@ -14893,7 +14716,9 @@
14893
14716
  /**
14894
14717
  * @returns {import('./interface.ts').TemplateCache}
14895
14718
  */
14896
- $get = () => this.cache;
14719
+ $get() {
14720
+ return this.cache;
14721
+ }
14897
14722
  }
14898
14723
 
14899
14724
  /**
@@ -14940,9 +14765,9 @@
14940
14765
  * @see {@link angular.ErrorHandler AngularTS ErrorHandler}
14941
14766
  */
14942
14767
 
14943
- /** @typedef {import('../services/log/interface.ts').LogService} LogService */
14768
+ /** @typedef {import('../log/interface.ts').LogService} LogService */
14944
14769
 
14945
- /** @typedef {import("./error-handler.ts").ErrorHandler} ErrorHandler */
14770
+ /** @typedef {import("./interface.ts").Interface} ErrorHandler */
14946
14771
 
14947
14772
  /**
14948
14773
  * Provider for `$exceptionHandler` service. Delegates uncaught exceptions to `$log.error()` by default.
@@ -15426,7 +15251,7 @@
15426
15251
  const isFilter = function (state, params, options) {
15427
15252
  return $state.is(state, params, options);
15428
15253
  };
15429
- //isFilter.$stateful = true;
15254
+ isFilter.$stateful = true;
15430
15255
  return isFilter;
15431
15256
  }
15432
15257
  /**
@@ -15447,53 +15272,52 @@
15447
15272
  const includesFilter = function (state, params, options) {
15448
15273
  return $state.includes(state, params, options);
15449
15274
  };
15450
- //includesFilter.$stateful = true;
15275
+ includesFilter.$stateful = true;
15451
15276
  return includesFilter;
15452
15277
  }
15453
15278
 
15454
- FilterProvider.$inject = ["$provide"];
15279
+ const SUFFIX = "Filter";
15455
15280
 
15456
- /**
15457
- * @param {import('../../interface.ts').Provider} $provide
15458
- */
15459
- function FilterProvider($provide) {
15460
- const suffix = "Filter";
15281
+ class FilterProvider {
15282
+ static $inject = [$injectTokens.$provide];
15283
+
15284
+ /**
15285
+ * @param {import('../../interface.ts').Provider} $provide
15286
+ */
15287
+ constructor($provide) {
15288
+ this.$provide = $provide;
15289
+ this.register({
15290
+ filter: filterFilter,
15291
+ json: jsonFilter,
15292
+ limitTo: limitToFilter,
15293
+ orderBy: orderByFilter,
15294
+ isState: $IsStateFilter,
15295
+ includedByState: $IncludedByStateFilter,
15296
+ });
15297
+ }
15461
15298
 
15462
15299
  /**
15463
15300
  * @param {string|Record<string, import('../../interface.ts').FilterFactory>} name
15464
- * @param {import('../../interface.ts').FilterFactory} factory
15465
- * @return {import('../../interface.ts').ServiceProvider}
15301
+ * @param {import('../../interface.ts').FilterFactory} [factory]
15302
+ * @return {import('../../interface.ts').Provider}
15466
15303
  */
15467
- function register(name, factory) {
15304
+ register(name, factory) {
15468
15305
  if (isObject(name)) {
15469
15306
  Object.entries(name).forEach(([key, filter]) => {
15470
- register(key, filter);
15307
+ this.register(key, filter);
15471
15308
  });
15472
15309
  }
15473
- return $provide.factory(name + suffix, factory);
15310
+ return this.$provide.factory(name + SUFFIX, factory);
15474
15311
  }
15475
15312
 
15476
- this.register = register;
15477
-
15478
- this.$get = [
15479
- "$injector",
15313
+ $get = [
15314
+ $injectTokens.$injector,
15480
15315
  /**
15481
15316
  * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
15482
- * @returns
15317
+ * @returns {import('../../interface.ts').FilterFn}
15483
15318
  */
15484
- function ($injector) {
15485
- return function (name) {
15486
- return $injector.get(name + suffix);
15487
- };
15488
- },
15319
+ ($injector) => (/** @type {string} */ name) => $injector.get(name + SUFFIX),
15489
15320
  ];
15490
-
15491
- register("filter", filterFilter);
15492
- register("json", jsonFilter);
15493
- register("limitTo", limitToFilter);
15494
- register("orderBy", orderByFilter);
15495
- register("isState", $IsStateFilter);
15496
- register("includedByState", $IncludedByStateFilter);
15497
15321
  }
15498
15322
 
15499
15323
  const PURITY_ABSOLUTE = 1;
@@ -15632,7 +15456,7 @@
15632
15456
  if (ast.filter) right = this.$filter(ast.callee.name);
15633
15457
  if (!ast.filter) right = this.recurse(ast.callee, true);
15634
15458
  return ast.filter
15635
- ? function (scope, locals, assign) {
15459
+ ? (scope, locals, assign) => {
15636
15460
  const values = [];
15637
15461
  for (let i = 0; i < args.length; ++i) {
15638
15462
  const res = args[i](scope, locals, assign);
@@ -15645,7 +15469,7 @@
15645
15469
  ? { context: undefined, name: undefined, value }
15646
15470
  : value;
15647
15471
  }
15648
- : function (scope, locals, assign) {
15472
+ : (scope, locals, assign) => {
15649
15473
  const rhs = right(scope, locals, assign);
15650
15474
  let value;
15651
15475
  if (rhs.value != null && isFunction(rhs.value)) {
@@ -15661,7 +15485,7 @@
15661
15485
  case ASTType.AssignmentExpression:
15662
15486
  left = this.recurse(ast.left, true, 1);
15663
15487
  right = this.recurse(ast.right);
15664
- return function (scope, locals, assign) {
15488
+ return (scope, locals, assign) => {
15665
15489
  const lhs = left(scope, locals, assign);
15666
15490
  const rhs = right(scope, locals, assign);
15667
15491
  lhs.context[lhs.name] = rhs;
@@ -15672,7 +15496,7 @@
15672
15496
  ast.elements.forEach((expr) => {
15673
15497
  args.push(self.recurse(expr));
15674
15498
  });
15675
- return function (scope, locals, assign) {
15499
+ return (scope, locals, assign) => {
15676
15500
  const value = [];
15677
15501
  for (let i = 0; i < args.length; ++i) {
15678
15502
  value.push(args[i](scope, locals, assign));
@@ -15699,7 +15523,7 @@
15699
15523
  });
15700
15524
  }
15701
15525
  });
15702
- return function (scope, locals, assign) {
15526
+ return (scope, locals, assign) => {
15703
15527
  const value = {};
15704
15528
  for (let i = 0; i < args.length; ++i) {
15705
15529
  if (args[i].computed) {
@@ -15715,17 +15539,12 @@
15715
15539
  return context ? { value } : value;
15716
15540
  };
15717
15541
  case ASTType.ThisExpression:
15718
- return function (scope) {
15719
- return context ? { value: scope } : scope;
15720
- };
15542
+ return (scope) => (context ? { value: scope } : scope);
15721
15543
  case ASTType.LocalsExpression:
15722
- return function (scope, locals) {
15723
- return context ? { value: locals } : locals;
15724
- };
15544
+ return (scope, locals) => (context ? { value: locals } : locals);
15725
15545
  case ASTType.NGValueParameter:
15726
- return function (scope, locals, assign) {
15727
- return context ? { value: assign } : assign;
15728
- };
15546
+ return (scope, locals, assign) =>
15547
+ context ? { value: assign } : assign;
15729
15548
  }
15730
15549
  }
15731
15550
 
@@ -15736,7 +15555,7 @@
15736
15555
  * @returns {function} The unary plus function.
15737
15556
  */
15738
15557
  "unary+"(argument, context) {
15739
- return function (scope, locals, assign) {
15558
+ return (scope, locals, assign) => {
15740
15559
  let arg = argument(scope, locals, assign);
15741
15560
  if (isDefined(arg)) {
15742
15561
  arg = +arg;
@@ -15754,7 +15573,7 @@
15754
15573
  * @returns {function} The unary minus function.
15755
15574
  */
15756
15575
  "unary-"(argument, context) {
15757
- return function (scope, locals, assign) {
15576
+ return (scope, locals, assign) => {
15758
15577
  let arg = argument(scope, locals, assign);
15759
15578
  if (isDefined(arg)) {
15760
15579
  arg = -arg;
@@ -15772,7 +15591,7 @@
15772
15591
  * @returns {function} The unary negation function.
15773
15592
  */
15774
15593
  "unary!"(argument, context) {
15775
- return function (scope, locals, assign) {
15594
+ return (scope, locals, assign) => {
15776
15595
  const arg = !argument(scope, locals, assign);
15777
15596
  return context ? { value: arg } : arg;
15778
15597
  };
@@ -15786,7 +15605,7 @@
15786
15605
  * @returns {function} The binary plus function.
15787
15606
  */
15788
15607
  "binary+"(left, right, context) {
15789
- return function (scope, locals, assign) {
15608
+ return (scope, locals, assign) => {
15790
15609
  const lhs = left(scope, locals, assign);
15791
15610
  const rhs = right(scope, locals, assign);
15792
15611
  const arg = plusFn(lhs, rhs);
@@ -15802,7 +15621,7 @@
15802
15621
  * @returns {function} The binary minus function.
15803
15622
  */
15804
15623
  "binary-"(left, right, context) {
15805
- return function (scope, locals, assign) {
15624
+ return (scope, locals, assign) => {
15806
15625
  const lhs = left(scope, locals, assign);
15807
15626
  const rhs = right(scope, locals, assign);
15808
15627
  const arg = (isDefined(lhs) ? lhs : 0) - (isDefined(rhs) ? rhs : 0);
@@ -15818,14 +15637,14 @@
15818
15637
  * @returns {function} The binary multiplication function.
15819
15638
  */
15820
15639
  "binary*"(left, right, context) {
15821
- return function (scope, locals, assign) {
15640
+ return (scope, locals, assign) => {
15822
15641
  const arg = left(scope, locals, assign) * right(scope, locals, assign);
15823
15642
  return context ? { value: arg } : arg;
15824
15643
  };
15825
15644
  }
15826
15645
 
15827
15646
  "binary/"(left, right, context) {
15828
- return function (scope, locals, assign) {
15647
+ return (scope, locals, assign) => {
15829
15648
  const arg = left(scope, locals, assign) / right(scope, locals, assign);
15830
15649
  return context ? { value: arg } : arg;
15831
15650
  };
@@ -15839,7 +15658,7 @@
15839
15658
  * @returns {function} The binary division function.
15840
15659
  */
15841
15660
  "binary%"(left, right, context) {
15842
- return function (scope, locals, assign) {
15661
+ return (scope, locals, assign) => {
15843
15662
  const arg = left(scope, locals, assign) % right(scope, locals, assign);
15844
15663
  return context ? { value: arg } : arg;
15845
15664
  };
@@ -15853,7 +15672,7 @@
15853
15672
  * @returns {function} The binary strict equality function.
15854
15673
  */
15855
15674
  "binary==="(left, right, context) {
15856
- return function (scope, locals, assign) {
15675
+ return (scope, locals, assign) => {
15857
15676
  const arg = left(scope, locals, assign) === right(scope, locals, assign);
15858
15677
  return context ? { value: arg } : arg;
15859
15678
  };
@@ -15867,7 +15686,7 @@
15867
15686
  * @returns {function} The binary strict inequality function.
15868
15687
  */
15869
15688
  "binary!=="(left, right, context) {
15870
- return function (scope, locals, assign) {
15689
+ return (scope, locals, assign) => {
15871
15690
  const arg = left(scope, locals, assign) !== right(scope, locals, assign);
15872
15691
  return context ? { value: arg } : arg;
15873
15692
  };
@@ -15881,7 +15700,7 @@
15881
15700
  * @returns {function} The binary equality function.
15882
15701
  */
15883
15702
  "binary=="(left, right, context) {
15884
- return function (scope, locals, assign) {
15703
+ return (scope, locals, assign) => {
15885
15704
  const arg = left(scope, locals, assign) == right(scope, locals, assign);
15886
15705
  return context ? { value: arg } : arg;
15887
15706
  };
@@ -15895,7 +15714,7 @@
15895
15714
  * @returns {function} The binary inequality function.
15896
15715
  */
15897
15716
  "binary!="(left, right, context) {
15898
- return function (scope, locals, assign) {
15717
+ return (scope, locals, assign) => {
15899
15718
  const arg = left(scope, locals, assign) != right(scope, locals, assign);
15900
15719
  return context ? { value: arg } : arg;
15901
15720
  };
@@ -15909,7 +15728,7 @@
15909
15728
  * @returns {function} The binary less-than function.
15910
15729
  */
15911
15730
  "binary<"(left, right, context) {
15912
- return function (scope, locals, assign) {
15731
+ return (scope, locals, assign) => {
15913
15732
  const arg = left(scope, locals, assign) < right(scope, locals, assign);
15914
15733
  return context ? { value: arg } : arg;
15915
15734
  };
@@ -15923,7 +15742,7 @@
15923
15742
  * @returns {function} The binary greater-than function.
15924
15743
  */
15925
15744
  "binary>"(left, right, context) {
15926
- return function (scope, locals, assign) {
15745
+ return (scope, locals, assign) => {
15927
15746
  const arg = left(scope, locals, assign) > right(scope, locals, assign);
15928
15747
  return context ? { value: arg } : arg;
15929
15748
  };
@@ -15937,7 +15756,7 @@
15937
15756
  * @returns {function} The binary less-than-or-equal-to function.
15938
15757
  */
15939
15758
  "binary<="(left, right, context) {
15940
- return function (scope, locals, assign) {
15759
+ return (scope, locals, assign) => {
15941
15760
  const arg = left(scope, locals, assign) <= right(scope, locals, assign);
15942
15761
  return context ? { value: arg } : arg;
15943
15762
  };
@@ -15951,7 +15770,7 @@
15951
15770
  * @returns {function} The binary greater-than-or-equal-to function.
15952
15771
  */
15953
15772
  "binary>="(left, right, context) {
15954
- return function (scope, locals, assign) {
15773
+ return (scope, locals, assign) => {
15955
15774
  const arg = left(scope, locals, assign) >= right(scope, locals, assign);
15956
15775
  return context ? { value: arg } : arg;
15957
15776
  };
@@ -15978,7 +15797,7 @@
15978
15797
  * @returns {function} The binary logical OR function.
15979
15798
  */
15980
15799
  "binary||"(left, right, context) {
15981
- return function (scope, locals, assign) {
15800
+ return (scope, locals, assign) => {
15982
15801
  const arg = left(scope, locals, assign) || right(scope, locals, assign);
15983
15802
  return context ? { value: arg } : arg;
15984
15803
  };
@@ -15993,7 +15812,7 @@
15993
15812
  * @returns {function} The ternary conditional function.
15994
15813
  */
15995
15814
  "ternary?:"(test, alternate, consequent, context) {
15996
- return function (scope, locals, assign) {
15815
+ return (scope, locals, assign) => {
15997
15816
  const arg = test(scope, locals, assign)
15998
15817
  ? alternate(scope, locals, assign)
15999
15818
  : consequent(scope, locals, assign);
@@ -16008,9 +15827,8 @@
16008
15827
  * @returns {import("./interface.ts").CompiledExpressionFunction} The function returning the literal value.
16009
15828
  */
16010
15829
  value(value, context) {
16011
- return function () {
16012
- return context ? { context: undefined, name: undefined, value } : value;
16013
- };
15830
+ return () =>
15831
+ context ? { context: undefined, name: undefined, value } : value;
16014
15832
  }
16015
15833
 
16016
15834
  /**
@@ -16021,7 +15839,7 @@
16021
15839
  * @returns {import("./interface.ts").CompiledExpressionFunction} The function returning the identifier value.
16022
15840
  */
16023
15841
  identifier(name, context, create) {
16024
- return function (scope, locals) {
15842
+ return (scope, locals) => {
16025
15843
  const base = locals && name in locals ? locals : scope;
16026
15844
  if (create && create !== 1 && base && base[name] == null) {
16027
15845
  base[name] = {};
@@ -16046,7 +15864,7 @@
16046
15864
  * @returns {function} The function returning the computed member value.
16047
15865
  */
16048
15866
  computedMember(left, right, context, create) {
16049
- return function (scope, locals, assign) {
15867
+ return (scope, locals, assign) => {
16050
15868
  const lhs = left(scope, locals, assign);
16051
15869
  let rhs;
16052
15870
  let value;
@@ -16076,7 +15894,7 @@
16076
15894
  * @returns {function} The function returning the non-computed member value.
16077
15895
  */
16078
15896
  nonComputedMember(left, right, context, create) {
16079
- return function (scope, locals, assign) {
15897
+ return (scope, locals, assign) => {
16080
15898
  const lhs = left(scope, locals, assign);
16081
15899
  if (create && create !== 1) {
16082
15900
  if (lhs && lhs[right] == null) {
@@ -18497,21 +18315,17 @@
18497
18315
  });
18498
18316
 
18499
18317
  this.$get = [
18500
- "$browser",
18501
18318
  "$httpBackend",
18502
- "$rootScope",
18503
18319
  "$injector",
18504
18320
  "$sce",
18505
18321
  /**
18506
18322
  *
18507
- * @param {*} $browser
18508
18323
  * @param {*} $httpBackend
18509
- * @param {import("../../core/scope/scope.js").Scope} $rootScope
18510
18324
  * @param {import("../../core/di/internal-injector.js").InjectorService} $injector
18511
18325
  * @param {*} $sce
18512
18326
  * @returns
18513
18327
  */
18514
- function ($browser, $httpBackend, $rootScope, $injector, $sce) {
18328
+ function ($httpBackend, $injector, $sce) {
18515
18329
  /**
18516
18330
  * @type {Map<string, string>}
18517
18331
  */
@@ -18581,8 +18395,6 @@
18581
18395
  ? $injector.get(config.paramSerializer)
18582
18396
  : config.paramSerializer;
18583
18397
 
18584
- $browser.$$incOutstandingRequestCount("$http");
18585
-
18586
18398
  const requestInterceptors = [];
18587
18399
  const responseInterceptors = [];
18588
18400
  let promise = Promise.resolve(config);
@@ -18606,7 +18418,6 @@
18606
18418
  promise = chainInterceptors(promise, requestInterceptors);
18607
18419
  promise = promise.then(serverRequest);
18608
18420
  promise = chainInterceptors(promise, responseInterceptors);
18609
- promise = promise.finally(completeOutstandingRequest);
18610
18421
 
18611
18422
  return promise;
18612
18423
 
@@ -18623,10 +18434,6 @@
18623
18434
  return promise;
18624
18435
  }
18625
18436
 
18626
- function completeOutstandingRequest() {
18627
- $browser.$$completeOutstandingRequest(() => {}, "$http");
18628
- }
18629
-
18630
18437
  function executeHeaderFns(headers, config) {
18631
18438
  let headerContent;
18632
18439
  const processedHeaders = {};
@@ -19065,24 +18872,14 @@
19065
18872
  */
19066
18873
  class HttpBackendProvider {
19067
18874
  constructor() {
19068
- this.$get = [
19069
- "$browser",
19070
- /**
19071
- * @param {import('../browser.js').Browser} $browser
19072
- * @returns
19073
- */
19074
- function ($browser) {
19075
- return createHttpBackend($browser);
19076
- },
19077
- ];
18875
+ this.$get = [() => createHttpBackend()];
19078
18876
  }
19079
18877
  }
19080
18878
 
19081
18879
  /**
19082
- * @param {import('../browser.js').Browser} $browser
19083
18880
  * @returns
19084
18881
  */
19085
- function createHttpBackend($browser) {
18882
+ function createHttpBackend() {
19086
18883
  // TODO(vojta): fix the signature
19087
18884
  return function (
19088
18885
  method,
@@ -19096,7 +18893,7 @@
19096
18893
  eventHandlers,
19097
18894
  uploadEventHandlers,
19098
18895
  ) {
19099
- url = url || $browser.url();
18896
+ url = url || trimEmptyHash(window.location.href);
19100
18897
 
19101
18898
  const xhr = new XMLHttpRequest();
19102
18899
  let abortedByTimeout = false;
@@ -19304,7 +19101,7 @@
19304
19101
  */
19305
19102
  this.$$replace = false;
19306
19103
 
19307
- /** @type {import('../url-utils/url-utils').HttpProtocol} */
19104
+ /** @type {string} */
19308
19105
  this.$$protocol = parsedUrl.protocol;
19309
19106
 
19310
19107
  /** @type {string} */
@@ -19371,7 +19168,7 @@
19371
19168
  /**
19372
19169
  *
19373
19170
  * Return protocol of current URL.
19374
- * @return {import("../url-utils/url-utils").HttpProtocol} protocol of current URL
19171
+ * @return {string} protocol of current URL
19375
19172
  */
19376
19173
  protocol() {
19377
19174
  return this.$$protocol;
@@ -19672,12 +19469,13 @@
19672
19469
  * This object is exposed as $location service when developer doesn't opt into html5 mode.
19673
19470
  * It also serves as the base class for html5 mode fallback on legacy browsers.
19674
19471
  *
19675
- * @constructor
19676
- * @param {string} appBase application base URL
19677
- * @param {string} appBaseNoFile application base URL stripped of any filename
19678
- * @param {string} hashPrefix hashbang prefix
19679
19472
  */
19680
19473
  class LocationHashbangUrl extends Location {
19474
+ /**
19475
+ * @param {string} appBase application base URL
19476
+ * @param {string} appBaseNoFile application base URL stripped of any filename
19477
+ * @param {string} hashPrefix hashbang prefix
19478
+ */
19681
19479
  constructor(appBase, appBaseNoFile, hashPrefix) {
19682
19480
  super(appBase, appBaseNoFile);
19683
19481
  this.hashPrefix = hashPrefix;
@@ -19788,6 +19586,111 @@
19788
19586
  requireBase: true,
19789
19587
  rewriteLinks: true,
19790
19588
  };
19589
+
19590
+ /** @type {Array<import("./interface.js").UrlChangeListener>} */
19591
+ this.urlChangeListeners = [];
19592
+ this.urlChangeInit = false;
19593
+
19594
+ /** @type {History['state']} */
19595
+ this.cachedState = null;
19596
+ /** @typeof {History.state} */
19597
+ this.lastHistoryState = null;
19598
+ /** @type {string} */
19599
+ this.lastBrowserUrl = window.location.href;
19600
+ this.cacheState();
19601
+ }
19602
+
19603
+ /// ///////////////////////////////////////////////////////////
19604
+ // URL API
19605
+ /// ///////////////////////////////////////////////////////////
19606
+
19607
+ setUrl(url, state) {
19608
+ if (state === undefined) {
19609
+ state = null;
19610
+ }
19611
+
19612
+ // setter
19613
+ if (url) {
19614
+ url = urlResolve(url).href;
19615
+
19616
+ if (this.lastBrowserUrl === url && this.lastHistoryState === state) {
19617
+ return this;
19618
+ }
19619
+
19620
+ this.lastBrowserUrl = url;
19621
+ this.lastHistoryState = state;
19622
+ history.pushState(state, "", url);
19623
+ this.cacheState();
19624
+ }
19625
+ }
19626
+
19627
+ /**
19628
+ * Returns the current URL with any empty hash (`#`) removed.
19629
+ * @return {string}
19630
+ */
19631
+ getUrl() {
19632
+ return trimEmptyHash(window.location.href);
19633
+ }
19634
+
19635
+ /**
19636
+ * Returns the cached state.
19637
+ * @returns {History['state']} The cached state.
19638
+ */
19639
+ state() {
19640
+ return this.cachedState;
19641
+ }
19642
+
19643
+ /**
19644
+ * Caches the current state.
19645
+ *
19646
+ * @private
19647
+ */
19648
+ cacheState() {
19649
+ const currentState = history.state ?? null;
19650
+ if (!equals$1(currentState, this.lastCachedState)) {
19651
+ this.cachedState = currentState;
19652
+ this.lastCachedState = currentState;
19653
+ this.lastHistoryState = currentState;
19654
+ }
19655
+ }
19656
+
19657
+ /**
19658
+ * Fires the state or URL change event.
19659
+ *
19660
+ * @private
19661
+ */
19662
+ fireStateOrUrlChange() {
19663
+ const prevLastHistoryState = this.lastHistoryState;
19664
+ this.cacheState();
19665
+ if (
19666
+ this.lastBrowserUrl === this.getUrl() &&
19667
+ prevLastHistoryState === this.cachedState
19668
+ ) {
19669
+ return;
19670
+ }
19671
+ this.lastBrowserUrl = this.getUrl();
19672
+ this.lastHistoryState = this.cachedState;
19673
+ this.urlChangeListeners.forEach((listener) => {
19674
+ listener(trimEmptyHash(window.location.href), this.cachedState);
19675
+ });
19676
+ }
19677
+
19678
+ /**
19679
+ * Registers a callback to be called when the URL changes.
19680
+ *
19681
+ * @param {import("./interface.js").UrlChangeListener} callback - The callback function to register.
19682
+ * @returns void
19683
+ */
19684
+ onUrlChange(callback) {
19685
+ if (!this.urlChangeInit) {
19686
+ window.addEventListener("popstate", this.fireStateOrUrlChange.bind(this));
19687
+ window.addEventListener(
19688
+ "hashchange",
19689
+ this.fireStateOrUrlChange.bind(this),
19690
+ );
19691
+ this.urlChangeInit = true;
19692
+ }
19693
+ this.urlChangeListeners.push(callback);
19791
19694
  }
19792
19695
 
19793
19696
  /**
@@ -19849,21 +19752,19 @@
19849
19752
 
19850
19753
  $get = [
19851
19754
  "$rootScope",
19852
- "$browser",
19853
19755
  "$rootElement",
19854
19756
  /**
19855
19757
  *
19856
- * @param {import('../scope/scope.js').Scope} $rootScope
19857
- * @param {import('../../services/browser').Browser} $browser
19758
+ * @param {import('../../core/scope/scope.js').Scope} $rootScope
19858
19759
  * @param {Element} $rootElement
19859
19760
  * @returns
19860
19761
  */
19861
- ($rootScope, $browser, $rootElement) => {
19762
+ ($rootScope, $rootElement) => {
19862
19763
  /** @type {Location} */
19863
19764
  let $location;
19864
19765
  let LocationMode;
19865
- const baseHref = $browser.baseHref(); // if base[href] is undefined, it defaults to ''
19866
- const initialUrl = /** @type {string} */ ($browser.url());
19766
+ const baseHref = getBaseHref(); // if base[href] is undefined, it defaults to ''
19767
+ const initialUrl = trimEmptyHash(window.location.href);
19867
19768
  let appBase;
19868
19769
 
19869
19770
  if (this.getHtml5Mode().enabled) {
@@ -19888,20 +19789,20 @@
19888
19789
  );
19889
19790
  $location.$$parseLinkUrl(initialUrl, initialUrl);
19890
19791
 
19891
- $location.$$state = $browser.state();
19792
+ $location.$$state = this.state();
19892
19793
 
19893
19794
  const IGNORE_URI_REGEXP = /^\s*(javascript|mailto):/i;
19894
19795
 
19895
- function setBrowserUrlWithFallback(url, state) {
19796
+ const setBrowserUrlWithFallback = (url, state) => {
19896
19797
  const oldUrl = $location.url();
19897
19798
  const oldState = $location.$$state;
19898
19799
  try {
19899
- $browser.url(url, state);
19800
+ this.setUrl(url, state);
19900
19801
 
19901
19802
  // Make sure $location.state() returns referentially identical (not just deeply equal)
19902
19803
  // state object; this makes possible quick checking if the state changed in the digest
19903
19804
  // loop. Checking deep equality would be too expensive.
19904
- $location.$$state = $browser.state();
19805
+ $location.$$state = this.state();
19905
19806
  } catch (e) {
19906
19807
  // Restore old values if pushState fails
19907
19808
  $location.url(/** @type {string} */ (oldUrl));
@@ -19909,7 +19810,7 @@
19909
19810
 
19910
19811
  throw e;
19911
19812
  }
19912
- }
19813
+ };
19913
19814
 
19914
19815
  $rootElement.addEventListener(
19915
19816
  "click",
@@ -19977,10 +19878,6 @@
19977
19878
  // in html5mode and also without, so that we are able to abort navigation without
19978
19879
  // getting double entries in the location history.
19979
19880
  event.preventDefault();
19980
- // update location manually
19981
- // if ($location.absUrl() !== $browser.url()) {
19982
- // $rootScope.$apply();
19983
- // }
19984
19881
  }
19985
19882
  }
19986
19883
  },
@@ -19988,20 +19885,20 @@
19988
19885
 
19989
19886
  // rewrite hashbang url <> html5 url
19990
19887
  if ($location.absUrl() !== initialUrl) {
19991
- $browser.url($location.absUrl(), true);
19888
+ this.setUrl($location.absUrl(), true);
19992
19889
  }
19993
19890
 
19994
19891
  let initializing = true;
19995
19892
 
19996
19893
  // update $location when $browser url changes
19997
- $browser.onUrlChange((newUrl, newState) => {
19894
+ this.onUrlChange((newUrl, newState) => {
19998
19895
  if (!startsWith(newUrl, appBaseNoFile)) {
19999
19896
  // If we are navigating outside of the app then force a reload
20000
19897
  window.location.href = newUrl;
20001
19898
  return;
20002
19899
  }
20003
19900
 
20004
- $rootScope.$evalAsync(() => {
19901
+ Promise.resolve().then(() => {
20005
19902
  const oldUrl = $location.absUrl();
20006
19903
  const oldState = $location.$$state;
20007
19904
  let defaultPrevented;
@@ -20036,9 +19933,9 @@
20036
19933
  if (initializing || $location.$$urlUpdatedByLocation) {
20037
19934
  $location.$$urlUpdatedByLocation = false;
20038
19935
 
20039
- const oldUrl = /** @type {string} */ ($browser.url());
19936
+ const oldUrl = /** @type {string} */ (this.getUrl());
20040
19937
  const newUrl = $location.absUrl();
20041
- const oldState = $browser.state();
19938
+ const oldState = this.state();
20042
19939
  const urlOrStateChanged =
20043
19940
  !urlsEqual(oldUrl, newUrl) ||
20044
19941
  ($location.$$html5 && oldState !== $location.$$state);
@@ -20297,7 +20194,7 @@
20297
20194
  */
20298
20195
  let $parse;
20299
20196
 
20300
- /**@type {import('../exception-handler.js').ErrorHandler} */
20197
+ /**@type {import('../../services/exception/exception-handler.js').ErrorHandler} */
20301
20198
  let $exceptionHandler;
20302
20199
 
20303
20200
  /**
@@ -20318,7 +20215,7 @@
20318
20215
  "$exceptionHandler",
20319
20216
  "$parse",
20320
20217
  /**
20321
- * @param {import('../exception-handler.js').ErrorHandler} exceptionHandler
20218
+ * @param {import('../../services/exception/exception-handler.js').ErrorHandler} exceptionHandler
20322
20219
  * @param {import('../parse/interface.ts').ParseService} parse
20323
20220
  */
20324
20221
  (exceptionHandler, parse) => {
@@ -20729,7 +20626,6 @@
20729
20626
  $destroy: this.$destroy.bind(this),
20730
20627
  $eval: this.$eval.bind(this),
20731
20628
  $apply: this.$apply.bind(this),
20732
- $evalAsync: this.$evalAsync.bind(this),
20733
20629
  $postUpdate: this.$postUpdate.bind(this),
20734
20630
  $isRoot: this.#isRoot.bind(this),
20735
20631
  $target: target,
@@ -21235,10 +21131,6 @@
21235
21131
  return res;
21236
21132
  }
21237
21133
 
21238
- async $evalAsync(expr, locals) {
21239
- return await this.$eval(expr, locals);
21240
- }
21241
-
21242
21134
  /**
21243
21135
  * @param {Object} newTarget
21244
21136
  */
@@ -21520,152 +21412,6 @@
21520
21412
  return ids;
21521
21413
  }
21522
21414
 
21523
- /** @typedef {import('../interface.ts').ServiceProvider} ServiceProvider */
21524
- /** @typedef {import('../interface.ts').AnnotatedFactory} AnnotatedFactory */
21525
-
21526
- /**
21527
- * @implements {ServiceProvider}
21528
- */
21529
- class TaskTrackerFactoryProvider {
21530
- /** @type {AnnotatedFactory} */
21531
- $get = [
21532
- "$log",
21533
- /**
21534
- * Creates a new `TaskTracker` instance.
21535
- *
21536
- * @param {import('../services/log/interface.ts').LogService} log - The logging service.
21537
- * @returns {TaskTracker} A new `TaskTracker` instance.
21538
- */
21539
- (log) => new TaskTracker(log),
21540
- ];
21541
- }
21542
-
21543
- /**
21544
- * A factory function to create `TaskTracker` instances.
21545
- *
21546
- * A `TaskTracker` tracks pending tasks (grouped by type) and notifies interested
21547
- * parties when all pending tasks (or tasks of a specific type) have been completed.
21548
- */
21549
- class TaskTracker {
21550
- /**
21551
- * @param {import('../services/log/interface.ts').LogService} log - The logging service.
21552
- */
21553
- constructor(log) {
21554
- /** @private */
21555
- this.log = log;
21556
-
21557
- /** @private */
21558
- this.taskCounts = {};
21559
-
21560
- /** @private */
21561
- this.taskCallbacks = [];
21562
-
21563
- /**
21564
- * Special task types used for tracking all tasks and default tasks.
21565
- * @type {string}
21566
- */
21567
- this.ALL_TASKS_TYPE = "$$all$$";
21568
-
21569
- /**
21570
- * Default task type.
21571
- * @type {string}
21572
- */
21573
- this.DEFAULT_TASK_TYPE = "$$default$$";
21574
- }
21575
-
21576
- /**
21577
- * Completes a task and decrements the associated task counter.
21578
- * If the counter reaches 0, all corresponding callbacks are executed.
21579
- *
21580
- * @param {Function} fn - The function to execute when completing the task.
21581
- * @param {string} [taskType=this.DEFAULT_TASK_TYPE] - The type of task being completed.
21582
- */
21583
- completeTask(fn, taskType = this.DEFAULT_TASK_TYPE) {
21584
- try {
21585
- fn();
21586
- } finally {
21587
- if (this.taskCounts[taskType]) {
21588
- this.taskCounts[taskType]--;
21589
- this.taskCounts[this.ALL_TASKS_TYPE]--;
21590
- }
21591
-
21592
- const countForType = this.taskCounts[taskType];
21593
- const countForAll = this.taskCounts[this.ALL_TASKS_TYPE];
21594
-
21595
- // If either the overall task queue or the specific task type queue is empty, run callbacks.
21596
- if (!countForAll || !countForType) {
21597
- const getNextCallback = !countForAll
21598
- ? this.getLastCallback.bind(this)
21599
- : () => this.getLastCallbackForType(taskType);
21600
-
21601
- let nextCb;
21602
- while ((nextCb = getNextCallback())) {
21603
- try {
21604
- nextCb();
21605
- } catch (e) {
21606
- this.log.error(e);
21607
- }
21608
- }
21609
- }
21610
- }
21611
- }
21612
-
21613
- /**
21614
- * Increments the task count for the specified task type.
21615
- *
21616
- * @param {string} [taskType=this.DEFAULT_TASK_TYPE] - The type of task whose count will be increased.
21617
- */
21618
- incTaskCount(taskType = this.DEFAULT_TASK_TYPE) {
21619
- this.taskCounts[taskType] = (this.taskCounts[taskType] || 0) + 1;
21620
- this.taskCounts[this.ALL_TASKS_TYPE] =
21621
- (this.taskCounts[this.ALL_TASKS_TYPE] || 0) + 1;
21622
- }
21623
-
21624
- /**
21625
- * Registers a callback to be executed when all pending tasks of the specified type are completed.
21626
- * If there are no pending tasks of the specified type, the callback is executed immediately.
21627
- *
21628
- * @param {Function} callback - The function to execute when no pending tasks remain.
21629
- * @param {string} [taskType=this.ALL_TASKS_TYPE] - The type of tasks to wait for completion.
21630
- */
21631
- notifyWhenNoPendingTasks(callback, taskType = this.ALL_TASKS_TYPE) {
21632
- if (!this.taskCounts[taskType]) {
21633
- callback();
21634
- } else {
21635
- this.taskCallbacks.push({ type: taskType, cb: callback });
21636
- }
21637
- }
21638
-
21639
- /**
21640
- * Retrieves and removes the last registered callback from the queue.
21641
- *
21642
- * @private
21643
- * @returns {Function|undefined} The last callback function or undefined if none exist.
21644
- */
21645
- getLastCallback() {
21646
- const cbInfo = this.taskCallbacks.pop();
21647
- return cbInfo ? cbInfo.cb : undefined;
21648
- }
21649
-
21650
- /**
21651
- * Retrieves and removes the last registered callback for the specified task type.
21652
- *
21653
- * @private
21654
- * @param {string} taskType - The type of task for which the callback was registered.
21655
- * @returns {Function|undefined} The last callback function for the task type, or undefined if none exist.
21656
- */
21657
- getLastCallbackForType(taskType) {
21658
- for (let i = this.taskCallbacks.length - 1; i >= 0; --i) {
21659
- const cbInfo = this.taskCallbacks[i];
21660
- if (cbInfo.type === taskType) {
21661
- this.taskCallbacks.splice(i, 1);
21662
- return cbInfo.cb;
21663
- }
21664
- }
21665
- return undefined;
21666
- }
21667
- }
21668
-
21669
21415
  const $templateRequestMinErr = minErr("$templateRequest");
21670
21416
 
21671
21417
  /**
@@ -21725,7 +21471,7 @@
21725
21471
  "$sce",
21726
21472
  /**
21727
21473
  *
21728
- * @param {import('../core/exception-handler.js').ErrorHandler} $exceptionHandler
21474
+ * @param {import('./exception/exception-handler.js').ErrorHandler} $exceptionHandler
21729
21475
  * @param {import('../services/template-cache/interface.ts').TemplateCache} $templateCache
21730
21476
  * @param {import("interface.ts").HttpService} $http
21731
21477
  * @param {*} $sce
@@ -21740,6 +21486,7 @@
21740
21486
  // resources for keys that already are included in there. This also makes
21741
21487
  // AngularTS accept any script directive, no matter its name. However, we
21742
21488
  // still need to unwrap trusted types.
21489
+
21743
21490
  if (!isString(tpl) || !$templateCache.has(tpl)) {
21744
21491
  try {
21745
21492
  tpl = $sce.getTrustedResourceUrl(tpl);
@@ -21805,7 +21552,7 @@
21805
21552
  ];
21806
21553
  }
21807
21554
 
21808
- /** @typedef {import('../../interface.ts').ServiceProvider} ServiceProvider } */
21555
+ /** @typedef {import('../../interface.ts').ServiceProvider} ServiceProvider */
21809
21556
 
21810
21557
  /**
21811
21558
  * Private service to sanitize uris for links and images. Used by $compile.
@@ -21857,7 +21604,7 @@
21857
21604
  }
21858
21605
 
21859
21606
  /**
21860
- * @returns {import("./interface.js").SanitizerFn} Sanitizer function.
21607
+ * @returns {import("./interface").SanitizerFn}
21861
21608
  */
21862
21609
  $get() {
21863
21610
  return (uri, isMediaUrl) => {
@@ -21981,7 +21728,7 @@
21981
21728
  reRender() {
21982
21729
  if (!this.renderLater) {
21983
21730
  this.renderLater = true;
21984
- this.$scope.$evalAsync(() => {
21731
+ Promise.resolve().then(() => {
21985
21732
  if (this.renderLater && this.cachedCollection) {
21986
21733
  this.render(this.cachedCollection);
21987
21734
  }
@@ -22114,6 +21861,10 @@
22114
21861
  const ngMessageExpDirective = ngMessageDirectiveFactory(false);
22115
21862
  const ngMessageDefaultDirective = ngMessageDirectiveFactory(true);
22116
21863
 
21864
+ /**
21865
+ * @param {boolean} isDefault
21866
+ * @returns {(any) => import("../../interface.js").Directive}
21867
+ */
22117
21868
  function ngMessageDirectiveFactory(isDefault) {
22118
21869
  ngMessageDirective.$inject = ["$animate"];
22119
21870
  function ngMessageDirective($animate) {
@@ -25194,7 +24945,7 @@
25194
24945
 
25195
24946
  /**
25196
24947
  * Service provider that creates a requestAnimationFrame-based scheduler.
25197
- * @implements {ServiceProvider}
24948
+ * @type {ServiceProvider}
25198
24949
  */
25199
24950
  class RafSchedulerProvider {
25200
24951
  constructor() {
@@ -26946,7 +26697,6 @@
26946
26697
  *
26947
26698
  * This is where we hold the global mutable state such as current state, current
26948
26699
  * params, current transition, etc.
26949
- * @implements {ServiceProvider}
26950
26700
  */
26951
26701
  class RouterGlobals {
26952
26702
  constructor() {
@@ -29587,6 +29337,11 @@
29587
29337
  */
29588
29338
  this.regexp = new RegExp("^" + regexpString + "$");
29589
29339
  }
29340
+
29341
+ /**
29342
+ * @param {string} name
29343
+ * @return {boolean}
29344
+ */
29590
29345
  matches(name) {
29591
29346
  return this.regexp.test("." + name);
29592
29347
  }
@@ -33521,7 +33276,7 @@
33521
33276
  ];
33522
33277
 
33523
33278
  /**
33524
- * @param {import("../../core/location/location").LocationProvider} $locationProvider
33279
+ * @param {import("../../services/location/location").LocationProvider} $locationProvider
33525
33280
  * @param {import("../../router/state/state-service.js").StateProvider} stateService
33526
33281
  * @param globals
33527
33282
  * @param {import("../../router/url/url-config.js").UrlConfigProvider} urlConfigProvider
@@ -33530,9 +33285,7 @@
33530
33285
  this.stateService = stateService;
33531
33286
  this.stateService.urlService = this; // circular wiring
33532
33287
  this.$locationProvider = $locationProvider;
33533
-
33534
33288
  this.$location = undefined;
33535
- this.$browser = undefined;
33536
33289
 
33537
33290
  /** Provides services related to the URL */
33538
33291
  this.urlRuleFactory = new UrlRuleFactory(this, this.stateService, globals);
@@ -33585,18 +33338,15 @@
33585
33338
 
33586
33339
  $get = [
33587
33340
  "$location",
33588
- "$browser",
33589
33341
  "$rootScope",
33590
33342
  /**
33591
33343
  *
33592
- * @param {import('../../core/location/location.js').Location} $location
33593
- * @param {import('../../services/browser.js').Browser} $browser
33344
+ * @param {import('../../services/location/location.js').Location} $location
33594
33345
  * @param {import('../../core/scope/scope.js').Scope} $rootScope
33595
33346
  * @returns {UrlService}
33596
33347
  */
33597
- ($location, $browser, $rootScope) => {
33348
+ ($location, $rootScope) => {
33598
33349
  this.$location = $location;
33599
- this.$browser = $browser;
33600
33350
  $rootScope.$on("$locationChangeSuccess", (evt) => {
33601
33351
  this._urlListeners.forEach((fn) => {
33602
33352
  fn(evt);
@@ -33620,7 +33370,7 @@
33620
33370
  baseHref() {
33621
33371
  return (
33622
33372
  this._baseHref ||
33623
- (this._baseHref = this.$browser.baseHref() || window.location.pathname)
33373
+ (this._baseHref = getBaseHref() || window.location.pathname)
33624
33374
  );
33625
33375
  }
33626
33376
 
@@ -34467,7 +34217,6 @@
34467
34217
  *
34468
34218
  * This API is found at `$stateRegistry` ([[UIRouter.stateRegistry]])
34469
34219
  *
34470
- * @implements {ServiceProvider}
34471
34220
  */
34472
34221
  class StateRegistryProvider {
34473
34222
  static $inject = provider([
@@ -35096,12 +34845,10 @@
35096
34845
  const removeClasses = allClasses.filter(
35097
34846
  (cls) => !addClasses.includes(cls),
35098
34847
  );
35099
- $scope.$evalAsync(() => {
35100
- addClasses.forEach((className) => $element.classList.add(className));
35101
- removeClasses.forEach((className) =>
35102
- $element.classList.remove(className),
35103
- );
35104
- });
34848
+ addClasses.forEach((className) => $element.classList.add(className));
34849
+ removeClasses.forEach((className) =>
34850
+ $element.classList.remove(className),
34851
+ );
35105
34852
  }
35106
34853
  update();
35107
34854
  },
@@ -35233,11 +34980,20 @@
35233
34980
  * });
35234
34981
  * ```
35235
34982
  */
34983
+
34984
+ /** @type {import("../../interface.js").AnnotatedDirectiveFactory} */
35236
34985
  let ngView = [
35237
34986
  "$view",
35238
34987
  "$animate",
35239
34988
  "$ngViewScroll",
35240
34989
  "$interpolate",
34990
+ /**
34991
+ * @param {*} $view
34992
+ * @param {*} $animate
34993
+ * @param {*} $ngViewScroll
34994
+ * @param {*} $interpolate
34995
+ * @returns {import("../../interface.js").Directive}
34996
+ */
35241
34997
  function $ViewDirective($view, $animate, $ngViewScroll, $interpolate) {
35242
34998
  function getRenderer() {
35243
34999
  return {
@@ -35268,7 +35024,6 @@
35268
35024
  };
35269
35025
  const directive = {
35270
35026
  count: 0,
35271
-
35272
35027
  terminal: true,
35273
35028
  priority: 400,
35274
35029
  transclude: "element",
@@ -35605,11 +35360,12 @@
35605
35360
  };
35606
35361
  }
35607
35362
 
35608
- ngSetterDirective.$inject = ["$parse", "$log"];
35363
+ ngSetterDirective.$inject = [$injectTokens.$parse, $injectTokens.$log];
35364
+
35609
35365
  /**
35610
35366
  * @param {import('../../core/parse/interface.ts').ParseService} $parse
35611
35367
  * @param {import('../../services/log/interface.ts').LogService} $log
35612
- * @returns {import('../../interface.ts').Directive}
35368
+ * @returns {import('interface.ts').Directive}
35613
35369
  */
35614
35370
  function ngSetterDirective($parse, $log) {
35615
35371
  return {
@@ -35618,19 +35374,19 @@
35618
35374
  const modelExpression = attrs["ngSetter"];
35619
35375
 
35620
35376
  if (!modelExpression) {
35621
- $log.warn("ngSetter: Model expression is not provided.");
35377
+ $log.warn("ng-setter: expression null");
35622
35378
  return;
35623
35379
  }
35624
35380
 
35625
35381
  const assignModel = $parse(modelExpression).assign;
35626
35382
 
35627
35383
  if (!assignModel) {
35628
- $log.warn("ngSetter: Invalid model expression.");
35384
+ $log.warn("ng-setter: expression invalid");
35629
35385
  return;
35630
35386
  }
35631
35387
 
35632
35388
  const updateModel = (value) => {
35633
- assignModel(scope, value);
35389
+ assignModel(scope, value.trim());
35634
35390
  };
35635
35391
 
35636
35392
  const observer = new MutationObserver((mutationsList) => {
@@ -35650,16 +35406,11 @@
35650
35406
  }
35651
35407
  });
35652
35408
 
35653
- if (element && element) {
35654
- observer.observe(element, {
35655
- childList: true,
35656
- subtree: true,
35657
- characterData: true,
35658
- });
35659
- } else {
35660
- $log.warn("ngSetter: Element is not a valid DOM node.");
35661
- return;
35662
- }
35409
+ observer.observe(element, {
35410
+ childList: true,
35411
+ subtree: true,
35412
+ characterData: true,
35413
+ });
35663
35414
 
35664
35415
  scope.$on("$destroy", () => observer.disconnect());
35665
35416
  updateModel(element.innerHTML);
@@ -35674,13 +35425,20 @@
35674
35425
  function defineDirective(method) {
35675
35426
  const attrName = "ng" + method.charAt(0).toUpperCase() + method.slice(1);
35676
35427
  const directive = createHttpDirective(method, attrName);
35677
- directive["$inject"] = ["$http", "$compile", "$log"];
35428
+ directive["$inject"] = [$injectTokens.$http, $injectTokens.$compile, $injectTokens.$log, $injectTokens.$parse, $injectTokens.$state];
35678
35429
  return directive;
35679
35430
  }
35680
35431
 
35432
+ /** @type {import('../../interface.ts').DirectiveFactory} */
35681
35433
  const ngGetDirective = defineDirective("get");
35434
+
35435
+ /** @type {import('../../interface.ts').DirectiveFactory} */
35682
35436
  const ngDeleteDirective = defineDirective("delete");
35437
+
35438
+ /** @type {import('../../interface.ts').DirectiveFactory} */
35683
35439
  const ngPostDirective = defineDirective("post");
35440
+
35441
+ /** @type {import('../../interface.ts').DirectiveFactory} */
35684
35442
  const ngPutDirective = defineDirective("put");
35685
35443
 
35686
35444
  /**
@@ -35707,7 +35465,7 @@
35707
35465
  * Handles DOM manipulation based on a swap strategy and server-rendered HTML.
35708
35466
  *
35709
35467
  * @param {string} html - The HTML string returned from the server.
35710
- * @param {import("../../interface.ts").SwapInsertPosition} swap
35468
+ * @param {import("../../interface.ts").SwapModeType} swap
35711
35469
  * @param {Element} target - The target DOM element to apply the swap to.
35712
35470
  * @param {import('../../core/scope/scope.js').Scope} scope
35713
35471
  * @param {import('../../core/compile/compile.js').CompileFn} $compile
@@ -35798,9 +35556,11 @@
35798
35556
  * @param {import("interface.ts").HttpService} $http
35799
35557
  * @param {import("../../core/compile/compile.js").CompileFn} $compile
35800
35558
  * @param {import("../../services/log/interface.ts").LogService} $log
35559
+ * @param {import("../../core/parse/interface.ts").ParseService} $parse
35560
+ * @param {import("../../router/state/state-service.js").StateProvider} $state
35801
35561
  * @returns {import('../../interface.ts').Directive}
35802
35562
  */
35803
- return function ($http, $compile, $log) {
35563
+ return function ($http, $compile, $log, $parse, $state) {
35804
35564
  /**
35805
35565
  * Collects form data from the element or its associated form.
35806
35566
  *
@@ -35861,16 +35621,38 @@
35861
35621
  restrict: "A",
35862
35622
  terminal: true,
35863
35623
  link(scope, element, attrs) {
35864
- /** @type {EventType} */
35865
- const eventName = getEventNameForElement(element);
35624
+ const eventName =
35625
+ attrs["trigger"] ||
35626
+ /** @type {EventType} */ getEventNameForElement(element);
35627
+
35866
35628
  const tag = element.tagName.toLowerCase();
35867
35629
 
35868
- element.addEventListener(eventName, (event) => {
35630
+ if (isDefined(attrs["latch"])) {
35631
+ attrs.$observe(
35632
+ "latch",
35633
+ callBackAfterFirst(() =>
35634
+ element.dispatchEvent(new Event(eventName)),
35635
+ ),
35636
+ );
35637
+ }
35638
+
35639
+ let throttled = false;
35640
+ let intervalId;
35641
+
35642
+ if (isDefined(attrs["interval"])) {
35643
+ element.dispatchEvent(new Event(eventName));
35644
+ intervalId = setInterval(
35645
+ () => element.dispatchEvent(new Event(eventName)),
35646
+ parseInt(attrs["interval"]) || 1000,
35647
+ );
35648
+ }
35649
+
35650
+ element.addEventListener(eventName, async (event) => {
35869
35651
  if (/** @type {HTMLButtonElement} */ (element).disabled) return;
35870
35652
  if (tag === "form") event.preventDefault();
35871
35653
 
35872
- const swap = element.dataset.swap || "innerHTML";
35873
- const targetSelector = element.dataset.target;
35654
+ const swap = attrs["swap"] || "innerHTML";
35655
+ const targetSelector = attrs["target"];
35874
35656
  const target = targetSelector
35875
35657
  ? document.querySelector(targetSelector)
35876
35658
  : element;
@@ -35887,18 +35669,67 @@
35887
35669
  }
35888
35670
 
35889
35671
  const handler = (res) => {
35672
+ if (isDefined(attrs["loading"])) {
35673
+ attrs.$set("loading", false);
35674
+ }
35675
+
35676
+ if (isDefined(attrs["loadingClass"])) {
35677
+ attrs.$removeClass(attrs["loadingClass"]);
35678
+ }
35679
+
35890
35680
  const html = res.data;
35681
+ if (200 <= res.status && res.status <= 299) {
35682
+ if (isDefined(attrs["success"])) {
35683
+ $parse(attrs["success"])(scope, { $res: html });
35684
+ }
35685
+
35686
+ if (isDefined(attrs["stateSuccess"])) {
35687
+ $state.go(attrs["stateSuccess"]);
35688
+ }
35689
+ } else if (400 <= res.status && res.status <= 599) {
35690
+ if (isDefined(attrs["error"])) {
35691
+ $parse(attrs["error"])(scope, { $res: html });
35692
+ }
35693
+
35694
+ if (isDefined(attrs["stateError"])) {
35695
+ $state.go(attrs["stateError"]);
35696
+ }
35697
+ }
35698
+
35891
35699
  handleSwapResponse(
35892
35700
  html,
35893
- /** @type {import("../../interface.ts").SwapInsertPosition} */ (
35894
- swap
35895
- ),
35701
+ /** @type {import("../../interface.ts").SwapModeType} */ (swap),
35896
35702
  target,
35897
35703
  scope,
35898
35704
  $compile,
35899
35705
  );
35900
35706
  };
35901
35707
 
35708
+ if (isDefined(attrs["delay"])) {
35709
+ await wait(parseInt(attrs["delay"]) | 0);
35710
+ }
35711
+
35712
+ if (throttled) {
35713
+ return;
35714
+ }
35715
+
35716
+ if (isDefined(attrs["throttle"])) {
35717
+ throttled = true;
35718
+ attrs.$set("throttled", true);
35719
+ setTimeout(() => {
35720
+ attrs.$set("throttled", false);
35721
+ throttled = false;
35722
+ }, parseInt(attrs["throttle"]));
35723
+ }
35724
+
35725
+ if (isDefined(attrs["loading"])) {
35726
+ attrs.$set("loading", true);
35727
+ }
35728
+
35729
+ if (isDefined(attrs["loadingClass"])) {
35730
+ attrs.$addClass(attrs["loadingClass"]);
35731
+ }
35732
+
35902
35733
  if (method === "post" || method === "put") {
35903
35734
  const data = collectFormData(element);
35904
35735
  $http[method](url, data).then(handler).catch(handler);
@@ -35906,6 +35737,8 @@
35906
35737
  $http[method](url).then(handler).catch(handler);
35907
35738
  }
35908
35739
  });
35740
+
35741
+ scope.$on("$destroy", () => clearInterval(intervalId));
35909
35742
  },
35910
35743
  };
35911
35744
  };
@@ -35917,13 +35750,13 @@
35917
35750
  * @returns {import('./core/di/ng-module.js').NgModule} `ng` module
35918
35751
  */
35919
35752
  function registerNgModule(angular) {
35920
- const ng = angular
35753
+ return angular
35921
35754
  .module(
35922
35755
  "ng",
35923
35756
  [],
35924
35757
  [
35925
35758
  "$provide",
35926
- /** @type {import('./interface.js').Provider} */
35759
+ /** @param {import("./interface.js").Provider} $provide */
35927
35760
  ($provide) => {
35928
35761
  // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
35929
35762
  $provide.provider({
@@ -36024,7 +35857,6 @@
36024
35857
  $$animateQueue: AnimateQueueProvider,
36025
35858
  $$AnimateRunner: AnimateRunnerFactoryProvider,
36026
35859
  $$animateAsyncRun: AnimateAsyncRunFactoryProvider,
36027
- $browser: BrowserProvider,
36028
35860
  $controller: ControllerProvider,
36029
35861
  $exceptionHandler: ExceptionHandlerProvider,
36030
35862
  $filter: FilterProvider,
@@ -36040,7 +35872,6 @@
36040
35872
  $routerGlobals: RouterGlobals,
36041
35873
  $sce: SceProvider,
36042
35874
  $sceDelegate: SceDelegateProvider,
36043
- $$taskTrackerFactory: TaskTrackerFactoryProvider,
36044
35875
  $templateCache: TemplateCacheProvider,
36045
35876
  $templateRequest: TemplateRequestProvider,
36046
35877
  $urlConfig: UrlConfigProvider,
@@ -36067,8 +35898,6 @@
36067
35898
  },
36068
35899
  ])
36069
35900
  .value("$trace", trace);
36070
-
36071
- return ng;
36072
35901
  }
36073
35902
 
36074
35903
  const ngMinErr = minErr("ng");
@@ -36094,7 +35923,7 @@
36094
35923
  /**
36095
35924
  * @type {string} `version` from `package.json`
36096
35925
  */
36097
- this.version = "0.7.5"; //inserted via rollup plugin
35926
+ this.version = "0.7.8"; //inserted via rollup plugin
36098
35927
 
36099
35928
  /** @type {!Array<string|any>} */
36100
35929
  this.bootsrappedModules = [];
@@ -36334,12 +36163,7 @@
36334
36163
  name,
36335
36164
  );
36336
36165
  }
36337
- const moduleInstance = new NgModule(
36338
- name,
36339
- requires,
36340
- /** @type {Function} */ (configFn),
36341
- );
36342
- return moduleInstance;
36166
+ return new NgModule(name, requires, /** @type {Function} */ (configFn));
36343
36167
  });
36344
36168
  }
36345
36169
  }