Skip to content

Instantly share code, notes, and snippets.

@lusentis
Created May 28, 2013 15:50
Show Gist options
  • Save lusentis/5663779 to your computer and use it in GitHub Desktop.
Save lusentis/5663779 to your computer and use it in GitHub Desktop.
Simple router for the browser.
var routes = {
'/login': login
, '/admin': adminIndex
, '/404': function () { alert('404 not found'); router.navigate('/'); } // mandatory
};
var router = new Router(routes);
router.attach();
router.initial('/login', true); // Forces going to login
router.on('navigate:before', function () { console.log('AfterNavigate'); });
router.on('navigate:after', function (section_id) { /* ... */ });
/*jshint browser:true, laxcomma:true, indent:2 */
/*
* (c) 2013 Plastic Panda Snc
* All rights reserved.
*
* License: BSD
* Author: Simone Lusenti <simone@plasticpanda.com>
*/
(function (root) {
var _getHash = function () {
return window.location.hash.replace('#', '');
};
var _matchRoute = function (routes, url) {
var ret = null;
Object.keys(routes).forEach(function (routeDef) {
// Case-sensitive non-regexp matching
if (routeDef.toUpperCase() === url.toUpperCase()) {
ret = [routeDef];
return true;
} else {
var escapedRouteDef = RegExp.escape(routeDef);
escapedRouteDef = escapedRouteDef.replace(/:[a-zA-Z][a-zA-Z0-9]/g, '(.+)');
var matches = new RegExp(escapedRouteDef, 'ig');
matches = matches.exec(url);
if (matches !== null) {
ret = [routeDef, matches.slice(1)];
return true;
}
}
});
return ret;
};
var _hashChangeHandler = function (e) {
this.trigger('navigate:before');
var that = this;
var routeDef = _matchRoute(this.routes, _getHash());
if (!routeDef && _getHash() !== '/404') {
this.navigate('/404');
} else {
var routeHandlers = this.routes[routeDef[0]]
, _dispatchHandler = function (handler) {
handler.apply(that, routeDef[1]);
};
if (Array.isArray(routeHandlers)) {
routeHandlers.forEach(_dispatchHandler);
} else {
_dispatchHandler(routeHandlers);
}
}
this.trigger('navigate:after');
};
function Router(routes) {
if (typeof routes !== 'object') {
throw new Error('Router constructor requires a routes parameter.');
}
this.routes = routes;
}
Router.prototype = Object.create(EventEmitter.prototype);
Router.prototype.attach = function () {
var that = this;
window.addEventListener('hashchange', function (e) { _hashChangeHandler.call(that, e); }, false);
};
Router.prototype.initial = function (initialRoute, force) {
if (initialRoute) {
if (_getHash() === '' || force) {
this.navigate(initialRoute);
}
}
};
Router.prototype.navigate = function (newHash) {
window.location.hash = newHash;
};
window.Router = Router;
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment