Skip to content

Instantly share code, notes, and snippets.

@OhMeadhbh
Created June 22, 2015 04:21
Show Gist options
  • Select an option

  • Save OhMeadhbh/1f3c668e2a472dd3c69a to your computer and use it in GitHub Desktop.

Select an option

Save OhMeadhbh/1f3c668e2a472dd3c69a to your computer and use it in GitHub Desktop.
Simple Hash-Router
// HashRouter.js - an object that routes through a table to an object + method
// based on a the "hash" portion of a http(s) URL. Designed to be much, much
// simpler than the Backbone router.
// Copyright (c) 2015 Meadhbh S. Hamrick
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
( function () {
// Pass a descriptor and a target to the constructor. The descriptor is
// an object containing the name of the default route and the routing table.
window.HashRouter = function HashRouter( descriptor, target ) {
this.target = target?target:this;
this.default = descriptor ?
( descriptor.default ? descriptor.default : '_default' ):
'_default';
this.routes = descriptor ?
( descriptor.routes ? descriptor.routes : [] ):
[];
this.routes.forEach( function( e ) {
e[ 0 ] = new RegExp( '^' + e[ 0 ] + '$' )
} );
}
// Call the route() method with a path string (like "#/foo/1/2/3")
// to call method in the target associated with the path pattern.
HashRouter.prototype.route = function ( path ) {
var results, method, args;
for( var i = 0, il = this.routes.length; i < il; i++ ) {
results = this.routes[ i ][ 0 ].exec( path );
if( Array.isArray( results ) ) {
method = this.routes[ i ][ 1 ];
args = results.slice( 1, results.length );
break;
}
}
method = method ? method : this.default ;
args = args ? args : [] ;
args.unshift( path );
if( 'function' == typeof this.target[ method ] ) {
this.target[ method ].apply( this.target, args );
}
};
// This is a convenience function to use like:
// var router = new HashRouter( descriptor, target );
// window.addEventListener( "hashchange", HashRouter.HashChange( router ) );
HashRouter.HashChange = function ( router ) {
return function () { router.route( location.hash.substr(1) ); }
};
} ) ();
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html, body {
width: 100%;
}
body {
background-color: #BFBFBF;
font-family: Helvetic, Sans-Serif;
}
body, div, p {
margin: 0px;
padding: 0px;
}
.block {
padding: 8px 12px 4px 12px;
margin: 8px 12px 4px 12px;
border: solid 1px black;
border-radius: 4px;
}
#title {
font-weight: bold;
}
#content {
position: fixed;
left: 0px;
right: 0px;
bottom: 0px;
top: 40px;
}
</style>
<script type="text/javascript" src="./HashRouter.js"></script>
<script type="text/javascript">
var templates = {}, router, app, title, content;
var route_descriptor = {
default: '_default',
routes: [
[ '/item', '_item_list' ],
[ '/item/(.*)', '_item' ],
[ '/point/(.*)/(.*)', '_point' ]
]
};
var items = [
{ id: "101", name: "whatever" },
{ id: "201", name: "black perl" },
{ id: "202", name: "larb" }
];
document.addEventListener( 'DOMContentLoaded', function () {
var a = document.getElementsByTagName( 'script' );
title = document.getElementById( 'title' );
content = document.getElementById( 'content' );
for( var i = 0, il = a.length; i < il; i++ ) {
var current = a[ i ];
templates[ current.id ] = current.innerHTML;
}
app = new App();
router = new HashRouter( route_descriptor, app );
window.addEventListener( 'hashchange', HashRouter.HashChange( router ) );
if( location.hash.length < 2 ) {
location.hash = "#/default";
}
router.route( location.hash.substr(1) );
} );
function App() {
}
App.prototype._default = function( path ) {
this._title( path );
this._content( templates[ path ] ? templates[ path ] : templates[ '/default' ] );
};
App.prototype._item_list = function( path ) {
this._title( path );
var stuff = '<table style="width: 100%; border: solid 1px black;"><tr><td>id</td><td>name</td></tr>';
for( var i = 0, il = items.length; i < il; i ++ ) {
stuff += '<tr><td><a href="#/item/' + items[ i ].id + '">' + items[ i ].id + "</a></td><td>" + items[ i ].name + "</td></tr>";
}
stuff += "</table>";
this._content( stuff );
};
App.prototype._item = function( path, id ) {
var stuff;
this._title( path );
for( var i = 0, il = items.length; i < il; i++ ) {
if( id == items[ i ].id ) { break; }
}
if( i < il ) {
stuff = "<p>Item: " + items[ i ].id + ", Name: " + items[i].name + "</p>";
} else {
stuff = templates[ 'unknown_item' ];
}
this._content( stuff );
};
App.prototype._point = function( path, x, y ) {
this._title( path );
this._content( "<p>X: " + x + ", Y: " + y + "</p>" );
};
App.prototype._title = function( text ) {
title.innerHTML = text;
};
App.prototype._content = function( text ) {
content.innerHTML = text;
};
</script>
</head>
<body>
<div class="block" id="title">&nbsp;</div>
<div class="block" id="content">&nbsp;</div>
<script id="/default" type="text/html">
<p>
So here's the default page. You <em>should</em> see this when you first load this page. <a href="#/another">Click here</a> to
see another page routed to by the default router.
</p>
<p>
<a href="#/item">Click here</a> for a list of items. And you can <a href="#/point/12/37">click here</a> to see a point.
</p>
</script>
<script id="/another" type="text/html">
<p>
Nothing to see here. Move along.
</p>
</script>
<script id="unknown_item" type="text/html">
<p>
Unknown item.
</p>
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment