Skip to content

Instantly share code, notes, and snippets.

@jkresner
Last active December 17, 2015 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkresner/5601305 to your computer and use it in GitHub Desktop.
Save jkresner/5601305 to your computer and use it in GitHub Desktop.
"""
BadassRouter takes the philosophical position that only one router can be
used for one html page / single page app. It is conceptually the top most
container object other than window that contains all instances associated with the app.
"""
module.exports = class BadassRouter extends Backbone.Router
# Set logging on /off - Very dandy during dev to see flow of routes
logging: off
# Set off if you don't want pushSate - great during testing!
pushState: on
# Almost always a good idea to override pushStateRoot in child router
pushStateRoot: '/'
# Good to turn off during testing & admin pages
enableExternalProviders: on
# takes pageData to pre-load data into the SPA without ajax calls
constructor: (pageData, callback) ->
@pageData = pageData if pageData?
@app = @appConstructor pageData, callback
if @logging
history = "pushState: #{@pushState}, root: #{@pushStateRoot}"
$log 'BadassRouter.ctor', history, @pageData, callback
@initialize = _.wrap @initialize, (fn, args) =>
Backbone.history.start pushState: @pushState, root: @pushStateRoot
$log("Router.init", args, @app) if @logging
fn.call @, args
# wire up our 3rd party provider scripts to load only after our app
# had been initialized and constructed so our stuff loads before 3rd party junk
if @enableExternalProviders
@loadExternalProviders()
@wrapRoutes()
# Call backbone to correctly wire up & call Router.initialize on child router
Backbone.Router::constructor.apply @, arguments
# construct all instances of models, collection & views for page
appConstructor: (pageData, callback) ->
throw new Error 'override appConstructor in child router & build all models, collections & views then return single objects'
# automatically wrap route handlers
# adding div hide/show + console logging (if enabled)
wrapRoutes: ->
for route of @routes
# routes may contain /:id etc. - we only use
# the first fragment to map to the fn name
routeName = route.replace(/:id/g,'').split('/')[0]
if routeName != ''
# default function allows us to be lazy in child routers
@[routeName] = (->) if !@[routeName]?
@[routeName].routeName = routeName
@[routeName] = _.wrap @[routeName], (fn, args) =>
$log("Router.#{fn.routeName}") if @logging
$(".route").hide()
$("##{fn.routeName}").show()
@routeMiddleware()
fn.call @, args
# override routeMiddleware to execute custom code on every route
routeMiddleware: ->
# load external providers like google analytics, user-voice etc.
loadExternalProviders: ->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment