-
Notifications
You must be signed in to change notification settings - Fork 1
/
router.js
121 lines (97 loc) · 2.93 KB
/
router.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
118
119
120
121
(function() {
// Node
if(typeof module !== 'undefined' && module.exports) {
var EventEmitter = require('eventemitter');
onload(EventEmitter);
}
// AMD
else if(typeof define !== 'undefined' && define.amd) {
define(['eventemitter'], onload);
}
// Browser
else {
onload(window.EventEmitter);
}
function onload(EventEmitter) {
var PARAM_PATTERN = /:([a-zA-Z0-9_]+)/g;
var PARAM_CAPTURE = '(.*?)';
function Router(options) {
EventEmitter.call(this);
var listenedEvent = 'popstate';
if(options && options.useHash){
this.useHash = options.useHash;
listenedEvent = 'hashchange';
}
if(typeof window !== 'undefined') {
var dispatchedUrl = window.location.pathname;
var self = this;
window.addEventListener(listenedEvent, function() {
if(options && options.useHash){
dispatchedUrl = window.location.hash.substring(1);
}
self.dispatch(dispatchedUrl);
}, false);
}
}
Router.prototype = Object.create(EventEmitter.prototype);
Router.prototype.define = function(routes) {
this.routes = {};
for(routeName in routes) {
var pattern = routes[routeName];
var params = [];
while(res = PARAM_PATTERN.exec(pattern)) {
params.push(res[0]);
}
var regexp = pattern;
params.forEach(function(paramName) {
regexp = regexp.replace(paramName, PARAM_CAPTURE);
});
this.routes[routeName] = {
pattern: pattern,
regexp: '^' + regexp + '$',
params: params.map(function(param) { return param.substring(1); }),
name: routeName
};
}
};
Router.prototype.dispatch = function(url) {
for(routeName in this.routes) {
var route = this.routes[routeName];
var matches = url.match(route.regexp);
if(!matches) {
continue;
}
var values = matches.slice(1);
var object = {};
route.params.forEach(function(paramName, idx) {
object[paramName] = values[idx];
});
this.emit('route', routeName, object);
return;
}
this.emit('notfound', url);
};
Router.prototype.navigate = function(url) {
if(typeof window === 'undefined') return;
if(!this.useHash) {
window.history.pushState(null, null, url);
this.dispatch(url);
} else {
url = url.substring(1);
window.location.hash = url;
}
};
// Node
if(typeof module !== 'undefined' && module.exports) {
module.exports = Router;
}
// AMD
else if(typeof define !== 'undefined' && define.amd) {
return Router;
}
// Browser
else {
window.Router = Router;
}
}
})();