Migrate from hasher.js to history.js to support HTML5-style navigation. Also clean up the HMR support.

This commit is contained in:
SteveSandersonMS
2016-03-08 15:56:43 +00:00
parent bbdbb449d5
commit 515c659a47
14 changed files with 390 additions and 190 deletions

View File

@@ -1,7 +1,5 @@
import * as ko from 'knockout';
import * as crossroads from 'crossroads';
import * as hasher from 'hasher';
import { routes } from './routes';
// This module configures crossroads.js, a routing library. If you prefer, you
// can use any other routing library (or none at all) as Knockout is designed to
@@ -11,23 +9,41 @@ import { routes } from './routes';
// specifies a 'page', which is a Knockout component) - there's nothing built into
// Knockout that requires or even knows about this technique. It's just one of
// many possible ways of setting up client-side routes.
export class Router {
public currentRoute = ko.observable<Route>({});
private disposeHistory: () => void;
private clickEventListener: EventListener;
constructor(routes: Route[]) {
// Configure Crossroads route handlers
constructor(history: HistoryModule.History, routes: Route[]) {
// Reset and configure Crossroads so it matches routes and updates this.currentRoute
crossroads.removeAllRoutes();
crossroads.resetState();
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
routes.forEach(route => {
crossroads.addRoute(route.url, (requestParams) => {
this.currentRoute(ko.utils.extend(requestParams, route.params));
});
});
// Activate Crossroads
crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
hasher.initialized.add(hash => crossroads.parse(hash));
hasher.changed.add(hash => crossroads.parse(hash));
hasher.init();
// Make history.js watch for navigation and notify Crossroads
this.disposeHistory = history.listen(location => crossroads.parse(location.pathname));
this.clickEventListener = evt => {
let target: any = evt.target;
if (target && target.tagName === 'A') {
let href = target.getAttribute('href');
if (href && href.charAt(0) == '/') {
history.push(href);
evt.preventDefault();
}
}
};
document.addEventListener('click', this.clickEventListener);
}
public dispose() {
this.disposeHistory();
document.removeEventListener('click', this.clickEventListener);
}
}
@@ -35,10 +51,3 @@ export interface Route {
url?: string;
params?: any;
}
export function instance() {
// Ensure there's only one instance. This is needed to support hot module replacement.
const windowOrDefault: any = typeof window === 'undefined' ? {} : window;
windowOrDefault._router = windowOrDefault._router || new Router(routes);
return windowOrDefault._router;
}