-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
117 lines (104 loc) · 3.88 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
;(function(window) {
var RiotFlow = function(routes, riot) {
this._registeredObservers = [];
this._routes = routes;
// Auto-load riot, if we need to and can
if(!riot) {
// CommonJS
if(typeof module !== 'undefined' && module.exports)
{
riot = require('riot');
} else if (window) {
riot = window.riot
}
}
if(riot) {
riot.route.stop();
riot.route.start();
riot.route(this._router.bind(this));
riot.route.exec();
riot.router = this;
}
};
RiotFlow.prototype.registerObserver = function(el) {
this._registeredObservers.push(el);
};
RiotFlow.prototype._matchTargetSegmentToRouteName = function(targetSegment, routeName) {
if (targetSegment == routeName) {
return true;
} else if (routeName[0] == ':') {
return 'symbol';
} else {
return false;
}
};
// Recursive function for matching paths to routes
RiotFlow.prototype._matchRoute = function(segments, depth, routes) {
var targetSegment = segments[depth];
var params = {};
for (var routeName in routes) {
if (routes.hasOwnProperty(routeName)) {
// If the segment at the current level matches a route on that level,
// try to resolve the route
if(this._matchTargetSegmentToRouteName(targetSegment, routeName)) {
// Extract params from path segments
if (this._matchTargetSegmentToRouteName(targetSegment, routeName) == 'symbol') {
params[routeName.substr(1)] = targetSegment;
}
// A function means that we can resolve the route
if(typeof(routes[routeName]) == 'function') {
return {params: params, routeFunction: routes[routeName], matched: true};
// An object means that we need to go into subroutes
} else if (segments.length > depth + 1) {
return this._matchRoute(segments, depth + 1, routes[routeName]);
// Only accept functions, arrays, and objects
} else {
return {params: params, routeFunction: undefined, matched: false};
}
}
}
}
// If matching fails, fall back to catchall
return {params: params, routeFunction: routes['*'] || undefined, matched: false};
};
RiotFlow.prototype._notifyRegisteredObservers = function(path, params) {
this._registeredObservers.forEach(function(observer, i, observers) {
observer.trigger(path, params);
})
};
RiotFlow.prototype._router = function() {
// Fancy code to avoid killing arguments optimization
// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
var pathSegments = new Array(arguments.length);
for(var i = 0; i < pathSegments.length; ++i) {
pathSegments[i] = arguments[i];
}
// Add trailing '' if it doesn't exist yet so that index routes in subroutes
// get processed
if (pathSegments.length > 1) {
pathSegments.push('');
}
var routeInfo = this._matchRoute(pathSegments, 0, this._routes);
var path = pathSegments.join('/');
if (routeInfo && routeInfo.routeFunction) {
var routeFunction = routeInfo.routeFunction;
var params = routeInfo.params;
routeFunction(path, params);
if(routeInfo.matched) {
this._notifyRegisteredObservers('routeMatch', path, params)
} else {
this._notifyRegisteredObservers('routeFallback', path, params)
}
} else {
console.error('Failed to find route for path "' + path + '".');
this._notifyRegisteredObservers('routeFailure', path, null)
}
};
// support CommonJS, AMD & browser
if (typeof module !== 'undefined' && module.exports)
module.exports = RiotFlow
else if (typeof define === 'function' && define.amd)
define(function() { return (window.RiotFlow = RiotFlow) })
else
window.RiotFlow = RiotFlow
})(typeof window != 'undefined' ? window : void 0)