(function(Backbone, _) {

  var extend = Backbone.Router.extend;

  Backbone.Router.extend = function() {
    var child = extend.apply(this, arguments),
        childProto = child.prototype,
        parentProto = this.prototype;

    _.each(['before', 'after'], function(filter) {
      _.defaults(childProto[filter], parentProto[filter]);
    });

    return child;
  };

  _.extend(Backbone.Router.prototype, {

    /**
     * Override default route fn to call before/after filters
     *
     * @param {String} route
     * @param {String} name
     * @param {Function} [callback]
     * @return {*}
     */
    route: function(route, name, callback) {
      if (!_.isRegExp(route)) route = this._routeToRegExp(route);

      if (_.isFunction(name)) {
        callback = name;
        name = '';
      }

      if (!callback) callback = this[name];
      var router = this;

      Backbone.history.route(route, function(fragment) {
        var args = router._extractParameters(route, fragment);

        runFilters(router, router.before, fragment, args, function() {
          if (callback) {
            callback.apply(router, args);
          }

          router.trigger.apply(router, ['route:' + name].concat(args));
          router.trigger('route', name, args);
          Backbone.history.trigger('route', router, name, args);

          runFilters(router, router.after, fragment, args, function() { });
        });
      });

      return this;
    }
  });

  /**
   * Running all filters that matches current fragment
   *
   * @param router {Router} router instance reference
   * @param filters {Object} all available filters
   * @param fragment {String} current fragment
   * @param args {Array} fragment arguments
   * @param callback {Function}
   */
  function runFilters(router, filters, fragment, args, callback) {
    var chain = _.filter(filters, function(callback, filter) {
      filter = _.isRegExp(filter) ? filter : router._routeToRegExp(filter);
      return filter.test(fragment);
    });

    run(chain, router, fragment, args, callback);
  }

  /**
   * Recursive function to run through filters chain supporting both async calls via `next` or regular
   * return-value based chain
   *
   * @param chain {Array} filter calls chain
   * @param router {Router} router instance reference
   * @param fragment {String} current fragment
   * @param args {Array} fragment arguments
   * @param callback {Function}
   */
  function run(chain, router, fragment, args, callback) {

    // When filters chain is finished - calling `done` callback
    if (!chain.length) {
      callback.call(router);
      return;
    }

    var current = chain[0],
        tail = _.tail(chain),
        next = function() {
          run(tail, router, fragment, args, callback);
        };

    if (_.isString(current)) {
      current = router[current];
    }

    if (current.length === 3) {
      // Filter expects `next` for async - ignoring return value
      // and waiting for `next` to be called
      current.apply(router, [fragment, args, next]);
    } else {
      // Using regular filter with `false` return value that stops
      // filters execution
      if (current.apply(router, [fragment, args]) !== false) {
        next();
      }
    }
  }

})(Backbone, _);

@@ -1,8 +1,431 @@
+/**%0A * Backbone.Route filter%0A *%0A * Adds support for sync/async Backbone routes filters%0A *%0A * @author Maksim Horbachevsky%0A */%0A%0A(function(factory) %7B%0A  if (typeof define === 'function' && define.amd) %7B%0A    define(%5B'backbone', 'underscore'%5D, factory);%0A  %7D else if (typeof exports === 'object') %7B%0A    module.exports = factory(require('backbone'), require('underscore'));%0A  %7D else %7B%0A    factory(window.Backbone, window._);%0A  %7D%0A%7D)
 (functio
@@ -441,16 +441,16 @@
 e, _) %7B%0A
-
 %0A  var e
@@ -575,18 +575,16 @@
 ,%0A      
-  
 childPro
@@ -605,18 +605,16 @@
 totype,%0A
-  
       pa
@@ -1819,16 +1819,26 @@
 tion() %7B
+%0A         
  %7D);%0A   
@@ -3099,18 +3099,16 @@
 ,%0A      
-  
 tail = _
@@ -3121,18 +3121,16 @@
 chain),%0A
-  
       ne
@@ -3155,18 +3155,16 @@
         
-  
 run(tail
@@ -3200,18 +3200,16 @@
 lback);%0A
-  
       %7D;
@@ -3685,21 +3685,8 @@
  %7D%0A%0A
+
 %7D)
-(Backbone, _)
 ;%0A

Add AMD support, fix #8