﻿<img src="https://github.com/michaelherndon/ux-routing/blob/master/logo.png?raw=true" title="ux-util" />

<img src="https://travis-ci.org/michaelherndon/ux-routing.png" title="Build Status" />

# ux-routing
version: 0.10.0-alpha1

Extensible url routing engine that isn't tied to the browser and can support Asp.Net's and Rail's style of url pattern matching. 

The rails style pattern matching is available if you use
require("ux-routing/rails-routing-parser").RouteCollection

## Contents
* [Key Requirements](#key-requirements)
* [Rationale](#rationale)
* [Builds](#builds)
  * [Browser Distribution](#browser-distribution)
  * [CommonJS Distribution](#commonjs-distribution)
  * [AMD Distribution](#amd-distribution)
* [Api](#api)
  * [RouteCollection](#routecollection)
    * [constructor](#routecollection-constructor)
  	* [count](#routecollection-count)
  	* [items](#routecollection-items)
  	* [add( String name, Route route )](#routecollection-add)
  	* [clear()](#routecollection-clear)
  	* [dispose()](#routecollection-dispose)
  	* [getVirtualPath( String url) ](#routecollection-getvirtualpath)
  	* [mapRoute( String name, String url, [Object defaults], [Object constraints], [Function handler] )](#routecollection-maproute)
  	* [match( String url )](#routecollection-match)
  	* [remove( String|Route nameOrRoute )](#routecollection-remove)
  * [Route](#route)
    * [extend(prototype)](#route-extend)
    * [constructor( String url, [Object defaults], [Object constraints], [Function handler] )](#route-constructor)
    * [constraints](#route-constraints)
    * [defaults](#route-defaults)
    * [url](#route-url)
    * [handler](#route-handler)
    * [name](#route-name)
    * [getVirtualPath( String url )](#route-getvirtualpath)
    * [match( String url )](#route-match)
    * [_getParser](#route-_getparser)
* [License](#license)

## Key Requirements
* Routing is not tied to the UI, user interface. 
* Routing works for multiple packages: browser, amd, commonjs
* The core code is flexible enough to handle mutiple styles of pattern matching. 

## Rationale
Most of the current JavaScript routers seemed to do too much or too little and they often required heavy dependencies for events.  "ux-routing" is meant to be easily extendable and not to be tied to any environment. It can be used in node, the browser, or other JavaScript environments that support ecmascript 5. Its designed after the Router in Asp.Net which is meant to be flexible.  


## Builds

The builds for commonjs, browser, and amd will let you include files as needed. The build process creates 3 versions of the scripts, one for [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1), one for [AMD](http://requirejs.org/docs/whyamd.html), and one with closures for the browser.  

The source files are included with the npm module inside the src folder. This is so that developers and script consumers may cheery pick the functionality he/she wants and include the files as neede for custom builds.   

To build and test everything use:

```bash
$ grunt ci
```

There are multiple versions of ux-routing. Using net-router,js or rails-router.js will require using the dependencies from ux-util and ux-lexer.  Using net-router-all.js or rails-router-all.js will require zero dependencies from external libraries.  

The net-router is the .NET style of pattern matching for routes.  The rails-router is the Rails style of pattern matching for routing.  

In the future it should be easy to mix and match both.   

[back to top](#contents) 



### Browser Distribution

location: dist/browser

The browser distribution will use closures to wrap functionality and it uses the global variable of "ux.Routing" If you wish to use a method you can do the following:

```html
    <script type="/scripts/ux-routing/net-router-all.js"> </script>
```

```js
    var RouteCollection = self.ux.Routing.RouteCollection,
        routes = RouteCollection.routes;

    routes.mapRoute(
		"default",
		"{controller}/{action}/{id}",
		{controller: "Home", action: "Index", id: null},
		{id: function(value) {
			if(value == null);
				return null;
			return /\d/.test(value);
			}}
		));

	var meta = routes.getVirtualPath("posts/title");

	console.log(meta.url);
	console.log(meta.data);
	console.log(meta.route);
```
[back to top](#contents)

### AMD Distribution

location: dist/amd[/lib]

The amd distribution has the main file in the root and the rest of the files are pushed into the lib folder. This is so that the same require statements will work within node and when using something like require js in a browser environment. 

### CommonJS Distribution

location: lib

The files are located inside of the lib folder.  The default package is lib/net-router.js

[back to top](#contents)


## API

### <a name="routecollection"></a>RouteCollection

Route Collection is a store of routing patterns that are used to find a match from an incoming url and provide meta information about the url. The meta information can be used to decided what the url maps or "routes" to. 

#### <a name="routecollection-constructor"></a>constructor()

creates a new instance of the RouteCollection.

[back to top](#contents)
<br /><br />

#### <a name="routecollection-items"></a>items

The array of routes.

[back to top](#contents)
<br /><br />

#### <a name="routecollection-items"></a>count

The number of routes in the collections.

[back to top](#contents)
<br /><br />


#### <a name="routecollection-add"></a>add(String name, Route route)

Adds a route to the collection. This is the method that should be used by mixin methods to extend the Route Collection with mapping methods similar to [mapRoute](#routecollection-mapRoute).

##### <a name="routecollection-add-example"></a>example
```js
    var RouteCollection = require("ux-routing/lib/net-router").RouteCollection;
    var routes = new RouteCollection();

    routes.add(null, 
    	new Route(
			"{controller}/{action}", 
    		{controller: "home", action: "index"}
    	)
    );
```


[back to top](#contents)
<br /><br />

#### <a name="routecollection-dispose"></a>dispose()

Clears the routes in the collection and deletes properties defined by the constructor. 

##### <a name="routecollection-dispose-example"></a>example
```js
    var RouteCollection = require("ux-routing/lib/net-router").RouteCollection;
    var routes = new RouteCollection();

    console.log(routes.items);
    routes.dispose();
    console.log(routes.items);
```
[back to top](#contents)
<br /><br />



#### clear()

Clears all the routes in the collection.

##### <a name="routecollection-clear-example"></a>example
```js
    var RouteCollection = require("ux-routing/lib/net-router").RouteCollection;
    var routes = new RouteCollection();

    routes.mapRoute(null, "notes/edit/{id}");

    console.log(routes.count); // 1
    routes.clear();
    console.log(routes.count); // 0
```
[back to top](#contents)
<br /><br />



#### <a name="routecollection-getvirtualpath"></a>getVirtualPath(String url)

Alias of [match(url)][#routecollection-match].

[back to top](#contents)
<br /><br />


#### <a name="routecollection-maproute"></a>mapRoute( String name, String url, [Object defaults], [Object constraints], [Function handler] )

Adds a route to the collection.

##### <a name="routecollection-maproute-example"></a>example
```js
    var RouteCollection = require("ux-routing/lib/net-router").RouteCollection;
    var routes = new RouteCollection();

    routes.mapRoute(
    	"default",
		"{controller}/{action}/{id}",
		{controller: "Home", action: "Index", id: null},
		{id: function(value) {
			if(value == null);
				return null;
			return /\d/.test(value);
			}}
		));
    );
```


[back to top](#contents)
<br /><br />

#### <a name="routecollection-match"></a>match(String url)

Gets the meta data from the first route that has a pattern that matches the given url. Returns null if a match could not be found. 

It returns an object with the the following properties:

* url - the resolved url after the matching route reassembles it. 
* data - the data of key / value pairs that were extracted from url by the matching route.
* route - the route object that matched.

##### <a name="routecollection-match-example"></a>example
```js
    var RouteCollection = require("ux-routing/lib/net-router").RouteCollection;
    var routes = new RouteCollection();

    routes.mapRoute(null, "notes/edit/{id}");

    var routeData = routes.match("notes/edit/1");
    console.log(routeData);
```
[back to top](#contents)
<br /><br />


#### <a name="routecollection-remove"></a>remove(String|Route nameOrRoute)

Removes the route from the collection by name or instance of the route. Returns the number items removed from the collection.

##### <a name="routecollection-remove-example"></a>example
```js
    var RouteCollection = require("ux-routing/lib/net-router").RouteCollection;
    var routes = new RouteCollection();

    routes.mapRoute(null, "notes/edit/{id}");

    routes.remove(null);
```

[back to top](#contents)
<br /><br />

### <a name="Route"></a>Route

An available path that can be used to determine what action a program should take when a url matches a specific path. 

#### <a name="route-extend"></a>extend(Object prototype)

Extends the route class to create a new subclass. 

[back to top](#contents)
<br /><br />

#### <a name="route-constructor"></a>constructor( String url, [Object defaults], [Object constraints], [Function handler] )

Creates a new instance of Route.  
* url - the url pattern that the route will match on.
* defaults - the default values that match tokens in the url pattern.
* constraints - the required rules that a token value has to match on to be valid.
* handler - the function that should be called when a route matches.  

[back to top](#contents)
<br /><br />

#### <a name="route-constraints"></a>constraints

Gets or sets the key value pairs of constraints that will be used to determine if a value is a valid match.  A constraint value can either be a RegExp or Function.  The key will be name of the token.

##### <a name="route-constraints-example"></a>example
```js
	var route = new Route(
		"{controller}/{action}/{id}", 
		null, 
		{
			id: function(value) {
				if(value === null)
					return true;

				return utility.isInteger(value);
			}
		}
	});
```
[back to top](#contents)
<br /><br />


#### <a name="route-defaults"></a>defaults

Gets or sets the default values for tokens that are optional.  Once a default value is given, the token becomes optional. 

[back to top](#contents)
<br /><br />



#### <a name="route-url"></a>url

Gets or sets the url pattern that the route should match on. 

##### .net style
```js
  var pattern = "{controller}/{action}/{id}";
```

##### rails style
```js
	var pattern = ":controller(/:action(/:id))"
```
[back to top](#contents)
<br /><br />


#### <a name="route-handler"></a>handler

Gets or sets the function handler that should be used to handle route. This is not automatically invoked.

[back to top](#contents)
<br /><br />

#### <a name="route-name"></a>name

Gets or sets the name of the route. 

[back to top](#contents)
<br /><br />


#### <a name="route-getvirtualpath"></a>getVirtualPath( String url )

Alias of [match](#route-match)

[back to top](#contents)
<br /><br />


#### <a name="route-match"></a>match( String url )

Determines if a url is a match for the route.  If the it is a match it returns url [meta data](#routecollection-match) otherwise it returns null.

Override this method in order to determine how routes match a url. The net-router.js and rails-router.js override the _getParser method, which is expected by the match method in order to match the url. 

[back to top](#contents)
<br /><br />

#### <a name="route-_getparser"></a>_getParser()

Returns the parser for the route. The parser is used to determine if the url is a match for the route and to extract values for tokens.  

[back to top](#contents)
<br /><br />


## License

For extends, isPlainObject, isWindow: Copyright 2014 jQuery Foundation and other contributors
http://jquery.com/

The MIT License (MIT)

Copyright (c) 2013-2014 Michael Herndon http://dev.michaelherndon.com

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.