2
0
mirror of https://github.com/frappe/books.git synced 2024-09-20 11:29:00 +00:00
books/common/router.js
2018-01-15 17:25:31 +05:30

99 lines
2.8 KiB
JavaScript

const frappe = require('frappe-core');
module.exports = class Router {
constructor() {
this.current_page = null;
this.static_routes = [];
this.dynamic_routes = [];
}
add(route, handler) {
let page = {handler: handler, route: route};
// '/todo/:name/:place'.match(/:([^/]+)/g);
page.param_keys = route.match(/:([^/]+)/g);
if (page.param_keys) {
// make expression
// '/todo/:name/:place'.replace(/\/:([a-z1-9]+)/g, "\/([a-z0-9]+)");
page.expression = route.replace(/\/:([a-z1-9]+)/g, "\/([a-z0-9]+)");
this.dynamic_routes.push(page);
this.sort_dynamic_routes();
} else {
this.static_routes.push(page);
this.sort_static_routes();
}
}
sort_dynamic_routes() {
// routes with fewer parameters first
this.dynamic_routes = this.dynamic_routes.sort((a, b) => {
if (a.param_keys.length > b.param_keys.length) {
return 1;
} else if (a.param_keys.length < b.param_keys.length) {
return -1;
} else {
return a.route.length > b.route.length ? 1 : -1;
}
})
}
sort_static_routes() {
// longer routes on first
this.static_routes = this.static_routes.sort((a, b) => {
return a.route.length > b.route.length ? 1 : -1;
});
}
listen() {
window.addEventListener('hashchange', (event) => {
this.show(window.location.hash);
});
}
set_route(...parts) {
const route = parts.join('/');
window.location.hash = route;
}
async show(route) {
if (route && route[0]==='#') {
route = route.substr(1);
}
if (!route) {
route = this.default;
}
let page = this.match(route);
if (page) {
if (typeof page.handler==='function') {
await page.handler(page.params);
} else {
await page.handler.show(page.params);
}
}
}
match(route) {
// match static
for(let page of this.static_routes) {
if (page.route === route) {
return {handler: page.handler};
}
}
// match dynamic
for(let page of this.dynamic_routes) {
let matches = route.match(new RegExp(page.expression));
if (matches && matches.length == page.param_keys.length + 1) {
let params = {}
for (let i=0; i < page.param_keys.length; i++) {
params[page.param_keys[i].substr(1)] = matches[i + 1];
}
return {handler:page.handler, params: params};
}
}
}
}