Created
June 27, 2012 18:05
-
-
Save jbroadway/3005741 to your computer and use it in GitHub Desktop.
Simple History.js-based client-side router
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var app = (function ($) { | |
var self = {}; | |
// change pages via app.go('/new/page') or app.go(-1) | |
self.go = function (url) { | |
if (url === parseInt (url)) { | |
History.go (url); | |
} else { | |
History.pushState (null, null, url); | |
} | |
}; | |
// handle click events | |
self.click_handler = function (e) { | |
var url = $(this).attr ('href'), | |
title = $(this).attr ('title'); | |
if (url.match (/:\/\//)) { | |
return true; | |
} | |
if (url === '#') { | |
return false; | |
} | |
e.preventDefault (); | |
History.pushState ({}, title, url); | |
}; | |
// show home | |
self.show_home = function () { | |
alert ('Home!'); | |
}; | |
// show item | |
self.show_item = function (id) { | |
alert ('Item ' + id); | |
}; | |
return self; | |
})(jQuery); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="history.js"></script> | |
<script src="router.js"></script> | |
<script src="app.js"></script> | |
<script src="init.js"></script> | |
<p><a href="/">Home</a> | <a href="/item/123">Item 123</a> | <a href="/item/456">Item 456</a></p> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (window, undefined) { | |
var History = window.History; | |
if (! History.enabled) { | |
return false; | |
} | |
router.set_routes ({ | |
'/': app.show_home, | |
'/item/:id': app.show_item | |
// ...etc... | |
}); | |
History.Adapter.bind (window, 'statechange', function () { | |
var State = History.getState (); | |
router.route (State.url); | |
}); | |
// catch all link clicks | |
$('body').on ('click', 'a', app.click_handler); | |
// now use app.go(url) to move around | |
router.route (router.get_path (window.location.href)); | |
})(window); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A simple router class to be used in conjunction with History.js. | |
* Triggers the appropriate callback function when `router.route(url)` | |
* is called. | |
* | |
* Usage: | |
* | |
* <script src="history.js"></script> | |
* <script src="router.js"></script> | |
* <script> | |
* (function (window, undefined) { | |
* var History = window.History; | |
* if (! History.enabled) { | |
* return false; | |
* } | |
* | |
* function handler_one () { | |
* console.log ('handler_one() called!'); | |
* } | |
* | |
* function handler_two (name) { | |
* console.log ('handler_two() called!'); | |
* console.log (name); | |
* } | |
* | |
* router.set_routes ({ | |
* '/one': handler_one, | |
* '/hello/:name': handler_two | |
* }); | |
* | |
* History.Adapter.bind (window, 'statechange', function () { | |
* var State = History.getState (); | |
* router.route (State.url); | |
* }); | |
* | |
* History.pushState (null, null, '/one'); | |
* History.pushState (null, null, '/hello/world'); | |
* })(window); | |
* </script> | |
*/ | |
var router = (function () { | |
var router = {}; | |
// list of routes | |
router.routes = {}; | |
// create once, used by get_path() | |
router.a = document.createElement ('a'); | |
// turn a url into a regex and params | |
router.regexify = function (url) { | |
var res = { | |
url: url, | |
regex: null, | |
params: [] | |
}; | |
// parse for params | |
var matches = url.match (/\:([a-zA-Z0-9_]+)/g); | |
if (matches !== null) { | |
for (var i in matches) { | |
matches[i] = matches[i].substring (1); | |
} | |
res.params = matches; | |
url = url.replace (/\:([a-zA-Z0-9_]+)/g, '(.*?)'); | |
} | |
res.regex = url.replace ('/', '\\/'); | |
return res; | |
}; | |
// set a list of routes and their callbacks | |
router.set_routes = function (routes) { | |
for (var url in routes) { | |
res = router.regexify (url); | |
var r = { | |
url: url, | |
regex: new RegExp ('^' + res.regex + '/?$', 'g'), | |
params: res.params, | |
callback: routes[url] | |
}; | |
router.routes[url] = r; | |
} | |
}; | |
// get the relative path from a full url | |
router.get_path = function (url) { | |
router.a.href = url; | |
return router.a.pathname + router.a.search + router.a.hash; | |
}; | |
// handle the routing for a url | |
router.route = function (url) { | |
var path = router.get_path (url); | |
for (var i in router.routes) { | |
var matches = router.routes[i].regex.exec (path); | |
router.routes[i].regex.lastIndex = 0; | |
if (matches !== null) { | |
if (matches.length > 1) { | |
matches.shift (); | |
router.routes[i].callback.apply (null, matches); | |
} else { | |
router.routes[i].callback (); | |
} | |
break; | |
} | |
} | |
}; | |
return router; | |
})(); |
Note that you need to do something like to get it working with IE11!
getPath(url) {
this.a.href = url;
// IE11 returns path name without a leading /, which the regexes need
const pathName = this.a.pathname.indexOf('/') !== 0 ? `/${this.a.pathname}` : this.a.pathname;
return `${pathName}${this.a.search}${this.a.hash}`;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thanks for this code, exactly what i am looking for :)