Skip to content

Instantly share code, notes, and snippets.

@hmarquardt
Created July 28, 2014 14:46
Show Gist options
  • Save hmarquardt/ca556dc12fab4871f510 to your computer and use it in GitHub Desktop.
Save hmarquardt/ca556dc12fab4871f510 to your computer and use it in GitHub Desktop.
Simple OnHashChange router and sample app implementation. Uses RegEx captures for generic routes, but allows for named routes and overrides as well.
Router = {};
/*
A route should look like this:
{
route: /<regExp>/,
controller: <string name of controller implemented by appObj>,
template: <string name of DOM ID containing template to be rendered, populated by controller>,
slugs: [array of named parameters populated by regex group in route, may override/implement controller
and template via regex group]
}
Examples:
{ route: /^\/$/, controller: "indexPageController", template: "indexPage" } // Regex for /, Slugs will be declared []
{ route: /^\/([a-zA-Z]+)$/, slugs: ["controller"] } // contoller implemented by regex capture
{ route: /^\/([a-zA-Z]+)\/([0-9]+)/, slugs: ["controller","id"] } id named parameter implemented
*/
Router.routes = [];
Router.dispatch = function(appObj) {
var url = location.hash.slice(1) || '/';
for(var x=0; x<Router.routes.length; x++) {
if(matches = url.match(Router.routes[x].route)) {
var parameters = {};
matches.shift();
console.log(matches,Router.routes[x]);
Router.routes[x].slugs = Router.routes[x].slugs || [];
for(var y=0; y < Router.routes[x].slugs.length; y++) {
parameters[Router.routes[x].slugs[y]] = matches[y];
}
parameters.controller = parameters.controller || Router.routes[x].controller
parameters.template = parameters.template || Router.routes[x].template || parameters.controller.replace(/[Cc]ontroller/,'');
if(parameters.hasOwnProperty('controller')) {
if(appObj.hasOwnProperty(parameters.controller)) {
appObj[parameters.controller](parameters);
} else if(appObj.hasOwnProperty(parameters.controller+'Controller')) {
appObj[parameters.controller+'Controller'](parameters);
} else {
Router.error(appObj,{url: url, msg: 'Controller not implemented in Application'});
}
return;
} else {
Router.error(appObj,{url: url, msg: 'Could not route url'});
return;
}
}
}
Router.error(appObj,{url: url, msg: 'No matching route for url'});
}
Router.error = function(appObj,errObj) {
if(appObj.hasOwnProperty('errorController')) {
appObj.errorController(errObj);
} else {
console.log("Something bad happened and no error controller defined",errObj);
}
}
Router.routes = [
{route: /^\/$/, controller: 'indexController'}, // handle the index page of a naked /
{route: /^\/myAwesomeController$/i, controller: 'detailController', template: 'detailTemplate'},
{route: /^\/([a-zA-Z]+[a-zA-Z0-9_-]*)$/, slugs: ['controller']}, // single annonymous controller
{route: /^\/([a-zA-Z]+[a-zA-Z0-9_-]*)\/([0-9]+)$/, slugs: ['controller','id'] },
{route: /^\/([a-zA-Z]+[a-zA-Z_-]*)\/([a-zA-Z]+[a-zA-Z_-]*)$/, slugs: ['controller','action'] },
{route: /^\/([a-zA-Z]+[a-zA-Z_-]*)\/([a-zA-Z]+[a-zA-Z0-9_-]*)\/([0-9]+)$/, slugs: ['controller','action','id'] },
];
/* Test Implentation */
if(!window.console) { window.console = {}; }
if(!window.console.log) { window.console.log = function() { } }
myApp = {};
myApp.indexController = function(params) { console.log('Handled index or raw hash with indexController ',params); }
myApp.detailController = function(params) { console.log('Called myAwesomeController, handled by detailController with ',params); }
myApp.homeController = function(params) { console.log('Called Home with ',params); }
myApp.myrandom = function(params) { console.log('Called Home with ',params); }
myApp.orderController = function(params) { console.log('Called Home with ',params); }
myApp.errorController = function(url) { console.log('Fo Shizzle!',url); }
window.onhashchange = function() { Router.dispatch(myApp); }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment