router.js

/**
 * 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
 * compose cleanly with external libraries.
 *
 * You *don't* have to follow the pattern established here (each route entry
 * 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.
 *
 * @module app/router
 * @requires knockout
 * @requires crossroads
 * @requires hasher
 * @requires jquery
 */
define(['knockout', 'crossroads', 'hasher', 'jquery'], function(ko, crossroads,
    hasher, $) {
    return new Router({
        routes: [{
            url: 'create',
            params: {
                page: 'home-page'
            }
        }, {
            url: 'edit/:id:/',
            params: {
                page: 'home-page'
            }
        }, {
            url: 'report-edit/:id:/',
            params: {
                page: 'report-edit'
            }
        }, {
            url: 'report-list',
            params: {
                page: 'report-list'
            }
        }, {
            url: 'report-view/:id:/',
            params: {
                page: 'report-view'
            }
        }, {
            url: 'about',
            params: {
                page: 'about-page'
            }
        }, {
            url: '',
            params: {
                page: 'templates-list'
            }
        }, {
            url: 'visit-list',
            params: {
                page: 'visit-list'
            }
        }]
    });


    function parseHash(newHash, oldHash) {
        setTimeout(function() {
            var prop,
                subscriptions = ko.postbox ? ko.postbox.subscriptions : null;
            if (subscriptions) {
                for (prop in subscriptions) {
                    if (prop !== 'showHamburger') {
                        if (subscriptions.hasOwnProperty(prop)) {
                            subscriptions[prop].dispose();
                        }
                    }
                }
            }

        }, 1);

        crossroads.parse(newHash);
    }

    function activateCrossroads() {
        crossroads.normalizeFn = crossroads.NORM_AS_OBJECT;
        hasher.initialized.add(parseHash);
        hasher.changed.add(parseHash);
        hasher.init();
    }

    function Router(config) {
        var currentRoute = this.currentRoute = ko.observable({});
        ko.utils.arrayForEach(config.routes, function(route) {
            crossroads.addRoute(route.url, function(requestParams) {
                currentRoute(ko.utils.extend(requestParams, route.params));
            });
        });

        activateCrossroads();
    }

});