js/runtime/router.js
// NPM IMPORTS
import assert from 'assert'
import Crossroads from 'crossroads'
import Hasher from 'hasher'
// COMMON IMPORTS
import T from '../../../node_modules/devapt-core-common/dist/js/utils/types'
// BROWSER IMPORTS
import RouterState from './router_state'
const context = 'browser/runtime/router'
/**
* @file Browser navigation router class.
*
* @author Luc BORIES
*
* @license Apache-2.0
*/
export default class Router extends RouterState
{
/**
* Create a Router instance.
* @extends RouterState
*
* A Router instance manages a navigation history and update the page on navigation change.
* Navigation history is an array stored into the Redux store.
* Actions are:
* * display_content(view name, menubar name): update page content with given view and menubar.
* * go_backward(): update page with history previous content if available.
* * go_forward(): update page with history next content if available.
* * clear_history(): reset history array.
*
* API:
* ->init(arg_home_view_name, arg_home_menubar_name)
* ->add_handler(arg_route, arg_handler)
* ->update_hash_self(arg_view_name, arg_menubar_name)
* ->display_content_self(arg_view_name, arg_menubar_name)
*
* @param {string} arg_log_context - context of traces of this instance (optional).
*
* @returns {nothing}
*/
constructor(arg_log_context)
{
const log_context = arg_log_context ? arg_log_context : context
super(log_context)
this.is_router = true
this._router_engine = Crossroads
this._hasher = Hasher
// DEBUG
// log all routes
// this._router_engine.routed.add( (request, data)=>{ console.log('route found', request, data) } )
// log all requests that were bypassed / not matched
this._router_engine.bypassed.add( (request)=>{ console.warn('route not found', request) } )
assert( T.isObject(this._state_store), context + ':constructor:bad state_store object')
}
/**
* Init router.
*
* @param {string} arg_home_view_name - Home view name.
* @param {string} arg_home_menubar_name - Home menubar name.
*
* @returns {nothing}
*/
init(arg_home_view_name, arg_home_menubar_name)
{
// REGISTER HOME PAGE ROUTE
// this.add_handler('',
// () => {
// return this.do_action_display_content(arg_home_view_name, arg_home_menubar_name)
// }
// )
// REGISTER IGNORE ROUTE
this.add_handler('ignore:{path}',
()=>{
// NOTHING TODO
}
)
this.add_handler('ignore_{path}',
()=>{
// NOTHING TODO
}
)
// REGISTER A PAGE ROUTE (view, menubar)
var route = 'view\={view}\,menubar\={menubar}'
this.add_handler(route,
(arg_view, arg_menubar) => {
return this.do_action_display_content(arg_view, arg_menubar)
}
)
// SETUP HASHER
const parseHash = (arg_newHash, arg_oldHash) => {
// console.log('Hasher parse cb for new [%s] and old [%s]', arg_newHash, arg_oldHash)
// debugger
this._router_engine.parse(arg_newHash)
}
Hasher.prependHash = ''
Hasher.setHash('/')
Hasher.initialized.add(parseHash) //parse initial hash
Hasher.changed.add(parseHash) //parse hash changes
Hasher.init() //start listening for history change
}
/**
* Add a route handler.
*
* @param {string|RegExp} arg_route - route.
* @param {Function} arg_handler - f(args)
*
* @returns {nothing}
*/
add_handler(arg_route, arg_handler)
{
// console.log('Crossroads add route handler for route:', arg_route)
this._router_engine.addRoute(arg_route,
(...args) => {
// var hash = Hasher.getHash()
// console.log('Crossroads route cb with hash [%s] and args:', hash, args)
return arg_handler(args)
}
)
}
/**
* Parse an url and route it.
*
* @param {string} arg_url - url to route.
*
* @returns {nothing}
*/
parse(arg_url)
{
const app_url = this._state_store.get_state().get('app_url', undefined)
arg_url = (app_url.length > 0 && app_url[0] == '/' ? '' : '/') + app_url + arg_url
if ( arg_url.endsWith('/') )
{
arg_url = arg_url.substr(0, arg_url.length - 1)
}
this._router_engine.parse(arg_url)
}
/**
* Update page url with given view and menubar (update only the hash).
*
* @param {string} arg_view_name - view name.
* @param {string} arg_menubar_name - menubar name.
*
* @returns {nothing}
*/
// update_hash_self(arg_view_name, arg_menubar_name)
// {
// Hasher.changed.active = false
// Hasher.setHash('view=' + arg_view_name + ',menubar=' + arg_menubar_name)
// Hasher.changed.active = true
// }
set_hash_if_empty(arg_hash)
{
if ( Hasher.getHash() == '' )
{
Hasher.changed.active = false
Hasher.setHash(arg_hash)
Hasher.changed.active = true
}
}
}