Fork me on GitHub
route.js

route.js is the smallest, easiest way to create stateful navigation based on unique location.hash's

route.js doesn't impose any other libraries or formats, handlers are arbitrarily bound to routes

route acquisition, RESTFul routing, an open library of route driven interfaces

jqUnit + debug.js = fully unit tested and fully loggable

standalone, but still best friends with jQuery

 

This entire site was built using route.js

try viewing source, enabling your browser's javascript console, or reading through the route.js lessons

Download

route.min.js (minified 1k)

route.js (unpacked, documented)

entire route.js example site


Github: http://github.com/marak/route.js

git clone git://github.com/Marak/route.js.git

Check out the Learn Section for more detailed usage

route('#/account').bind(customMethod);
route('#/account').bind(customMethod2);
route('#/websites').bind(customMethod);
route('#/websites').bind(function(){
  alert('custom closure');
});

route('#/account').run();
route('#/websites').run();
                
			
				
    route('#/account').bind(customMethod);
    route('#/account').bind(customMethod2);

    route('#/account/marak.squires').run();

    RESULT:
    No match found for '#/account/marak.squires' attempting to bubble with arguments {"path":"marak.squires"}
    Match found for '#/account', running customMethod and customMethod2 with custom arguments.

    Arguments are available as a global reference in windows.routes.args
                
			

Back   

Plain ole routing
binding an event to a route and then running the route
route('#/Learn').bind(function(){
  $('.panel').hide();
  $('#Learn').show();
});
	
route('#/Learn').bind(function(){
  Alert('showing panel');
});

route('#Learn').run();

in this basic example we are using closures to bind a custom method to the route '#/Learn'. when the route is run, every method which has been binded to that route will execute (in the order it was bound).

building on this concept we can create a custom route handler.

Binding routes to the browsers url bar
creating a simple cross-browser dispatcher to run routes when the browser’s location.hash changes

	
/* PROTIP: Use a Dispatcher! */
var Biggie={};
Biggie._hashchange_last = '';
Biggie._onhashchange=function(){
if(Biggie._hashchange_last!=location.hash){
  Biggie._hashchange_last=location.hash;
  route(location.hash).run();
}

/* use interval to check for changes on the location.hash 
   instead of trying to detect HTML5 hashchange event    */

setInterval(function () {Biggie._onhashchange();}, 50);	
                
			

now every time the location.hash of a browser is modified (via JavaScript, the browser’s url bar, or the browser’s back button) Biggie will attempt to run any routes bound to that location.hash. Any methods bound to that route will be executed.

notice there is a 50 ms poll checking for location.hash changes. in HTML5 we could use the browser’s new hashchange event, unfortunately there simply isn’t cross browser support for onhashchange so we are stuck with a 50ms interval.

now that have covered the basics, lets create a simple interface to bind our pages to their repsective DOM elements

Creating Custom Route Handlers
route.js has an insanely easy scheme for creating custom event handlers for routes.

first, create an event.

var togglePanel = function(){
  $('.panel').hide();
  $('#Learn').show();
});

then...
route('/#Learn').bind(togglePanel);

Simple as cake! Now, everytime the route '/#Learn' is entered, all divs with the class "panel" will hide.

now, let's try to pass some arguments to our route

Passing arguments to routes
binding handlers (with arguments) to a route and deferring the passing of the arguments until the route is run

let's create a route handler that will toggle between panels based on panel id


/* define handler with arguments */
var togglePanel = function(selector){
     $('.panel').hide();
     $(selector).show();	 
};

/* bind handler to route */   
route('#/Learn').bind(togglePanel); 

/* later, we declare arguments and run the route */
var selector = "#Learn";
route('#/Learn').run(selector); 
	  
	  

this is all very basic, low level routing. in most cases you will use route acquisition to automatically pass along route arguments for you

Route Acquisition 101
intelligent bubbling of routes, dynamic routing, route lookup

let's assume you wanted to create a simple parent -> child relationship with your routes, a simple example is to think of "pages" within your website.

the parent will be the browser's root location.hash: "/#", the children will be the "pages":"/Why","/Learn","/Documentation"

lets create a handler that will log all page requests


/* define handler with arguments */

var logPage = function(page){
  debug.log(page);
};

route('#').bind(logPage);


route('#/Learn').run();
	  
	  

notice that there is no direct match for '#/Learn'?

what is going to happen here?

route.run('#/Learn');
no routes were found...attempting to bubble with arguments: "path":"Learn"

route.run('#');
route(s) found for '#'
executing :function (page) { debug.log(page); }

Output: Object path=Learn

			
			

Win!

now it is time to create a simple event dispatcher for location.hash changes!

creating route formats that imply structure
Binding routes to DOM elements
setting up simple route navigation based on static DOM elements

Javascript:




/* create handler for loading panels */
var loadPanel = function(page){ 
  $('.panel').hide();
  $('#' + page.path).show();
}; 
route('#').bind(loadPanel); 

route('#/Why').run(); /* loads the Why panel */
route('#/Examples').run(); /* loads the Examples panel */
route('#/Documentation').run(); /* loads the Documentation panel */
	
	

HTML:


<style>
	.panel{display:none;}
</style>

<div class="panel" id="Why">This is the Why section.</div>

<div class="panel" id="Learn">This is the Learn section</div>

<div class="panel" id="Documentation">This is the Documentation section</div>
	
	
	

notice we don't have to define any of our panels explicity in the route.js code? since we have bound our loadPanel handler to "#" (the location.hash root) any routes that don't match exactly will bubble to root route handler(see: route acquisition)

If you are new to route.js I would suggest looking at the examples first.

route(path) - top level selector:

route(path);

/* 
   returns route object for path. if no route is found, null route is returned.
   path is a string which should be in a location.hash format.
   
   in most cases you will never need to access the route object directly
*/   
   
examples: 

	route('#/websites');
	route('#/account'); 
	route('/#account/marak.squires/edit');
            

route(path).bind(fn);

route(path).bind(function);

/* 
   binds an arbitrary function to a route that will be executed when the route is run
   path is a string which should be in a location.hash format.
   fn is a function.

*/


examples:

	route('#/Learn').bind(function(){ 
	  Alert('Alert1'); 	  
	}); 
	
	var myFunction = function(){
	  Alert('Alert2'); 
	};
	 
	route('#/Learn').bind(myFunction);             

route(path).run(args);

route(path).run(args);

/*    
  runs a route and executes any functions listening to that route
  path is a string which should be in a location.hash format.
  args is an object hash of arbitrary properties (see: Passing arguments to routes)
*/
   
 examples: 

	route('#/websites').run();
	route('#/account').run(); 
	route('/#account/marak.squires/edit').run();

 
            

jQuery by John Resig (aka God of JavaScript)

Sinatra jQuery implementation Sammy.js by Aaron Quint

NYC.js

This pre-made routing action will allow you to easily perform ajax routing with route.js
  
   The "options" param may be defined as the following:
	 "route":{
	   "VERB":"http verbs : GET,POST,PUT,DELETE",
	   "URI":"remote uri"
	   "DATA":"object",
	   "TEMPLATE":"template name",
	   "TARGETS":"jQuery selector",
	   "success":function(),
	   "error":function(),
	   "complete":function()	   
	  }
	
	/* DEFAULT ROUTING ACTION */
	var defaultRouteAction=function(options){
	  var onsuccess = options.success || defaultRouteSuccess;
	  var onerror = options.error || defaultRouteError;  
	  var oncomplete = options.complete || defaultRouteComplete;  
	  $.ajax({
		type: options.VERB,
		url: options.URI,
		data: options.data,
		success: function(response){onsuccess(response,options)}
	  });
	};