JS軽量クライアントサイドルーティングライブラリいろいろ

JSの軽量クライアントサイドルーティングライブラリをなんとなくまとめました。

ここで述べるルーティングライブラリとは、文字列、または正規表現によって定義したパスに対してコールバックをマッピングできるライブラリを指します。また、ルーティング機能のみを提供するものを中心として紹介します。backbone.js等のフレームワークは省いています。

## kazitori.js
https://github.com/glassesfactory/kazitori.js

### Example
http://pstest.hageee.net/

```coffeescript:
    class Router extends Kazitori
        beforeAnytime:["testBefore"]
        befores:
            '/<int:id>':['testShow']
        routes :
            '/':'index'
            '/<int:id>':'show'
            '/<string:username>/<int:id>':'post'

        index:()->
            # console.log "index"
            $('.currentPage').empty().append "this page is index"

        show:(id)->
            # console.log id
            $('.currentPage').empty().append "this page is test" + id

        post:(username, id)->
            $('.currentPage').empty().append username + "post " + id

        ###
            some before handlers
        ###
        testBefore:()->
            console.log "before!"
        testShow:()->
            console.log "before show"


    $(document).ready ()->
        window.App = new Router({root:'/'})
```

パスの記法はpythonのフレームワークwerkzeugを参考にしていて、パラメータの型指定ができるようです

あとドキュメントが日本語です

bower、npm からのインストールに対応しています

## page.js
https://github.com/visionmedia/page.js
http://visionmedia.github.com/page.js/

```javascript:
	page('/', index)
	page('/user/:user', show)
	page('/user/:user/edit', edit)
	page('/user/:user/album', album)
	page('/user/:id', user.load, user.show)
	page('/user/:id/edit', user.load, user.edit)
	page('/user/:name/:operation', callback)
	page('/user/:name/:operation?', callback)
	page('/user/*', loadUser)	
	page('/file/:file(*)', loadUser)
	page(/^\/commits\/(\d+)\.\.(\d+)/, loadUser)
	page('*', notfound)
	page()
```

パスに対してコールバックを複数マッピングできるところが良い感じですね。サンプルコードのように、リソースの読み込みと表示を明確に分けることがで
きます。

```javascript:
	page(path, callback[, callback ...])
```

bowerからのインストールに対応しています

## Crossroads.js
https://github.com/millermedeiros/crossroads.js
http://millermedeiros.github.com/crossroads.js/

```javascript:
	// Basic usage
	crossroads.addRoute('/news/{id}', function(id){
	  console.log(id);
	});
	crossroads.parse('/news/123'); //will match '/news/{id}' route passing 123 as param

	// Optional parameters
	crossroads.addRoute('/news/{id}/:date:', function(id, date){
	  console.log(id +' - '+ date);
	});
	crossroads.parse('/news/123'); //match route and pass "123" as param
	crossroads.parse('/news/45/2011-09-31'); //match route passing "45" and "2011-09-31" as param

	// Rest segments
	// {section*} will match multiple segments
	crossroads.addRoute('/news/{section*}/{id}', function(section, id){
	  console.log(section +' - '+ id);
	});
	//match route and pass "lorem" and "123"
	crossroads.parse('/news/lorem/123');
	//match route passing "lorem/ipsum/dolor" and "45"
	crossroads.parse('/news/lorem/ipsum/dolor/45'); 

	// Decode Query String
	crossroads.addRoute('foo.php{?query}', function(query){
	  console.log(query.lorem +' - '+ query.dolor);
	});
	// match route passing {lorem:"ipsum", dolor:"amet"}
	crossroads.parse('foo.php?lorem=ipsum&dolor=amet');

	//capturing groups are passed as parameters to listeners
	crossroads.addRoute(/^news\/([0-9]+)$/, function(id){
  	console.log(id);
	});
	crossroads.parse('/news/123'); //will match route passing "123" as param
	crossroads.parse('/news/qwerty'); //won't match route
	crossroads
    	.addRoute('{section}', loadSection)
    	.rules = {
       		section : ['home', 'login', 'contact']
    	};
```

長いので続きは[こちら](https://github.com/millermedeiros/crossroads.js/wiki/Examples)をどうぞ
パラメータのバリデーションまでできるなど大変高機能なようですね

bowerからのインストールに対応しています

## Davis.js
https://github.com/olivernn/davis.js

### Example
http://davis-example.heroku.com/

```javascript:
	var app = Davis(function () {
	  this.get('/welcome/:name', function (req) {
	    $('body').append('<h1>Hello there, ' +  req.params['name'] + '!</h1>')
	  })
	})

	$(document).ready(function () {
	  // append a link to trigger the route
	  $('body').append('<a href="/welcome/bob">Greet</a>');
	
	  app.start();
	})
```

bowerからのインストールに対応しています

## PathJS
https://github.com/mtrpcic/pathjs
http://mtrpcic.github.com/pathjs/

### Example
http://mtrpcic.github.com/pathjs/hashtag_basic.html
http://mtrpcic.github.com/pathjs/html5_basic.html
http://mtrpcic.github.com/pathjs/advanced_routing.html

```javascript:
	function clearPanel(){
        // You can put some code in here to do fancy DOM transitions, such as fade-out or slide-in.
    }

    Path.map("#/users").to(function(){
        alert("Users!");
    });

    Path.map("#/comments").to(function(){
        alert("Comments!");
    }).enter(clearPanel);

    Path.map("#/posts").to(function(){
        alert("Posts!");
    }).enter(clearPanel);

    Path.root("#/posts");

    Path.listen();
```

## Grapnel.js
https://github.com/gregsabia/Grapnel.js

```javascript:
	var hook = new Grapnel(':');
	
	hook.add('show', function(value){
    	console.log('Showing: %s', this.value);
	});

	hook.on('match', function(value, action){
	    console.log('Grapnel.js works! (Hook: "%s", Action: "%s", Value: "%s")', this.hook, action, value);
	});
```

## Routie
https://github.com/jgallen23/routie
http://projects.jga.me/routie/

```javascript:
	// Here is the most basic way:
	routie('users', function() {
	    //this gets called when hash == #users
	});
	
	// If you want to define multiple routes you can pass in an object like this:
	routie({
	    'users': function() {
	
	    },
	    'about': function() {
	    }
	});

	// Routie also supports regex style routes, so you can do advanced routing like this:
	routie('users/:name', function(name) {
	    //name == 'bob';
	});

	// Optional Params
	routie('users/:name?', function(name) {
	    //name == undefined
	    //then
    	//name == bob
	});

	// Wildcard
	routie('users/*', function() {
	});
	
	// Catch All
	routie('*', function() {
	});

	// Named Routes
	routie('user users/:name', function() {});
```

Named Routesという機能はユニークですね

bowerからのインストールに対応しています

## RouterJs
https://github.com/haithembelhaj/RouterJs
http://haithembelhaj.github.com/RouterJs/

```javascript:
    //Instanciate the router
    var router = new Router();

    //Define some routes with their respective callback function
    router.route('/posts/:id', function(id){ console.log(id)});
    router.route('/route/*path', function(path){ console.log(path)});
    router.route('', function(){ console.log("default route")});

    /* 
    * Navigate to route
    * the navigate method takes two extra arguments trigger and replace
    * trigger is by default true and replace is by default false
    */

    router.navigate('/posts/22');
    router.navigate('/posts/23', false); //ommit calling the callback
    router.navigate('/route/to/heaven', true, false); //just replace without history traceback

    //Navigate throught the History
    router.go(2); //forward navigation
    router.go(-3); //backward navigation
```

navigateというメソッドに、コールバックを呼ばないオプションがありますね。どんなシーンで使うのでしょう。わたし気になります。


## まとめ
フレームワークのルータにインスパイアされて出来たものが多いようですね。

 |pushState|依存ライブラリ|パッケージマネージャ|ライセンス
---|---|---|---|---|---|---|---|---|---
page.js|◯||bower|MIT
Davis.js|◯|jQuery 1.4.2+|bower|MIT
PathJS|◯||bower|MIT
Grapnel.js|◯|||MIT
Routie|||bower|MIT
RouterJs|◯|History.js||MIT
Crossroads.js||JS-Signals|npm|MIT
kazitori.js|◯||npm bower|MIT|