• Stars
    star
    111
  • Rank 308,244 (Top 7 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 12 years ago
  • Updated over 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Better route management for Backbone.js projects.

backbone.routemanager

Created by Tim Branyen @tbranyen

Provides missing features to the Backbone.Router.

Depends on Underscore, Backbone and jQuery. You can swap out the jQuery dependency completely with a custom configuration.

Tutorials and Screencasts

Download & Include

Development is fully commented source, Production is minified and stripped of all comments except for license/credits.

Include in your application after jQuery, Underscore, and Backbone have been included.

<script src="/js/jquery.js"></script>
<script src="/js/underscore.js"></script>
<script src="/js/backbone.js"></script>

<script src="/js/backbone.routemanager.js"></script>

Usage

Defining a RouteManager

A route manager is your App Router, you will be able to define any number of Nested Routers.

Assuming you have an app namespace

// A basic route manager, works just like a Backbone.Router (cause it is one)
var AppRouter = Backbone.RouteManager.extend({
  routes: {
    "": "index"
  },

  index: function() {
    window.alert("Navigated successfully");
  }
});

// Create a new instance of the app router
app.router = new AppRouter();

// Trigger the index route
app.router.navigate("", true);

Alternative method of defining a RouteManager

If you don't wish to extend the Backbone.RouteManager you can simply make a new instance of the constructor and assign that to save yourself a step.

// A basic route manager, works just like a Backbone.Router (cause it is one)
app.router = new Backbone.RouteManager({
  routes: {
    "": "index"
  },

  index: function() {
    window.alert("Navigated successfully");
  }
});

// Trigger the index route
app.router.navigate("", true);

Named params object

All route callbacks get access to a special object on the Router called params which maps directly to the variables and splats defined in the route.

// A basic route manager, works just like a Backbone.Router (cause it is one)
var AppRouter = new Backbone.RouteManager({
  routes: {
    ":id/*path": "index"
  },

  index: function(id, path) {
    // You can use the arbitrarily named args you define... or you can use the
    // params object on the router.
    window.alert(id == this.params.id);
    window.alert(path == this.params.path);
  }
});

// Create a new instance of the app router
app.router = new AppRouter();

// Trigger the index route
app.router.navigate("5/hi", true);

This is useful for a number of reasons including a special significance for before/after filters that are defined later on.

Nested Routers

So far we haven't seen anything special that we couldn't do already with a normal Backbone.Router. One of the major benefits of RouteManager is that you can define nested Routers. These are defined in the same way as normal routes, except you pass a Backbone.Router class instead.

Nested Routers are just normal Backbone.Router's.

For example:

var SubRouter = Backbone.Router.extend({
  routes: {
    "": "index",
    "test": "test"
  },

  index: function() {
    window.alert("SubRouter navigated successfully");
  },

  test: function() {
    window.alert("sub/test triggered correctly");
  }
});

var AppRouter = Backbone.RouteManager.extend({
  routes: {
    // Define a root level route
    "": "index",

    // Define a sub route
    "sub/": SubRouter
  },

  index: function() {
    window.alert("MasterRouter navigated successfully");
  }
});

// Create a new instance of the app router
app.router = new AppRouter();

// Trigger the test route under sub
app.router.navigate("sub/test", true);

Before/After filters

The real meat of RouteManager, besides the nested Routers, is the ability to define functions to be run before and after a route has fired. This has huge benefits for keeping your Router DRY and flexible.

To define a before and after filter, simply create respectively named objects on your Router along with a key/val set matching routes and callbacks.

The this context inside the filter functions is different from the route callback. this is a special object that can put the function in async/defer mode (which is discussed later). It has a reference to the router that can be accessed with this.router if you wish to store properties or access it.

Backbone.Router.extend({
  before: {
    "": ["auth", "layout"]
  },

  after: {
    "": ["render"]
  }

  routes: {
    "": "index"
  },

  // Before callbacks
  auth: function() {}
  layout: function() {}

  // Route callbacks
  index: function() {}

  // After callbacks
  render: function() {}
});

Params => arguments mapping

Your filter functions may need to be callable from outside of the RouteManager filter environment. Therefore no automatic mapping is possible, but there is a very simple boolean logic assignment that you can make that ensures your functions are correctly callable.

Backbone.Router.extend({
  before: {
    "user/:id": ["getUser"]
  },

  routes: {
    "": "index"
  },

  // Before callbacks
  getUser: function(id) {
    id = id || this.params.id;

    // id maps to this.params.id or whatever value is passed in
    console.log(id);
  }

  // Route callbacks
  index: function() {}
});

Because of this check you can now do something like this:

// Since you are calling this function on its own, the id will be mapped to
// whatever value you'd like, without needing `this.params`.
router.getUser(5);

There are three different types of functions that can be put inside the filters array: Synchronous, Asynchronous, and Promise/Deferreds. These can be mixed and matched together to create a logical and performant flow to your route.

Filters run sequentially and will always block the next function until they are complete. This means if you have ["a","b","c"] as your array of callbacks, a will have to complete before b is executed. The only exception to this is when a Promise/Deferred is encountered and added to the list to resolve.

If you wish to stop the chain at any point (subsequently stopping the route callback from triggering as well), you can do this in a number of ways depending on the type of filter. Each way is discussed in the respective section.

Synchronous filters

These are the most basic filter and require nothing special to use. Just create normal functions that should be executed before a route.

Backbone.Router.extend({
  before: {
    "": ["sync"]
  },

  sync: function() {
    console.log("this runs before index");
  },

  routes: {
    "": "index"
  }
});

To signify an error in your synchronous function to cause remaining functions to not be called, simply return false in your function.

  sync: function() {
    console.log("not going to run any more filter functions");

    return false;
  },

Asynchronous filters

When your code is affected by a non-blocking call (think XHR, setTimeout, etc), the above synchronous definition cannot work, as there would be no way to tell RouteManager when the function is done.

To put the function into asynchronous mode simply assign a done callback with var done = this.async() and call done() when you are finished in the function.

Backbone.Router.extend({
  before: {
    "": ["sync", "async"]
  },

  ...,

  async: function() {
    var done = this.async();

    window.setTimeout(function() {
      console.log("this runs after sync and before index");

      // Progress to the next 
      done();
    }, 1000);
  },

  routes: {
    "": "index"
  }
});

To signify an error in your asynchronous function to cause remaining functions to not be called, simply call done with false.

  async: function() {
    var done = this.async();

    window.setTimeout(function() {
      console.log("this runs after sync and never calls index");

      // Do not progress to the next
      done(false);
    }, 1000);
  },

Deferred/Promise filters

There may be times that you will work with asynchronous code that can be run in parallel. The deferred filter mode was designed for this use case.
When RouteManager encounters a deferred filter it puts it into a bucket and continues on to the next function, it will continue grouping all deferreds until it hits a non-deferred in which it will wait till they resolve and then execute.

To put a filter function into the deferred mode, simply assign this.defer to a variable and call resolve or reject when its finished.

Backbone.Router.extend({
  before: {
    "": ["sync", "async", "defer"]
  },

  ...,

  defer: function() {
    var deferred = this.defer();

    window.setTimeout(function() {
      console.log("this runs after sync, async, and before index");

      // Progress to the next 
      deferred.resolve();
    }, 1000);
  },

  routes: {
    "": "index"
  }
});

It may be useful to leverage an existing deferred instead of creating a new one. This is particularly useful when calling fetch on models and collections. Simply pass the deferred to defer and it will be used internally.

defer: function() {
  this.defer(collection.fetch());
}

To signify an error in your deferred function to cause remaining functions to not be called, simply call reject on the deferred.

  defer: function() {
    var deferred = this.defer();

    window.setTimeout(function() {
      console.log("this runs after sync, async, and stops index");

      // Do not progress to the next 
      deferred.reject();
    }, 1000);
  },

Configuration

Overriding RouteManager options has been designed to work just like Backbone.sync. You can override at a global level using RouteManager.configure or you can specify when instantiating a RouteManager instance.

Global level

Lets say you wanted to use underscore.deferred for the Promise lib instead of jQuery.

// Override all RouteManagers to use underscore.deferred
Backbone.RouteManager.configure({
  deferred: function() {
    return new _.Deferred();
  },

  when: function(promises) {
    return _.when.apply(null, promises);
  }
});

Instance level

In this specific router, use underscore.deferred for the Promise lib instead of jQuery.

app.router = new Backbone.RouteManager({
  routes: {
    "": "index"
  },

  options: {
    deferred: function() {
      return new _.Deferred();
    },

    when: function(promises) {
      return _.when.apply(null, promises);
    }
  }
});

Defaults

  • Deferred: Uses jQuery deferreds for internal operation, this may be overridden to use a different Promises/A compliant deferred.
deferred: function() {
  return $.Deferred();
}
  • When: This function will trigger callbacks based on the success/failure of one or more deferred objects.
when: function(promises) {
  return $.when.apply(null, promises);
}

Release History

More Repositories

1

backbone-boilerplate

A workflow for building Backbone applications.
JavaScript
4,496
star
2

backbone.layoutmanager

UNMAINTAINED 7/31/18: A layout and template manager for Backbone applications.
JavaScript
1,682
star
3

diffhtml

diffHTML is a web framework that helps you build applications and other interactive content
JavaScript
868
star
4

hyperlist

A performant virtual scrolling list utility capable of rendering millions of rows
JavaScript
407
star
5

github-viewer

GitHub Viewer.
JavaScript
370
star
6

use-amd

An AMD plugin for consuming globally defined JavaScript.
JavaScript
271
star
7

combyne

A template engine that works the way you expect.
JavaScript
144
star
8

salita

Automatically upgrade all NPM dependencies.
JavaScript
95
star
9

babel-plugin-transform-commonjs

A Babel 7 plugin transform to convert CommonJS into ES Modules
JavaScript
82
star
10

lodash-template-loader

A Lo-Dash template loader plugin for AMD projects.
JavaScript
54
star
11

backbone.cacheit

Fetch caching made super simple in Backbone.
JavaScript
47
star
12

vertebrae

Backbone transport management.
JavaScript
43
star
13

previewcode

previewcode.com public repository.
JavaScript
32
star
14

nodewii

Node.js cwiid asynchronous native bindings
C++
31
star
15

growing-up-with-backbone

Growing Up With Backbone.
JavaScript
28
star
16

localhub

A local hub of your Git repositories
JavaScript
15
star
17

redux-create-action-types

Easily create immutable, strict, and well formed action types
JavaScript
15
star
18

diffhtml-prollyfill

DEPRECATED MOVED TO MAIN REPO
14
star
19

scopedcss

Scoping your CSS to a specific selector or element.
JavaScript
14
star
20

nodefreckle

Node.js freckle api bindings
JavaScript
13
star
21

pigeonpost

Amazon SES E-Mail Scheduler & Delivery API
JavaScript
11
star
22

vim-typescript

VIM TypeScript Plugin
JavaScript
10
star
23

site-content

All site content.
JavaScript
10
star
24

hooks-theme-refs

A simple pattern for well structured React Components
JavaScript
10
star
25

todomvc

TodoMVC implemented with VDOM, Tagged templates, and Redux
JavaScript
8
star
26

talks

My Talks
JavaScript
8
star
27

diffhtml-inline-transitions

Inline transition hooks directly into tagged templates
JavaScript
7
star
28

miso.fs

A Miso Dataset FileSystem Importer.
JavaScript
7
star
29

cat-api-boilerplate

A starting point for creating your very own cat API.
JavaScript
7
star
30

react-babel-esm

Using React and Hooks without a bundler, from npm, and with native browser ESM
JavaScript
6
star
31

react-hyperlist

A React wrapper for HyperList
JavaScript
6
star
32

redux-simple-routing

Simple routing for React/Redux apps
JavaScript
5
star
33

babel-plugin-resolve-imports-for-browser

A Babel plugin to convert imports to support browser ESM
JavaScript
5
star
34

bserve

Static HTTP server which automatically transpiles JS using Babel
JavaScript
4
star
35

app.toweatherproof.me

Basic Weather App.
JavaScript
4
star
36

parallel-run

Run npm scripts multiplexed
JavaScript
4
star
37

babel-preset-browser-esm

Babel preset to make running JavaScript in the browser easier
TypeScript
4
star
38

lm-forms

Backbone LayoutManager and Backbone Forms integration
JavaScript
4
star
39

devoxx-2013

Backbone and Tools
JavaScript
4
star
40

chart-component

An experimental Web Component that renders a chart, using diffHTML
JavaScript
4
star
41

babel-ast-cache-perf-tests

Benchmarks various ways of getting a Babel AST
JavaScript
3
star
42

tbranyen.com

My personal site.
JavaScript
3
star
43

grunt-nodequnit

Run QUnit tests in the Node.js environment.
JavaScript
3
star
44

transform-tagged-diffhtml

A Babel plugin transform for diffHTML tagged template strings
JavaScript
3
star
45

diffhtml-synthetic-events

Swaps out inline events for synthetic event delegation.
JavaScript
3
star
46

synchronizer

Build AMD projects into a single UMD file.
JavaScript
3
star
47

combyne-amd-loader

A Combyne template loader plugin for AMD projects.
JavaScript
3
star
48

consumare

Consume content from Git.
JavaScript
3
star
49

combynexpress

Combyne view engine for Express.
JavaScript
3
star
50

extless-loader

Loads Node ESM in a more compatible way by making extensions optional.
JavaScript
3
star
51

d3-playground

D3 playground with webpack hot reloading & babel for prototyping
JavaScript
3
star
52

cropcircle

Pattern framework for building web sites and applications
HTML
2
star
53

quick-dom-node

Make DOM Nodes in Node quickly and they are also quick
JavaScript
2
star
54

make8bitart

an in-browser canvas tool which is great fun!
JavaScript
2
star
55

diffhtml-logger

DEPRECATED MOVED TO MAIN REPO
2
star
56

diffhtml-snowpack

Extremely simple demo using diffHTML and Snowpack
JavaScript
2
star
57

amd.js

Experimental AMD loader
JavaScript
2
star
58

static-sync

A static server that automatically keeps HTML files in sync using Virtual DOM.
JavaScript
2
star
59

awesome-config

My minimalistic Awesome WM configuration.
Lua
2
star
60

LiveEdit-CSS

JavaScript
2
star
61

amd-test-bed

A project test bed
JavaScript
2
star
62

turbopack-webpack-example

Example of turbopack integration with webpack
JavaScript
1
star
63

amd-next

If we were to have a v2 of the AMD specification what would it look like?
1
star
64

Charcoal_UI_v1.1

MIRROR of Charcoal UI 1.1
Lua
1
star
65

calendar.js

A long lost project
JavaScript
1
star
66

cribbage

Follow me as I get incrementally updated from College-standards to Modern-standards.
JavaScript
1
star
67

load-as-fake-workers

Loads scripts as fake workers for testing
JavaScript
1
star
68

ayo-node-esm-tests

Testing Node vs Ayo ES Modules
JavaScript
1
star
69

broken-npm-resolution

Works with updates to react-blessed-you (fork for react-blessed)
JavaScript
1
star
70

diffhtml-esm-test-app

Zero build test of diffHTML, Redux, and a simple event emitter
JavaScript
1
star
71

css-loader

CSS Loader.
JavaScript
1
star