-
Notifications
You must be signed in to change notification settings - Fork 3
/
router-alt.js
120 lines (99 loc) · 3.15 KB
/
router-alt.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
const trim = str => str.replace(/^[\s]+/ig, '').replace(/[\s]+$/ig, '')
export const router = (routes, fn=(a,b)=>a(b)) => {
let current = null
const listen = (onError) => {
window.addEventListener('hashchange', () => {
if(!trigger(window.location.hash.slice(1))){
(onError instanceof Function) && onError(window.location.hash.slice(1))
}
})
}
const trigger = path => {
for(let x in routes){
if(routes.hasOwnProperty(x)){
let v = match(x,path)
if(v){
fn(routes[x], v)
return true
}
}
}
return false
}
const match = (pattern, path) => {
let _patterns = pattern.split('/'),
parts = _patterns.map(x => {
switch(x[0]){
case ':': return '([^/]+)'
case '*': return '.*'
default: return x
}
}),
uris = path.split('/')
for(var i = 0; i < Math.max(parts.length, uris.length); i++){
let p = trim(parts[i]),
u = trim(uris[i]),
v = null
if(p === '' || u === ''){
v = p === '' && u === ''
} else {
v = new RegExp(p).exec(u)
}
if(!v) return false
}
return parts.reduce((a,v,i) => {
if(v[0] === ':')
return {...a, [v]: uris[i]}
return a
}, {})
}
return {
add: (name, fn) => !!(routes[name] = fn),
remove: name => !!(delete routes[name]) || true,
listen,
match,
trigger
}
}
// use a router inside a custom <Router> Component in React ...
// const app = () => {
// let [React, DOM] = [react, reactDom],
// {Component} = React
// class Home extends Component {
// constructor(...a){
// super(...a)
// }
// render(){
// return <div><h1>Home Screen</h1></div>
// }
// }
// export class Router extends Component {
// constructor(...a){
// super(...a)
// let p = this.props
// this.state = {
// routes: p.routes || {},
// default: p.default || '/'
// }
// this.router = router(this.state.routes, (el, props) => {
// this.current = el
// })
// this.router.trigger(this.state.default)
// }
// render(){
// return this.current()
// }
// }
// DOM.render(<Router routes={{
// '/': () => <Home/>
// }}/>, document.body)
// }
// require('react', 'react-dom').then(app)
// ... or use router outside of a React Component
// let x = router({
// '/:x/test/:y' : ({x,y}) => log({x,y}),
// '/': () => log('home screen')
// })
// log(x.match('/:x/test/:y', '/anything/test/anything')) // test a route pattern with a route
// x.trigger('/') // trigger the / route
// x.trigger('/hi/test/bye') // any named URI segments will be passed to the route callback