1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | var angular_1 = require("../angular");
|
14 | var core_1 = require("@uirouter/core");
|
15 |
|
16 | function parseStateRef(ref) {
|
17 | var paramsOnly = ref.match(/^\s*({[^}]*})\s*$/);
|
18 | if (paramsOnly)
|
19 | ref = '(' + paramsOnly[1] + ')';
|
20 | var parsed = ref.replace(/\n/g, ' ').match(/^\s*([^(]*?)\s*(\((.*)\))?\s*$/);
|
21 | if (!parsed || parsed.length !== 4)
|
22 | throw new Error("Invalid state ref '" + ref + "'");
|
23 | return { state: parsed[1] || null, paramExpr: parsed[3] || null };
|
24 | }
|
25 |
|
26 | function stateContext(el) {
|
27 | var $uiView = el.parent().inheritedData('$uiView');
|
28 | var path = core_1.parse('$cfg.path')($uiView);
|
29 | return path ? core_1.tail(path).state.name : undefined;
|
30 | }
|
31 |
|
32 | function processedDef($state, $element, def) {
|
33 | var uiState = def.uiState || $state.current.name;
|
34 | var uiStateOpts = core_1.extend(defaultOpts($element, $state), def.uiStateOpts || {});
|
35 | var href = $state.href(uiState, def.uiStateParams, uiStateOpts);
|
36 | return { uiState: uiState, uiStateParams: def.uiStateParams, uiStateOpts: uiStateOpts, href: href };
|
37 | }
|
38 |
|
39 | function getTypeInfo(el) {
|
40 |
|
41 | var isSvg = Object.prototype.toString.call(el.prop('href')) === '[object SVGAnimatedString]';
|
42 | var isForm = el[0].nodeName === 'FORM';
|
43 | return {
|
44 | attr: isForm ? 'action' : isSvg ? 'xlink:href' : 'href',
|
45 | isAnchor: el.prop('tagName').toUpperCase() === 'A',
|
46 | clickable: !isForm,
|
47 | };
|
48 | }
|
49 |
|
50 | function clickHook(el, $state, $timeout, type, getDef) {
|
51 | return function (e) {
|
52 | var button = e.which || e.button, target = getDef();
|
53 | if (!(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey || el.attr('target'))) {
|
54 |
|
55 | var transition_1 = $timeout(function () {
|
56 | if (!el.attr('disabled')) {
|
57 | $state.go(target.uiState, target.uiStateParams, target.uiStateOpts);
|
58 | }
|
59 | });
|
60 | e.preventDefault();
|
61 |
|
62 | var ignorePreventDefaultCount_1 = type.isAnchor && !target.href ? 1 : 0;
|
63 | e.preventDefault = function () {
|
64 | if (ignorePreventDefaultCount_1-- <= 0)
|
65 | $timeout.cancel(transition_1);
|
66 | };
|
67 | }
|
68 | };
|
69 | }
|
70 | /** @hidden */
|
71 | function defaultOpts(el, $state) {
|
72 | return {
|
73 | relative: stateContext(el) || $state.$current,
|
74 | inherit: true,
|
75 | source: 'sref',
|
76 | };
|
77 | }
|
78 | /** @hidden */
|
79 | function bindEvents(element, scope, hookFn, uiStateOpts) {
|
80 | var events;
|
81 | if (uiStateOpts) {
|
82 | events = uiStateOpts.events;
|
83 | }
|
84 | if (!core_1.isArray(events)) {
|
85 | events = ['click'];
|
86 | }
|
87 | var on = element.on ? 'on' : 'bind';
|
88 | for (var _i = 0, events_1 = events; _i < events_1.length; _i++) {
|
89 | var event_1 = events_1[_i];
|
90 | element[on](event_1, hookFn);
|
91 | }
|
92 | scope.$on('$destroy', function () {
|
93 | var off = element.off ? 'off' : 'unbind';
|
94 | for (var _i = 0, events_2 = events; _i < events_2.length; _i++) {
|
95 | var event_2 = events_2[_i];
|
96 | element[off](event_2, hookFn);
|
97 | }
|
98 | });
|
99 | }
|
100 | /**
|
101 | * `ui-sref`: A directive for linking to a state
|
102 | *
|
103 | * A directive which links to a state (and optionally, parameters).
|
104 | * When clicked, this directive activates the linked state with the supplied parameter values.
|
105 | *
|
106 | * ### Linked State
|
107 | * The attribute value of the `ui-sref` is the name of the state to link to.
|
108 | *
|
109 | * #### Example:
|
110 | * This will activate the `home` state when the link is clicked.
|
111 | * ```html
|
112 | * <a ui-sref="home">Home</a>
|
113 | * ```
|
114 | *
|
115 | * ### Relative Links
|
116 | * You can also use relative state paths within `ui-sref`, just like a relative path passed to `$state.go()` ([[StateService.go]]).
|
117 | * You just need to be aware that the path is relative to the state that *created* the link.
|
118 | * This allows a state to create a relative `ui-sref` which always targets the same destination.
|
119 | *
|
120 | * #### Example:
|
121 | * Both these links are relative to the parent state, even when a child state is currently active.
|
122 | * ```html
|
123 | * <a ui-sref=".child1">child 1 state</a>
|
124 | * <a ui-sref=".child2">child 2 state</a>
|
125 | * ```
|
126 | *
|
127 | * This link activates the parent state.
|
128 | * ```html
|
129 | * <a ui-sref="^">Return</a>
|
130 | * ```
|
131 | *
|
132 | * ### hrefs
|
133 | * If the linked state has a URL, the directive will automatically generate and
|
134 | * update the `href` attribute (using the [[StateService.href]] method).
|
135 | *
|
136 | * #### Example:
|
137 | * Assuming the `users` state has a url of `/users/`
|
138 | * ```html
|
139 | * <a ui-sref="users" href="/users/">Users</a>
|
140 | * ```
|
141 | *
|
142 | * ### Parameter Values
|
143 | * In addition to the state name, a `ui-sref` can include parameter values which are applied when activating the state.
|
144 | * Param values can be provided in the `ui-sref` value after the state name, enclosed by parentheses.
|
145 | * The content inside the parentheses is an expression, evaluated to the parameter values.
|
146 | *
|
147 | * #### Example:
|
148 | * This example renders a list of links to users.
|
149 | * The state's `userId` parameter value comes from each user's `user.id` property.
|
150 | * ```html
|
151 | * <li ng-repeat="user in users">
|
152 | * <a ui-sref="users.detail({ userId: user.id })">{{ user.displayName }}</a>
|
153 | * </li>
|
154 | * ```
|
155 | *
|
156 | * Note:
|
157 | * The parameter values expression is `$watch`ed for updates.
|
158 | *
|
159 | * ### Transition Options
|
160 | * You can specify [[TransitionOptions]] to pass to [[StateService.go]] by using the `ui-sref-opts` attribute.
|
161 | * Options are restricted to `location`, `inherit`, and `reload`.
|
162 | *
|
163 | * #### Example:
|
164 | * ```html
|
165 | * <a ui-sref="home" ui-sref-opts="{ reload: true }">Home</a>
|
166 | * ```
|
167 | *
|
168 | * ### Other DOM Events
|
169 | *
|
170 | * You can also customize which DOM events to respond to (instead of `click`) by
|
171 | * providing an `events` array in the `ui-sref-opts` attribute.
|
172 | *
|
173 | * #### Example:
|
174 | * ```html
|
175 | * <input type="text" ui-sref="contacts" ui-sref-opts="{ events: ['change', 'blur'] }">
|
176 | * ```
|
177 | *
|
178 | * ### Highlighting the active link
|
179 | * This directive can be used in conjunction with [[uiSrefActive]] to highlight the active link.
|
180 | *
|
181 | * ### Examples
|
182 | * If you have the following template:
|
183 | *
|
184 | * ```html
|
185 | * <a ui-sref="home">Home</a>
|
186 | * <a ui-sref="about">About</a>
|
187 | * <a ui-sref="{page: 2}">Next page</a>
|
188 | *
|
189 | * <ul>
|
190 | * <li ng-repeat="contact in contacts">
|
191 | * <a ui-sref="contacts.detail({ id: contact.id })">{{ contact.name }}</a>
|
192 | * </li>
|
193 | * </ul>
|
194 | * ```
|
195 | *
|
196 | * Then (assuming the current state is `contacts`) the rendered html including hrefs would be:
|
197 | *
|
198 | * ```html
|
199 | * <a href="#/home" ui-sref="home">Home</a>
|
200 | * <a href="#/about" ui-sref="about">About</a>
|
201 | * <a href="#/contacts?page=2" ui-sref="{page: 2}">Next page</a>
|
202 | *
|
203 | * <ul>
|
204 | * <li ng-repeat="contact in contacts">
|
205 | * <a href="#/contacts/1" ui-sref="contacts.detail({ id: contact.id })">Joe</a>
|
206 | * </li>
|
207 | * <li ng-repeat="contact in contacts">
|
208 | * <a href="#/contacts/2" ui-sref="contacts.detail({ id: contact.id })">Alice</a>
|
209 | * </li>
|
210 | * <li ng-repeat="contact in contacts">
|
211 | * <a href="#/contacts/3" ui-sref="contacts.detail({ id: contact.id })">Bob</a>
|
212 | * </li>
|
213 | * </ul>
|
214 | *
|
215 | * <a href="#/home" ui-sref="home" ui-sref-opts="{reload: true}">Home</a>
|
216 | * ```
|
217 | *
|
218 | * ### Notes
|
219 | *
|
220 | * - You can use `ui-sref` to change **only the parameter values** by omitting the state name and parentheses.
|
221 | * #### Example:
|
222 | * Sets the `lang` parameter to `en` and remains on the same state.
|
223 | *
|
224 | * ```html
|
225 | * <a ui-sref="{ lang: 'en' }">English</a>
|
226 | * ```
|
227 | *
|
228 | * - A middle-click, right-click, or ctrl-click is handled (natively) by the browser to open the href in a new window, for example.
|
229 | *
|
230 | * - Unlike the parameter values expression, the state name is not `$watch`ed (for performance reasons).
|
231 | * If you need to dynamically update the state being linked to, use the fully dynamic [[uiState]] directive.
|
232 | */
|
233 | var uiSrefDirective;
|
234 | uiSrefDirective = [
|
235 | '$uiRouter',
|
236 | '$timeout',
|
237 | function $StateRefDirective($uiRouter, $timeout) {
|
238 | var $state = $uiRouter.stateService;
|
239 | return {
|
240 | restrict: 'A',
|
241 | require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
|
242 | link: function (scope, element, attrs, uiSrefActive) {
|
243 | var type = getTypeInfo(element);
|
244 | var active = uiSrefActive[1] || uiSrefActive[0];
|
245 | var unlinkInfoFn = null;
|
246 | var rawDef = {};
|
247 | var getDef = function () { return processedDef($state, element, rawDef); };
|
248 | var ref = parseStateRef(attrs.uiSref);
|
249 | rawDef.uiState = ref.state;
|
250 | rawDef.uiStateOpts = attrs.uiSrefOpts ? scope.$eval(attrs.uiSrefOpts) : {};
|
251 | function update() {
|
252 | var def = getDef();
|
253 | if (unlinkInfoFn)
|
254 | unlinkInfoFn();
|
255 | if (active)
|
256 | unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
|
257 | if (def.href != null)
|
258 | attrs.$set(type.attr, def.href);
|
259 | }
|
260 | if (ref.paramExpr) {
|
261 | scope.$watch(ref.paramExpr, function (val) {
|
262 | rawDef.uiStateParams = core_1.extend({}, val);
|
263 | update();
|
264 | }, true);
|
265 | rawDef.uiStateParams = core_1.extend({}, scope.$eval(ref.paramExpr));
|
266 | }
|
267 | update();
|
268 | scope.$on('$destroy', $uiRouter.stateRegistry.onStatesChanged(update));
|
269 | scope.$on('$destroy', $uiRouter.transitionService.onSuccess({}, update));
|
270 | if (!type.clickable)
|
271 | return;
|
272 | var hookFn = clickHook(element, $state, $timeout, type, getDef);
|
273 | bindEvents(element, scope, hookFn, rawDef.uiStateOpts);
|
274 | },
|
275 | };
|
276 | },
|
277 | ];
|
278 | /**
|
279 | * `ui-state`: A fully dynamic directive for linking to a state
|
280 | *
|
281 | * A directive which links to a state (and optionally, parameters).
|
282 | * When clicked, this directive activates the linked state with the supplied parameter values.
|
283 | *
|
284 | * **This directive is very similar to [[uiSref]], but it `$observe`s and `$watch`es/evaluates all its inputs.**
|
285 | *
|
286 | * A directive which links to a state (and optionally, parameters).
|
287 | * When clicked, this directive activates the linked state with the supplied parameter values.
|
288 | *
|
289 | * ### Linked State
|
290 | * The attribute value of `ui-state` is an expression which is `$watch`ed and evaluated as the state to link to.
|
291 | * **This is in contrast with `ui-sref`, which takes a state name as a string literal.**
|
292 | *
|
293 | * #### Example:
|
294 | * Create a list of links.
|
295 | * ```html
|
296 | * <li ng-repeat="link in navlinks">
|
297 | * <a ui-state="link.state">{{ link.displayName }}</a>
|
298 | * </li>
|
299 | * ```
|
300 | *
|
301 | * ### Relative Links
|
302 | * If the expression evaluates to a relative path, it is processed like [[uiSref]].
|
303 | * You just need to be aware that the path is relative to the state that *created* the link.
|
304 | * This allows a state to create relative `ui-state` which always targets the same destination.
|
305 | *
|
306 | * ### hrefs
|
307 | * If the linked state has a URL, the directive will automatically generate and
|
308 | * update the `href` attribute (using the [[StateService.href]] method).
|
309 | *
|
310 | * ### Parameter Values
|
311 | * In addition to the state name expression, a `ui-state` can include parameter values which are applied when activating the state.
|
312 | * Param values should be provided using the `ui-state-params` attribute.
|
313 | * The `ui-state-params` attribute value is `$watch`ed and evaluated as an expression.
|
314 | *
|
315 | * #### Example:
|
316 | * This example renders a list of links with param values.
|
317 | * The state's `userId` parameter value comes from each user's `user.id` property.
|
318 | * ```html
|
319 | * <li ng-repeat="link in navlinks">
|
320 | * <a ui-state="link.state" ui-state-params="link.params">{{ link.displayName }}</a>
|
321 | * </li>
|
322 | * ```
|
323 | *
|
324 | * ### Transition Options
|
325 | * You can specify [[TransitionOptions]] to pass to [[StateService.go]] by using the `ui-state-opts` attribute.
|
326 | * Options are restricted to `location`, `inherit`, and `reload`.
|
327 | * The value of the `ui-state-opts` is `$watch`ed and evaluated as an expression.
|
328 | *
|
329 | * #### Example:
|
330 | * ```html
|
331 | * <a ui-state="returnto.state" ui-state-opts="{ reload: true }">Home</a>
|
332 | * ```
|
333 | *
|
334 | * ### Other DOM Events
|
335 | *
|
336 | * You can also customize which DOM events to respond to (instead of `click`) by
|
337 | * providing an `events` array in the `ui-state-opts` attribute.
|
338 | *
|
339 | * #### Example:
|
340 | * ```html
|
341 | * <input type="text" ui-state="contacts" ui-state-opts="{ events: ['change', 'blur'] }">
|
342 | * ```
|
343 | *
|
344 | * ### Highlighting the active link
|
345 | * This directive can be used in conjunction with [[uiSrefActive]] to highlight the active link.
|
346 | *
|
347 | * ### Notes
|
348 | *
|
349 | * - You can use `ui-params` to change **only the parameter values** by omitting the state name and supplying only `ui-state-params`.
|
350 | * However, it might be simpler to use [[uiSref]] parameter-only links.
|
351 | *
|
352 | * #### Example:
|
353 | * Sets the `lang` parameter to `en` and remains on the same state.
|
354 | *
|
355 | * ```html
|
356 | * <a ui-state="" ui-state-params="{ lang: 'en' }">English</a>
|
357 | * ```
|
358 | *
|
359 | * - A middle-click, right-click, or ctrl-click is handled (natively) by the browser to open the href in a new window, for example.
|
360 | * ```
|
361 | */
|
362 | var uiStateDirective;
|
363 | uiStateDirective = [
|
364 | '$uiRouter',
|
365 | '$timeout',
|
366 | function $StateRefDynamicDirective($uiRouter, $timeout) {
|
367 | var $state = $uiRouter.stateService;
|
368 | return {
|
369 | restrict: 'A',
|
370 | require: ['?^uiSrefActive', '?^uiSrefActiveEq'],
|
371 | link: function (scope, element, attrs, uiSrefActive) {
|
372 | var type = getTypeInfo(element);
|
373 | var active = uiSrefActive[1] || uiSrefActive[0];
|
374 | var unlinkInfoFn = null;
|
375 | var hookFn;
|
376 | var rawDef = {};
|
377 | var getDef = function () { return processedDef($state, element, rawDef); };
|
378 | var inputAttrs = ['uiState', 'uiStateParams', 'uiStateOpts'];
|
379 | var watchDeregFns = inputAttrs.reduce(function (acc, attr) { return ((acc[attr] = core_1.noop), acc); }, {});
|
380 | function update() {
|
381 | var def = getDef();
|
382 | if (unlinkInfoFn)
|
383 | unlinkInfoFn();
|
384 | if (active)
|
385 | unlinkInfoFn = active.$$addStateInfo(def.uiState, def.uiStateParams);
|
386 | if (def.href != null)
|
387 | attrs.$set(type.attr, def.href);
|
388 | }
|
389 | inputAttrs.forEach(function (field) {
|
390 | rawDef[field] = attrs[field] ? scope.$eval(attrs[field]) : null;
|
391 | attrs.$observe(field, function (expr) {
|
392 | watchDeregFns[field]();
|
393 | watchDeregFns[field] = scope.$watch(expr, function (newval) {
|
394 | rawDef[field] = newval;
|
395 | update();
|
396 | }, true);
|
397 | });
|
398 | });
|
399 | update();
|
400 | scope.$on('$destroy', $uiRouter.stateRegistry.onStatesChanged(update));
|
401 | scope.$on('$destroy', $uiRouter.transitionService.onSuccess({}, update));
|
402 | if (!type.clickable)
|
403 | return;
|
404 | hookFn = clickHook(element, $state, $timeout, type, getDef);
|
405 | bindEvents(element, scope, hookFn, rawDef.uiStateOpts);
|
406 | },
|
407 | };
|
408 | },
|
409 | ];
|
410 | /**
|
411 | * `ui-sref-active` and `ui-sref-active-eq`: A directive that adds a CSS class when a `ui-sref` is active
|
412 | *
|
413 | * A directive working alongside [[uiSref]] and [[uiState]] to add classes to an element when the
|
414 | * related directive's state is active (and remove them when it is inactive).
|
415 | *
|
416 | * The primary use-case is to highlight the active link in navigation menus,
|
417 | * distinguishing it from the inactive menu items.
|
418 | *
|
419 | * ### Linking to a `ui-sref` or `ui-state`
|
420 | * `ui-sref-active` can live on the same element as `ui-sref`/`ui-state`, or it can be on a parent element.
|
421 | * If a `ui-sref-active` is a parent to more than one `ui-sref`/`ui-state`, it will apply the CSS class when **any of the links are active**.
|
422 | *
|
423 | * ### Matching
|
424 | *
|
425 | * The `ui-sref-active` directive applies the CSS class when the `ui-sref`/`ui-state`'s target state **or any child state is active**.
|
426 | * This is a "fuzzy match" which uses [[StateService.includes]].
|
427 | *
|
428 | * The `ui-sref-active-eq` directive applies the CSS class when the `ui-sref`/`ui-state`'s target state is directly active (not when child states are active).
|
429 | * This is an "exact match" which uses [[StateService.is]].
|
430 | *
|
431 | * ### Parameter values
|
432 | * If the `ui-sref`/`ui-state` includes parameter values, the current parameter values must match the link's values for the link to be highlighted.
|
433 | * This allows a list of links to the same state with different parameters to be rendered, and the correct one highlighted.
|
434 | *
|
435 | * #### Example:
|
436 | * ```html
|
437 | * <li ng-repeat="user in users" ui-sref-active="active">
|
438 | * <a ui-sref="user.details({ userId: user.id })">{{ user.lastName }}</a>
|
439 | * </li>
|
440 | * ```
|
441 | *
|
442 | * ### Examples
|
443 | *
|
444 | * Given the following template:
|
445 | * #### Example:
|
446 | * ```html
|
447 | * <ul>
|
448 | * <li ui-sref-active="active" class="item">
|
449 | * <a href ui-sref="app.user({user: 'bilbobaggins'})">@bilbobaggins</a>
|
450 | * </li>
|
451 | * </ul>
|
452 | * ```
|
453 | *
|
454 | * When the app state is `app.user` (or any child state),
|
455 | * and contains the state parameter "user" with value "bilbobaggins",
|
456 | * the resulting HTML will appear as (note the 'active' class):
|
457 | *
|
458 | * ```html
|
459 | * <ul>
|
460 | * <li ui-sref-active="active" class="item active">
|
461 | * <a ui-sref="app.user({user: 'bilbobaggins'})" href="/users/bilbobaggins">@bilbobaggins</a>
|
462 | * </li>
|
463 | * </ul>
|
464 | * ```
|
465 | *
|
466 | * ### Glob mode
|
467 | *
|
468 | * It is possible to pass `ui-sref-active` an expression that evaluates to an object.
|
469 | * The objects keys represent active class names and values represent the respective state names/globs.
|
470 | * `ui-sref-active` will match if the current active state **includes** any of
|
471 | * the specified state names/globs, even the abstract ones.
|
472 | *
|
473 | * #### Example:
|
474 | * Given the following template, with "admin" being an abstract state:
|
475 | * ```html
|
476 | * <div ui-sref-active="{'active': 'admin.**'}">
|
477 | * <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
|
478 | * </div>
|
479 | * ```
|
480 | *
|
481 | * Arrays are also supported as values in the `ngClass`-like interface.
|
482 | * This allows multiple states to add `active` class.
|
483 | *
|
484 | * #### Example:
|
485 | * Given the following template, with "admin.roles" being the current state, the class will be added too:
|
486 | * ```html
|
487 | * <div ui-sref-active="{'active': ['owner.**', 'admin.**']}">
|
488 | * <a ui-sref-active="active" ui-sref="admin.roles">Roles</a>
|
489 | * </div>
|
490 | * ```
|
491 | *
|
492 | * When the current state is "admin.roles" the "active" class will be applied to both the `<div>` and `<a>` elements.
|
493 | * It is important to note that the state names/globs passed to `ui-sref-active` override any state provided by a linked `ui-sref`.
|
494 | *
|
495 | * ### Notes:
|
496 | *
|
497 | * - The class name is interpolated **once** during the directives link time (any further changes to the
|
498 | * interpolated value are ignored).
|
499 | *
|
500 | * - Multiple classes may be specified in a space-separated format: `ui-sref-active='class1 class2 class3'`
|
501 | */
|
502 | var uiSrefActiveDirective;
|
503 | uiSrefActiveDirective = [
|
504 | '$state',
|
505 | '$stateParams',
|
506 | '$interpolate',
|
507 | '$uiRouter',
|
508 | function $StateRefActiveDirective($state, $stateParams, $interpolate, $uiRouter) {
|
509 | return {
|
510 | restrict: 'A',
|
511 | controller: [
|
512 | '$scope',
|
513 | '$element',
|
514 | '$attrs',
|
515 | function ($scope, $element, $attrs) {
|
516 | var states = [];
|
517 | var activeEqClass;
|
518 | var uiSrefActive;
|
519 | // There probably isn't much point in $observing this
|
520 | // uiSrefActive and uiSrefActiveEq share the same directive object with some
|
521 | // slight difference in logic routing
|
522 | activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);
|
523 | try {
|
524 | uiSrefActive = $scope.$eval($attrs.uiSrefActive);
|
525 | }
|
526 | catch (e) {
|
527 | // Do nothing. uiSrefActive is not a valid expression.
|
528 | // Fall back to using $interpolate below
|
529 | }
|
530 | uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);
|
531 | setStatesFromDefinitionObject(uiSrefActive);
|
532 | // Allow uiSref to communicate with uiSrefActive[Equals]
|
533 | this.$$addStateInfo = function (newState, newParams) {
|
534 | // we already got an explicit state provided by ui-sref-active, so we
|
535 | // shadow the one that comes from ui-sref
|
536 | if (core_1.isObject(uiSrefActive) && states.length > 0) {
|
537 | return;
|
538 | }
|
539 | var deregister = addState(newState, newParams, uiSrefActive);
|
540 | update();
|
541 | return deregister;
|
542 | };
|
543 | function updateAfterTransition(trans) {
|
544 | trans.promise.then(update, core_1.noop);
|
545 | }
|
546 | $scope.$on('$destroy', setupEventListeners());
|
547 | if ($uiRouter.globals.transition) {
|
548 | updateAfterTransition($uiRouter.globals.transition);
|
549 | }
|
550 | function setupEventListeners() {
|
551 | var deregisterStatesChangedListener = $uiRouter.stateRegistry.onStatesChanged(handleStatesChanged);
|
552 | var deregisterOnStartListener = $uiRouter.transitionService.onStart({}, updateAfterTransition);
|
553 | var deregisterStateChangeSuccessListener = $scope.$on('$stateChangeSuccess', update);
|
554 | return function cleanUp() {
|
555 | deregisterStatesChangedListener();
|
556 | deregisterOnStartListener();
|
557 | deregisterStateChangeSuccessListener();
|
558 | };
|
559 | }
|
560 | function handleStatesChanged() {
|
561 | setStatesFromDefinitionObject(uiSrefActive);
|
562 | }
|
563 | function setStatesFromDefinitionObject(statesDefinition) {
|
564 | if (core_1.isObject(statesDefinition)) {
|
565 | states = [];
|
566 | core_1.forEach(statesDefinition, function (stateOrName, activeClass) {
|
567 | // Helper function to abstract adding state.
|
568 | var addStateForClass = function (stateOrName, activeClass) {
|
569 | var ref = parseStateRef(stateOrName);
|
570 | addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);
|
571 | };
|
572 | if (core_1.isString(stateOrName)) {
|
573 | // If state is string, just add it.
|
574 | addStateForClass(stateOrName, activeClass);
|
575 | }
|
576 | else if (core_1.isArray(stateOrName)) {
|
577 | // If state is an array, iterate over it and add each array item individually.
|
578 | core_1.forEach(stateOrName, function (stateOrName) {
|
579 | addStateForClass(stateOrName, activeClass);
|
580 | });
|
581 | }
|
582 | });
|
583 | }
|
584 | }
|
585 | function addState(stateName, stateParams, activeClass) {
|
586 | var state = $state.get(stateName, stateContext($element));
|
587 | var stateInfo = {
|
588 | state: state || { name: stateName },
|
589 | params: stateParams,
|
590 | activeClass: activeClass,
|
591 | };
|
592 | states.push(stateInfo);
|
593 | return function removeState() {
|
594 | core_1.removeFrom(states)(stateInfo);
|
595 | };
|
596 | }
|
597 | // Update route state
|
598 | function update() {
|
599 | var splitClasses = function (str) { return str.split(/\s/).filter(core_1.identity); };
|
600 | var getClasses = function (stateList) {
|
601 | return stateList
|
602 | .map(function (x) { return x.activeClass; })
|
603 | .map(splitClasses)
|
604 | .reduce(core_1.unnestR, []);
|
605 | };
|
606 | var allClasses = getClasses(states).concat(splitClasses(activeEqClass)).reduce(core_1.uniqR, []);
|
607 | var fuzzyClasses = getClasses(states.filter(function (x) { return $state.includes(x.state.name, x.params); }));
|
608 | var exactlyMatchesAny = !!states.filter(function (x) { return $state.is(x.state.name, x.params); }).length;
|
609 | var exactClasses = exactlyMatchesAny ? splitClasses(activeEqClass) : [];
|
610 | var addClasses = fuzzyClasses.concat(exactClasses).reduce(core_1.uniqR, []);
|
611 | var removeClasses = allClasses.filter(function (cls) { return !core_1.inArray(addClasses, cls); });
|
612 | $scope.$evalAsync(function () {
|
613 | addClasses.forEach(function (className) { return $element.addClass(className); });
|
614 | removeClasses.forEach(function (className) { return $element.removeClass(className); });
|
615 | });
|
616 | }
|
617 | update();
|
618 | },
|
619 | ],
|
620 | };
|
621 | },
|
622 | ];
|
623 | angular_1.ng
|
624 | .module('ui.router.state')
|
625 | .directive('uiSref', uiSrefDirective)
|
626 | .directive('uiSrefActive', uiSrefActiveDirective)
|
627 | .directive('uiSrefActiveEq', uiSrefActiveDirective)
|
628 | .directive('uiState', uiStateDirective);
|
629 | //# sourceMappingURL=stateDirectives.js.map |
\ | No newline at end of file |