Minimal JavaScript routing microframework connecting paths to functions.
Web apps frequently need to initialize client-side JavaScript on a per-page
basis. Initializing stuff with inline JavaScript works for small
applications, but when they grow larger it does not scale: there is no single
place responsible for setting up the state. Cartograph
comes to the rescue,
providing a simple and barebone routing logic matching URL paths to
JavaScript functions, so you can run code depending on the current URL. It
has a clean and readable DSL with support for named URL parameters and
splats. All in a microscopic framework of ~2Kb of minified code.
var Router = new Cartograph(function() {
// Connect route to a function:
this.map("/foo/:id", function( req ) {
// `req` is an object containing the params
// and other information on the request
console.log( "Requested id is: " + req.params["id"] );
});
// Namespaced routes:
this.namespace("/users", function() {
// Say we have a controller object:
var users = UsersController;
this.map( "/", users.index );
this.map( "/new", users.new );
this.map( "/:id", users.show );
});
});
// Unleash the magic! (will get window.location
// and execute the first matching route)
Router.routeRequest();
And with CoffeeScript it's even more fun:
Router = new Cartograph ->
@map "/foo/:id", ( req ) ->
console.log "Requested id is #{req.params['id']}"
@namespace "/users", ->
users = UsersController
@map "/", users.index
@map "/new", users.new
@map "/:id", users.show
# Unleash the magic!
Router.routeRequest()
When called with a function fn
, the constructor evaluates it in the scope of
the newly created instance, providing a closure for route definitions.
Adds a mapping for route
to function fn
. Whenever route
or
routeRequest
is called, mappings are checked in order until the first
matching route is found. The callback function for that route is then
executed, passing as the first argument a request object.
Routes are strings, and can contain named params (e.g. "/foo/:id"
) and
named splats (e.g. "/foo/*bar/baz"
). The request object passed to fn
exposes a params
key/value object property containing params and splats.
Trailing slash is considered optional, so "/foo/bar"
and "/foo/bar/"
are
considered identical.
Provides a namespace block. Whithin function fn
, all routes defined by
calling map
are prefixed with the namespace ns
.
Gets a path
string and match it against each route in order until a match
is found. If a matching route is found, it executes its callback function
passing an object containing information about the request and the params. If
a mixin
object is provided, its properties are mixed in the request object
(so that additional request info or params can be inserted).
Similar to route
, but it takes as argument a request object exposing at
least a pathname
property. If no argument is provided, window.location
is
taken (this is the only case in which Cartograph
makes a soft assumption of
being in the browser).
When building the object to be passed to the matched callback, it also mixes
in it all the request properties and all the params parsed from the
querystring (looked for in request.search
), so that they become available to
the callback. Array params (e.g. foo[]=a&foo[]=b
) and nested params (e.g.
foo[bar][baz]=qux
) are supported (so
/mypath?foo[]=xxx&foo[]=yyy&bar[baz]=zzz
will be parsed to params { foo: ["xxx", "yyy"], bar: { baz: "zzz" } }
).
Like the constructor, it executes function fn
in the scope of the
Cartograph
instance. It is useful for adding routes on an existing
Cartograph
instance (e.g. if you want to split route definitions in multiple
files).
Contributes are very welcome! If you have an idea about how to make
Cartograph
better, you should:
-
Fork the project and setup the environment with
npm install
-
Write your new features/fixes and relative tests in CoffeeScript. The test suite uses BusterJS, and can be run with
npm test
after starting the Buster server. -
Send a pull request (please do not change the version in
package.json
)