1 | import BackboneSubRoute from 'backbone.subroute';
|
2 | import { settings } from './contexts';
|
3 | import { global, runtime } from './contexts';
|
4 |
|
5 | let _stateRouteMapping = {};
|
6 |
|
7 | class UrlDefinition {
|
8 | constructor(state, controller) {
|
9 | this._state = state;
|
10 | this._controller = controller;
|
11 | }
|
12 |
|
13 | get state() {
|
14 | return this._state;
|
15 | }
|
16 |
|
17 | get controller() {
|
18 | return this._controller;
|
19 | }
|
20 | }
|
21 |
|
22 | class IncludeDefinition {
|
23 | constructor(router) {
|
24 | this._router = router;
|
25 | }
|
26 |
|
27 | get router() {
|
28 | return this._router;
|
29 | }
|
30 | }
|
31 |
|
32 | export function url(state, controller) {
|
33 | return new UrlDefinition(state, controller);
|
34 | }
|
35 |
|
36 | export function include(router) {
|
37 | return new IncludeDefinition(router);
|
38 | }
|
39 |
|
40 | export class RouteUtils {
|
41 | static _urlParamsReplace(url, params) {
|
42 | for (let pkey of Object.keys(params)) {
|
43 | let beforeReplace = url;
|
44 | url = url.replace(`:${pkey}`, params[pkey]);
|
45 | if (beforeReplace === url) {
|
46 | throw `Unable to find reverse url for "${beforeReplace}" with params ${JSON.stringify(params)}.`;
|
47 | }
|
48 | }
|
49 | return url;
|
50 | }
|
51 |
|
52 | static reverse(state, params = {}, prependHash = true) {
|
53 | var url = _stateRouteMapping[state].route;
|
54 | url = RouteUtils._urlParamsReplace(url, params);
|
55 | if (prependHash) {
|
56 | return `#${url}`;
|
57 | }
|
58 | return url;
|
59 | }
|
60 |
|
61 | static navigate(state, params = {}) {
|
62 | var routeMapping = _stateRouteMapping[state];
|
63 | var url = _stateRouteMapping[state].route;
|
64 | url = RouteUtils._urlParamsReplace(url, params);
|
65 | routeMapping.router.navigate(url, {trigger: true});
|
66 | }
|
67 |
|
68 | static query() {
|
69 | var href = window.location.href;
|
70 | var result = {};
|
71 | if (href.includes('#')) {
|
72 | href = href.split('#')[1];
|
73 | }
|
74 | href = href.split('?')[1];
|
75 | if (href) {
|
76 | for (let param of href.split('&')) {
|
77 | let [k, v] = param.split('=');
|
78 | result[decodeURIComponent(k)] = decodeURIComponent(v);
|
79 | }
|
80 | }
|
81 | return result;
|
82 | }
|
83 |
|
84 | static isState(state, className = 'active') {
|
85 | if (global.state.indexOf(state) === 0) {
|
86 | return className;
|
87 | }
|
88 | }
|
89 | }
|
90 |
|
91 | export class BaseRouter extends BackboneSubRoute {
|
92 | constructor(prefix, options, mainElement) {
|
93 | super(prefix, options);
|
94 |
|
95 |
|
96 | for (let rt of Object.keys(this.routes)) {
|
97 | let rtObj = this.routes[rt];
|
98 | if (rtObj instanceof IncludeDefinition) {
|
99 |
|
100 | new rtObj.router(rt, options, mainElement);
|
101 | delete this.routes[rt];
|
102 | } else {
|
103 | _stateRouteMapping[rtObj.state] = {route: rt, router: this};
|
104 | }
|
105 | }
|
106 |
|
107 | this.on('route', function (urlDef, args) {
|
108 | var Controller = urlDef.controller;
|
109 | var routeContext = {
|
110 | currentState: urlDef.state,
|
111 | element: mainElement
|
112 | };
|
113 | var midPromises = [];
|
114 | for (var mid of runtime.middleware) {
|
115 | if (mid.preControllerInit) {
|
116 | midPromises.push(mid.preControllerInit());
|
117 | }
|
118 | }
|
119 | Promise.all(midPromises).then(() => {
|
120 | global.state = urlDef.state;
|
121 | new Controller(routeContext).init(...args);
|
122 | }, (error) => {
|
123 | if (error) {
|
124 | console.log(error);
|
125 | }
|
126 | });
|
127 | });
|
128 | }
|
129 |
|
130 | get routes() {
|
131 | if (!this._routes) {
|
132 | this._routes = this.urlPatterns;
|
133 | }
|
134 | return this._routes;
|
135 | }
|
136 | }
|