Created
June 22, 2015 04:21
-
-
Save OhMeadhbh/1f3c668e2a472dd3c69a to your computer and use it in GitHub Desktop.
Simple Hash-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
| // 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) ); } | |
| }; | |
| } ) (); |
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
| <!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"> </div> | |
| <div class="block" id="content"> </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