1 | "use strict";
|
2 | var __extends = (this && this.__extends) || function (d, b) {
|
3 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
4 | function __() { this.constructor = d; }
|
5 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
6 | };
|
7 | var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
8 | var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
9 | if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
10 | else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
11 | return c > 3 && r && Object.defineProperty(target, key, r), r;
|
12 | };
|
13 | var __metadata = (this && this.__metadata) || function (k, v) {
|
14 | if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
15 | };
|
16 | var __param = (this && this.__param) || function (paramIndex, decorator) {
|
17 | return function (target, key) { decorator(target, key, paramIndex); }
|
18 | };
|
19 | var common_1 = require('@angular/common');
|
20 | var core_1 = require('@angular/core');
|
21 | var async_1 = require('../src/facade/async');
|
22 | var collection_1 = require('../src/facade/collection');
|
23 | var exceptions_1 = require('../src/facade/exceptions');
|
24 | var lang_1 = require('../src/facade/lang');
|
25 | var instruction_1 = require('./instruction');
|
26 | var route_lifecycle_reflector_1 = require('./lifecycle/route_lifecycle_reflector');
|
27 | var route_registry_1 = require('./route_registry');
|
28 | var _resolveToTrue = async_1.PromiseWrapper.resolve(true);
|
29 | var _resolveToFalse = async_1.PromiseWrapper.resolve(false);
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 | var Router = (function () {
|
48 | function Router(registry, parent, hostComponent, root) {
|
49 | this.registry = registry;
|
50 | this.parent = parent;
|
51 | this.hostComponent = hostComponent;
|
52 | this.root = root;
|
53 | this.navigating = false;
|
54 | |
55 |
|
56 |
|
57 | this.currentInstruction = null;
|
58 | this._currentNavigation = _resolveToTrue;
|
59 | this._outlet = null;
|
60 | this._auxRouters = new collection_1.Map();
|
61 | this._subject = new async_1.EventEmitter();
|
62 | }
|
63 | |
64 |
|
65 |
|
66 |
|
67 | Router.prototype.childRouter = function (hostComponent) {
|
68 | return this._childRouter = new ChildRouter(this, hostComponent);
|
69 | };
|
70 | |
71 |
|
72 |
|
73 |
|
74 | Router.prototype.auxRouter = function (hostComponent) { return new ChildRouter(this, hostComponent); };
|
75 | |
76 |
|
77 |
|
78 |
|
79 |
|
80 | Router.prototype.registerPrimaryOutlet = function (outlet) {
|
81 | if (lang_1.isPresent(outlet.name)) {
|
82 | throw new exceptions_1.BaseException("registerPrimaryOutlet expects to be called with an unnamed outlet.");
|
83 | }
|
84 | if (lang_1.isPresent(this._outlet)) {
|
85 | throw new exceptions_1.BaseException("Primary outlet is already registered.");
|
86 | }
|
87 | this._outlet = outlet;
|
88 | if (lang_1.isPresent(this.currentInstruction)) {
|
89 | return this.commit(this.currentInstruction, false);
|
90 | }
|
91 | return _resolveToTrue;
|
92 | };
|
93 | |
94 |
|
95 |
|
96 |
|
97 |
|
98 | Router.prototype.unregisterPrimaryOutlet = function (outlet) {
|
99 | if (lang_1.isPresent(outlet.name)) {
|
100 | throw new exceptions_1.BaseException("registerPrimaryOutlet expects to be called with an unnamed outlet.");
|
101 | }
|
102 | this._outlet = null;
|
103 | };
|
104 | |
105 |
|
106 |
|
107 |
|
108 |
|
109 | Router.prototype.registerAuxOutlet = function (outlet) {
|
110 | var outletName = outlet.name;
|
111 | if (lang_1.isBlank(outletName)) {
|
112 | throw new exceptions_1.BaseException("registerAuxOutlet expects to be called with an outlet with a name.");
|
113 | }
|
114 | var router = this.auxRouter(this.hostComponent);
|
115 | this._auxRouters.set(outletName, router);
|
116 | router._outlet = outlet;
|
117 | var auxInstruction;
|
118 | if (lang_1.isPresent(this.currentInstruction) &&
|
119 | lang_1.isPresent(auxInstruction = this.currentInstruction.auxInstruction[outletName])) {
|
120 | return router.commit(auxInstruction);
|
121 | }
|
122 | return _resolveToTrue;
|
123 | };
|
124 | |
125 |
|
126 |
|
127 |
|
128 | Router.prototype.isRouteActive = function (instruction) {
|
129 | var router = this;
|
130 | var currentInstruction = this.currentInstruction;
|
131 | if (lang_1.isBlank(currentInstruction)) {
|
132 | return false;
|
133 | }
|
134 |
|
135 | while (lang_1.isPresent(router.parent) && lang_1.isPresent(instruction.child)) {
|
136 | router = router.parent;
|
137 | instruction = instruction.child;
|
138 | }
|
139 | var reason = true;
|
140 |
|
141 | do {
|
142 | if (lang_1.isBlank(instruction.component) || lang_1.isBlank(currentInstruction.component) ||
|
143 | currentInstruction.component.routeName != instruction.component.routeName) {
|
144 | return false;
|
145 | }
|
146 | if (lang_1.isPresent(instruction.component.params)) {
|
147 | collection_1.StringMapWrapper.forEach(instruction.component.params, function (value /** TODO #9100 */, key /** TODO #9100 */) {
|
148 | if (currentInstruction.component.params[key] !== value) {
|
149 | reason = false;
|
150 | }
|
151 | });
|
152 | }
|
153 | currentInstruction = currentInstruction.child;
|
154 | instruction = instruction.child;
|
155 | } while (lang_1.isPresent(currentInstruction) && lang_1.isPresent(instruction) &&
|
156 | !(instruction instanceof instruction_1.DefaultInstruction) && reason);
|
157 |
|
158 | return reason && (lang_1.isBlank(instruction) || instruction instanceof instruction_1.DefaultInstruction);
|
159 | };
|
160 | |
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | Router.prototype.config = function (definitions) {
|
173 | var _this = this;
|
174 | definitions.forEach(function (routeDefinition) { _this.registry.config(_this.hostComponent, routeDefinition); });
|
175 | return this.renavigate();
|
176 | };
|
177 | |
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 | Router.prototype.navigate = function (linkParams) {
|
190 | var instruction = this.generate(linkParams);
|
191 | return this.navigateByInstruction(instruction, false);
|
192 | };
|
193 | |
194 |
|
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | Router.prototype.navigateByUrl = function (url, _skipLocationChange) {
|
201 | var _this = this;
|
202 | if (_skipLocationChange === void 0) { _skipLocationChange = false; }
|
203 | return this._currentNavigation = this._currentNavigation.then(function (_) {
|
204 | _this.lastNavigationAttempt = url;
|
205 | _this._startNavigating();
|
206 | return _this._afterPromiseFinishNavigating(_this.recognize(url).then(function (instruction) {
|
207 | if (lang_1.isBlank(instruction)) {
|
208 | return false;
|
209 | }
|
210 | return _this._navigate(instruction, _skipLocationChange);
|
211 | }));
|
212 | });
|
213 | };
|
214 | |
215 |
|
216 |
|
217 |
|
218 | Router.prototype.navigateByInstruction = function (instruction, _skipLocationChange) {
|
219 | var _this = this;
|
220 | if (_skipLocationChange === void 0) { _skipLocationChange = false; }
|
221 | if (lang_1.isBlank(instruction)) {
|
222 | return _resolveToFalse;
|
223 | }
|
224 | return this._currentNavigation = this._currentNavigation.then(function (_) {
|
225 | _this._startNavigating();
|
226 | return _this._afterPromiseFinishNavigating(_this._navigate(instruction, _skipLocationChange));
|
227 | });
|
228 | };
|
229 |
|
230 | Router.prototype._settleInstruction = function (instruction) {
|
231 | var _this = this;
|
232 | return instruction.resolveComponent().then(function (_) {
|
233 | var unsettledInstructions = [];
|
234 | if (lang_1.isPresent(instruction.component)) {
|
235 | instruction.component.reuse = false;
|
236 | }
|
237 | if (lang_1.isPresent(instruction.child)) {
|
238 | unsettledInstructions.push(_this._settleInstruction(instruction.child));
|
239 | }
|
240 | collection_1.StringMapWrapper.forEach(instruction.auxInstruction, function (instruction, _ /** TODO #9100 */) {
|
241 | unsettledInstructions.push(_this._settleInstruction(instruction));
|
242 | });
|
243 | return async_1.PromiseWrapper.all(unsettledInstructions);
|
244 | });
|
245 | };
|
246 |
|
247 | Router.prototype._navigate = function (instruction, _skipLocationChange) {
|
248 | var _this = this;
|
249 | return this._settleInstruction(instruction)
|
250 | .then(function (_) { return _this._routerCanReuse(instruction); })
|
251 | .then(function (_) { return _this._canActivate(instruction); })
|
252 | .then(function (result) {
|
253 | if (!result) {
|
254 | return false;
|
255 | }
|
256 | return _this._routerCanDeactivate(instruction).then(function (result) {
|
257 | if (result) {
|
258 | return _this.commit(instruction, _skipLocationChange).then(function (_) {
|
259 | _this._emitNavigationFinish(instruction.component);
|
260 | return true;
|
261 | });
|
262 | }
|
263 | });
|
264 | });
|
265 | };
|
266 | Router.prototype._emitNavigationFinish = function (instruction) {
|
267 | async_1.ObservableWrapper.callEmit(this._subject, { status: 'success', instruction: instruction });
|
268 | };
|
269 |
|
270 | Router.prototype._emitNavigationFail = function (url) {
|
271 | async_1.ObservableWrapper.callEmit(this._subject, { status: 'fail', url: url });
|
272 | };
|
273 | Router.prototype._afterPromiseFinishNavigating = function (promise) {
|
274 | var _this = this;
|
275 | return async_1.PromiseWrapper.catchError(promise.then(function (_) { return _this._finishNavigating(); }), function (err) {
|
276 | _this._finishNavigating();
|
277 | throw err;
|
278 | });
|
279 | };
|
280 | |
281 |
|
282 |
|
283 |
|
284 | Router.prototype._routerCanReuse = function (instruction) {
|
285 | var _this = this;
|
286 | if (lang_1.isBlank(this._outlet)) {
|
287 | return _resolveToFalse;
|
288 | }
|
289 | if (lang_1.isBlank(instruction.component)) {
|
290 | return _resolveToTrue;
|
291 | }
|
292 | return this._outlet.routerCanReuse(instruction.component).then(function (result) {
|
293 | instruction.component.reuse = result;
|
294 | if (result && lang_1.isPresent(_this._childRouter) && lang_1.isPresent(instruction.child)) {
|
295 | return _this._childRouter._routerCanReuse(instruction.child);
|
296 | }
|
297 | });
|
298 | };
|
299 | Router.prototype._canActivate = function (nextInstruction) {
|
300 | return canActivateOne(nextInstruction, this.currentInstruction);
|
301 | };
|
302 | Router.prototype._routerCanDeactivate = function (instruction) {
|
303 | var _this = this;
|
304 | if (lang_1.isBlank(this._outlet)) {
|
305 | return _resolveToTrue;
|
306 | }
|
307 | var next;
|
308 | var childInstruction = null;
|
309 | var reuse = false;
|
310 | var componentInstruction = null;
|
311 | if (lang_1.isPresent(instruction)) {
|
312 | childInstruction = instruction.child;
|
313 | componentInstruction = instruction.component;
|
314 | reuse = lang_1.isBlank(instruction.component) || instruction.component.reuse;
|
315 | }
|
316 | if (reuse) {
|
317 | next = _resolveToTrue;
|
318 | }
|
319 | else {
|
320 | next = this._outlet.routerCanDeactivate(componentInstruction);
|
321 | }
|
322 |
|
323 | return next.then(function (result) {
|
324 | if (result == false) {
|
325 | return false;
|
326 | }
|
327 | if (lang_1.isPresent(_this._childRouter)) {
|
328 |
|
329 |
|
330 | return _this._childRouter._routerCanDeactivate(childInstruction);
|
331 | }
|
332 | return true;
|
333 | });
|
334 | };
|
335 | |
336 |
|
337 |
|
338 | Router.prototype.commit = function (instruction, _skipLocationChange) {
|
339 | var _this = this;
|
340 | if (_skipLocationChange === void 0) { _skipLocationChange = false; }
|
341 | this.currentInstruction = instruction;
|
342 | var next = _resolveToTrue;
|
343 | if (lang_1.isPresent(this._outlet) && lang_1.isPresent(instruction.component)) {
|
344 | var componentInstruction = instruction.component;
|
345 | if (componentInstruction.reuse) {
|
346 | next = this._outlet.reuse(componentInstruction);
|
347 | }
|
348 | else {
|
349 | next =
|
350 | this.deactivate(instruction).then(function (_) { return _this._outlet.activate(componentInstruction); });
|
351 | }
|
352 | if (lang_1.isPresent(instruction.child)) {
|
353 | next = next.then(function (_) {
|
354 | if (lang_1.isPresent(_this._childRouter)) {
|
355 | return _this._childRouter.commit(instruction.child);
|
356 | }
|
357 | });
|
358 | }
|
359 | }
|
360 | var promises = [];
|
361 | this._auxRouters.forEach(function (router, name) {
|
362 | if (lang_1.isPresent(instruction.auxInstruction[name])) {
|
363 | promises.push(router.commit(instruction.auxInstruction[name]));
|
364 | }
|
365 | });
|
366 | return next.then(function (_) { return async_1.PromiseWrapper.all(promises); });
|
367 | };
|
368 |
|
369 | Router.prototype._startNavigating = function () { this.navigating = true; };
|
370 |
|
371 | Router.prototype._finishNavigating = function () { this.navigating = false; };
|
372 | |
373 |
|
374 |
|
375 | Router.prototype.subscribe = function (onNext, onError) {
|
376 | return async_1.ObservableWrapper.subscribe(this._subject, onNext, onError);
|
377 | };
|
378 | |
379 |
|
380 |
|
381 | Router.prototype.deactivate = function (instruction) {
|
382 | var _this = this;
|
383 | var childInstruction = null;
|
384 | var componentInstruction = null;
|
385 | if (lang_1.isPresent(instruction)) {
|
386 | childInstruction = instruction.child;
|
387 | componentInstruction = instruction.component;
|
388 | }
|
389 | var next = _resolveToTrue;
|
390 | if (lang_1.isPresent(this._childRouter)) {
|
391 | next = this._childRouter.deactivate(childInstruction);
|
392 | }
|
393 | if (lang_1.isPresent(this._outlet)) {
|
394 | next = next.then(function (_) { return _this._outlet.deactivate(componentInstruction); });
|
395 | }
|
396 |
|
397 | return next;
|
398 | };
|
399 | |
400 |
|
401 |
|
402 | Router.prototype.recognize = function (url) {
|
403 | var ancestorComponents = this._getAncestorInstructions();
|
404 | return this.registry.recognize(url, ancestorComponents);
|
405 | };
|
406 | Router.prototype._getAncestorInstructions = function () {
|
407 | var ancestorInstructions = [this.currentInstruction];
|
408 | var ancestorRouter = this;
|
409 | while (lang_1.isPresent(ancestorRouter = ancestorRouter.parent)) {
|
410 | ancestorInstructions.unshift(ancestorRouter.currentInstruction);
|
411 | }
|
412 | return ancestorInstructions;
|
413 | };
|
414 | |
415 |
|
416 |
|
417 |
|
418 | Router.prototype.renavigate = function () {
|
419 | if (lang_1.isBlank(this.lastNavigationAttempt)) {
|
420 | return this._currentNavigation;
|
421 | }
|
422 | return this.navigateByUrl(this.lastNavigationAttempt);
|
423 | };
|
424 | |
425 |
|
426 |
|
427 | Router.prototype.generate = function (linkParams) {
|
428 | var ancestorInstructions = this._getAncestorInstructions();
|
429 | return this.registry.generate(linkParams, ancestorInstructions);
|
430 | };
|
431 | Router = __decorate([
|
432 | core_1.Injectable(),
|
433 | __metadata('design:paramtypes', [route_registry_1.RouteRegistry, Router, Object, Router])
|
434 | ], Router);
|
435 | return Router;
|
436 | }());
|
437 | exports.Router = Router;
|
438 | var RootRouter = (function (_super) {
|
439 | __extends(RootRouter, _super);
|
440 | function RootRouter(registry, location, primaryComponent) {
|
441 | var _this = this;
|
442 | _super.call(this, registry, null, primaryComponent);
|
443 | this.root = this;
|
444 | this._location = location;
|
445 | this._locationSub = this._location.subscribe(function (change) {
|
446 |
|
447 | _this.recognize(change['url']).then(function (instruction) {
|
448 | if (lang_1.isPresent(instruction)) {
|
449 | _this.navigateByInstruction(instruction, lang_1.isPresent(change['pop'])).then(function (_) {
|
450 |
|
451 | if (lang_1.isPresent(change['pop']) && change['type'] != 'hashchange') {
|
452 | return;
|
453 | }
|
454 | var emitPath = instruction.toUrlPath();
|
455 | var emitQuery = instruction.toUrlQuery();
|
456 | if (emitPath.length > 0 && emitPath[0] != '/') {
|
457 | emitPath = '/' + emitPath;
|
458 | }
|
459 |
|
460 |
|
461 |
|
462 |
|
463 |
|
464 |
|
465 |
|
466 | if (change['type'] == 'hashchange') {
|
467 | if (instruction.toRootUrl() != _this._location.path()) {
|
468 | _this._location.replaceState(emitPath, emitQuery);
|
469 | }
|
470 | }
|
471 | else {
|
472 | _this._location.go(emitPath, emitQuery);
|
473 | }
|
474 | });
|
475 | }
|
476 | else {
|
477 | _this._emitNavigationFail(change['url']);
|
478 | }
|
479 | });
|
480 | });
|
481 | this.registry.configFromComponent(primaryComponent);
|
482 | this.navigateByUrl(location.path());
|
483 | }
|
484 | RootRouter.prototype.commit = function (instruction, _skipLocationChange) {
|
485 | var _this = this;
|
486 | if (_skipLocationChange === void 0) { _skipLocationChange = false; }
|
487 | var emitPath = instruction.toUrlPath();
|
488 | var emitQuery = instruction.toUrlQuery();
|
489 | if (emitPath.length > 0 && emitPath[0] != '/') {
|
490 | emitPath = '/' + emitPath;
|
491 | }
|
492 | var promise = _super.prototype.commit.call(this, instruction);
|
493 | if (!_skipLocationChange) {
|
494 | if (this._location.isCurrentPathEqualTo(emitPath, emitQuery)) {
|
495 | promise = promise.then(function (_) { _this._location.replaceState(emitPath, emitQuery); });
|
496 | }
|
497 | else {
|
498 | promise = promise.then(function (_) { _this._location.go(emitPath, emitQuery); });
|
499 | }
|
500 | }
|
501 | return promise;
|
502 | };
|
503 | RootRouter.prototype.dispose = function () {
|
504 | if (lang_1.isPresent(this._locationSub)) {
|
505 | async_1.ObservableWrapper.dispose(this._locationSub);
|
506 | this._locationSub = null;
|
507 | }
|
508 | };
|
509 | RootRouter = __decorate([
|
510 | core_1.Injectable(),
|
511 | __param(2, core_1.Inject(route_registry_1.ROUTER_PRIMARY_COMPONENT)),
|
512 | __metadata('design:paramtypes', [route_registry_1.RouteRegistry, common_1.Location, lang_1.Type])
|
513 | ], RootRouter);
|
514 | return RootRouter;
|
515 | }(Router));
|
516 | exports.RootRouter = RootRouter;
|
517 | var ChildRouter = (function (_super) {
|
518 | __extends(ChildRouter, _super);
|
519 | function ChildRouter(parent, hostComponent /** TODO #9100 */) {
|
520 | _super.call(this, parent.registry, parent, hostComponent, parent.root);
|
521 | this.parent = parent;
|
522 | }
|
523 | ChildRouter.prototype.navigateByUrl = function (url, _skipLocationChange) {
|
524 | if (_skipLocationChange === void 0) { _skipLocationChange = false; }
|
525 |
|
526 | return this.parent.navigateByUrl(url, _skipLocationChange);
|
527 | };
|
528 | ChildRouter.prototype.navigateByInstruction = function (instruction, _skipLocationChange) {
|
529 | if (_skipLocationChange === void 0) { _skipLocationChange = false; }
|
530 |
|
531 | return this.parent.navigateByInstruction(instruction, _skipLocationChange);
|
532 | };
|
533 | return ChildRouter;
|
534 | }(Router));
|
535 | function canActivateOne(nextInstruction, prevInstruction) {
|
536 | var next = _resolveToTrue;
|
537 | if (lang_1.isBlank(nextInstruction.component)) {
|
538 | return next;
|
539 | }
|
540 | if (lang_1.isPresent(nextInstruction.child)) {
|
541 | next = canActivateOne(nextInstruction.child, lang_1.isPresent(prevInstruction) ? prevInstruction.child : null);
|
542 | }
|
543 | return next.then(function (result) {
|
544 | if (result == false) {
|
545 | return false;
|
546 | }
|
547 | if (nextInstruction.component.reuse) {
|
548 | return true;
|
549 | }
|
550 | var hook = route_lifecycle_reflector_1.getCanActivateHook(nextInstruction.component.componentType);
|
551 | if (lang_1.isPresent(hook)) {
|
552 | return hook(nextInstruction.component, lang_1.isPresent(prevInstruction) ? prevInstruction.component : null);
|
553 | }
|
554 | return true;
|
555 | });
|
556 | }
|
557 |
|
\ | No newline at end of file |