UNPKG

10.6 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.UrlService = void 0;
4var common_1 = require("../common");
5var urlRules_1 = require("./urlRules");
6var urlConfig_1 = require("./urlConfig");
7var state_1 = require("../state");
8/**
9 * API for URL management
10 */
11var UrlService = /** @class */ (function () {
12 /** @internal */
13 function UrlService(/** @internal */ router) {
14 var _this = this;
15 this.router = router;
16 /** @internal */ this.interceptDeferred = false;
17 /**
18 * The nested [[UrlRules]] API for managing URL rules and rewrites
19 *
20 * See: [[UrlRules]] for details
21 */
22 this.rules = new urlRules_1.UrlRules(this.router);
23 /**
24 * The nested [[UrlConfig]] API to configure the URL and retrieve URL information
25 *
26 * See: [[UrlConfig]] for details
27 */
28 this.config = new urlConfig_1.UrlConfig(this.router);
29 // Delegate these calls to the current LocationServices implementation
30 /**
31 * Gets the current url, or updates the url
32 *
33 * ### Getting the current URL
34 *
35 * When no arguments are passed, returns the current URL.
36 * The URL is normalized using the internal [[path]]/[[search]]/[[hash]] values.
37 *
38 * For example, the URL may be stored in the hash ([[HashLocationServices]]) or
39 * have a base HREF prepended ([[PushStateLocationServices]]).
40 *
41 * The raw URL in the browser might be:
42 *
43 * ```
44 * http://mysite.com/somepath/index.html#/internal/path/123?param1=foo#anchor
45 * ```
46 *
47 * or
48 *
49 * ```
50 * http://mysite.com/basepath/internal/path/123?param1=foo#anchor
51 * ```
52 *
53 * then this method returns:
54 *
55 * ```
56 * /internal/path/123?param1=foo#anchor
57 * ```
58 *
59 *
60 * #### Example:
61 * ```js
62 * locationServices.url(); // "/some/path?query=value#anchor"
63 * ```
64 *
65 * ### Updating the URL
66 *
67 * When `newurl` arguments is provided, changes the URL to reflect `newurl`
68 *
69 * #### Example:
70 * ```js
71 * locationServices.url("/some/path?query=value#anchor", true);
72 * ```
73 *
74 * @param newurl The new value for the URL.
75 * This url should reflect only the new internal [[path]], [[search]], and [[hash]] values.
76 * It should not include the protocol, site, port, or base path of an absolute HREF.
77 * @param replace When true, replaces the current history entry (instead of appending it) with this new url
78 * @param state The history's state object, i.e., pushState (if the LocationServices implementation supports it)
79 *
80 * @return the url (after potentially being processed)
81 */
82 this.url = function (newurl, replace, state) {
83 return _this.router.locationService.url(newurl, replace, state);
84 };
85 /**
86 * Gets the path part of the current url
87 *
88 * If the current URL is `/some/path?query=value#anchor`, this returns `/some/path`
89 *
90 * @return the path portion of the url
91 */
92 this.path = function () { return _this.router.locationService.path(); };
93 /**
94 * Gets the search part of the current url as an object
95 *
96 * If the current URL is `/some/path?query=value#anchor`, this returns `{ query: 'value' }`
97 *
98 * @return the search (query) portion of the url, as an object
99 */
100 this.search = function () { return _this.router.locationService.search(); };
101 /**
102 * Gets the hash part of the current url
103 *
104 * If the current URL is `/some/path?query=value#anchor`, this returns `anchor`
105 *
106 * @return the hash (anchor) portion of the url
107 */
108 this.hash = function () { return _this.router.locationService.hash(); };
109 /**
110 * @internal
111 *
112 * Registers a low level url change handler
113 *
114 * Note: Because this is a low level handler, it's not recommended for general use.
115 *
116 * #### Example:
117 * ```js
118 * let deregisterFn = locationServices.onChange((evt) => console.log("url change", evt));
119 * ```
120 *
121 * @param callback a function that will be called when the url is changing
122 * @return a function that de-registers the callback
123 */
124 this.onChange = function (callback) { return _this.router.locationService.onChange(callback); };
125 }
126 /** @internal */
127 UrlService.prototype.dispose = function () {
128 this.listen(false);
129 this.rules.dispose();
130 };
131 /**
132 * Gets the current URL parts
133 *
134 * This method returns the different parts of the current URL (the [[path]], [[search]], and [[hash]]) as a [[UrlParts]] object.
135 */
136 UrlService.prototype.parts = function () {
137 return { path: this.path(), search: this.search(), hash: this.hash() };
138 };
139 /**
140 * Activates the best rule for the current URL
141 *
142 * Checks the current URL for a matching [[UrlRule]], then invokes that rule's handler.
143 * This method is called internally any time the URL has changed.
144 *
145 * This effectively activates the state (or redirect, etc) which matches the current URL.
146 *
147 * #### Example:
148 * ```js
149 * urlService.deferIntercept();
150 *
151 * fetch('/states.json').then(resp => resp.json()).then(data => {
152 * data.forEach(state => $stateRegistry.register(state));
153 * urlService.listen();
154 * // Find the matching URL and invoke the handler.
155 * urlService.sync();
156 * });
157 * ```
158 */
159 UrlService.prototype.sync = function (evt) {
160 if (evt && evt.defaultPrevented)
161 return;
162 var _a = this.router, urlService = _a.urlService, stateService = _a.stateService;
163 var url = { path: urlService.path(), search: urlService.search(), hash: urlService.hash() };
164 var best = this.match(url);
165 var applyResult = common_1.pattern([
166 [common_1.isString, function (newurl) { return urlService.url(newurl, true); }],
167 [state_1.TargetState.isDef, function (def) { return stateService.go(def.state, def.params, def.options); }],
168 [common_1.is(state_1.TargetState), function (target) { return stateService.go(target.state(), target.params(), target.options()); }],
169 ]);
170 applyResult(best && best.rule.handler(best.match, url, this.router));
171 };
172 /**
173 * Starts or stops listening for URL changes
174 *
175 * Call this sometime after calling [[deferIntercept]] to start monitoring the url.
176 * This causes UI-Router to start listening for changes to the URL, if it wasn't already listening.
177 *
178 * If called with `false`, UI-Router will stop listening (call listen(true) to start listening again).
179 *
180 * #### Example:
181 * ```js
182 * urlService.deferIntercept();
183 *
184 * fetch('/states.json').then(resp => resp.json()).then(data => {
185 * data.forEach(state => $stateRegistry.register(state));
186 * // Start responding to URL changes
187 * urlService.listen();
188 * urlService.sync();
189 * });
190 * ```
191 *
192 * @param enabled `true` or `false` to start or stop listening to URL changes
193 */
194 UrlService.prototype.listen = function (enabled) {
195 var _this = this;
196 if (enabled === false) {
197 this._stopListeningFn && this._stopListeningFn();
198 delete this._stopListeningFn;
199 }
200 else {
201 return (this._stopListeningFn =
202 this._stopListeningFn || this.router.urlService.onChange(function (evt) { return _this.sync(evt); }));
203 }
204 };
205 /**
206 * Disables monitoring of the URL.
207 *
208 * Call this method before UI-Router has bootstrapped.
209 * It will stop UI-Router from performing the initial url sync.
210 *
211 * This can be useful to perform some asynchronous initialization before the router starts.
212 * Once the initialization is complete, call [[listen]] to tell UI-Router to start watching and synchronizing the URL.
213 *
214 * #### Example:
215 * ```js
216 * // Prevent UI-Router from automatically intercepting URL changes when it starts;
217 * urlService.deferIntercept();
218 *
219 * fetch('/states.json').then(resp => resp.json()).then(data => {
220 * data.forEach(state => $stateRegistry.register(state));
221 * urlService.listen();
222 * urlService.sync();
223 * });
224 * ```
225 *
226 * @param defer Indicates whether to defer location change interception.
227 * Passing no parameter is equivalent to `true`.
228 */
229 UrlService.prototype.deferIntercept = function (defer) {
230 if (defer === undefined)
231 defer = true;
232 this.interceptDeferred = defer;
233 };
234 /**
235 * Matches a URL
236 *
237 * Given a URL (as a [[UrlParts]] object), check all rules and determine the best matching rule.
238 * Return the result as a [[MatchResult]].
239 */
240 UrlService.prototype.match = function (url) {
241 var _this = this;
242 url = common_1.extend({ path: '', search: {}, hash: '' }, url);
243 var rules = this.rules.rules();
244 // Checks a single rule. Returns { rule: rule, match: match, weight: weight } if it matched, or undefined
245 var checkRule = function (rule) {
246 var match = rule.match(url, _this.router);
247 return match && { match: match, rule: rule, weight: rule.matchPriority(match) };
248 };
249 // The rules are pre-sorted.
250 // - Find the first matching rule.
251 // - Find any other matching rule that sorted *exactly the same*, according to `.sort()`.
252 // - Choose the rule with the highest match weight.
253 var best;
254 for (var i = 0; i < rules.length; i++) {
255 // Stop when there is a 'best' rule and the next rule sorts differently than it.
256 if (best && best.rule._group !== rules[i]._group)
257 break;
258 var current = checkRule(rules[i]);
259 // Pick the best MatchResult
260 best = !best || (current && current.weight > best.weight) ? current : best;
261 }
262 return best;
263 };
264 return UrlService;
265}());
266exports.UrlService = UrlService;
267//# sourceMappingURL=urlService.js.map
\No newline at end of file