user375566
user375566

Reputation:

Advanced routing and single object definition?

I'm trying to simplify routes. What I have now still requires a reference inside the class that extends router, but since I'm using eval to instantiate references, every route method is the same.

Currently, inside my app:

ROUTES =
  'action1/:page': 'action1'
  'action2/:page': 'action2'
  '*path': 'default' # Default routes to action1

# Start Backbone history.
App.Router = new Routes(
  routes: ROUTES
)
App.Router.setDefaultRoute 'action1'
Backbone.history.start()

And the Router class:

class window.Routes extends Backbone.Marionette.AppRouter

  constructor: (options) ->

    @on 'all', @storeRoute
    @history = []
    super options

  @trace initialize: () ->

    debug.info 'Routes: ' + JSON.stringify @routes

  @trace setDefaultRoute: (route) ->

    App.Data.defaultRoute = route

  @trace getDefaultRoute: () ->

    App.Data.defaultRoute

  @trace storeRoute: () ->

    @history.push Backbone.history.fragment

  @trace getPrevious: () ->

    if @history.length > 1
      @history[@history.length - 1] 

  @trace getPreviousRoute: () ->

    @getPrevious().split('/')[0]

  @trace getPreviousPage: () ->

    @getPrevious().split('/')[1]

  @trace getFormattedWindowHash: () ->

    hash = window.location.hash
    hash = hash.substring(1, hash.length) 

    hash

  @trace getCurrentRoute: () ->

    current = @getFormattedWindowHash().split('/')[0]

    # Allow us to not specify 'route = <route>' inside every routing method.
    if !current
      current = @getDefaultRoute()
    else
      current = current

    current = current.charAt(0).toUpperCase() + current.slice(1)    

  @trace getCurrentPage: () ->

    @getFormattedWindowHash().split('/')[1]

  # Everytime a page is loaded, default data is cleared by instantiating new 
  # Views, Events, UI, State, and Error classes.
  @trace setupPage: (page) ->

    route = @getCurrentRoute()

    debug.info 'current route: ' + route

    event = 'App.Pages.Events.' + route + ' = new App.Events.' + route + '()'
    debug.info 'eval event: ' + event

    eval event

    # The magic which routes to the page.
    goTo = 'App.Pages.Events.' + route + '.router(parseInt(' + page + '))'
    debug.info 'goTo: ' + goTo

    eval goTo

  # Place routing actions below.

  @trace action1: (page) ->

    @setupPage page

  @trace action2: (page) ->

    @setupPage page

  # Default route.
  @trace default: () ->

    # TODO make this settable?
    @action1 1

What I want to do is be able to remove these 3 methods:

 @trace action1: (page) ->

    @setupPage page

  @trace action2: (page) ->

    @setupPage page

  # Default route.
  @trace default: () ->

    # TODO make this settable?
    @action1 1

How can I accomplish this?

Running: http://franklovecchio-playback.herokuapp.com/?log=true

Full code: https://github.com/franklovecchio/playback

Upvotes: 1

Views: 182

Answers (1)

mu is too short
mu is too short

Reputation: 434685

You can get away with two route handlers:

ROUTES =
  'action1/:page': 'page'
  'action2/:page': 'page'
  '*path': 'def'

and then:

page: (page) ->
  @setupPage(parseInt(page, 10))
def: ->
  @setupPage(1)

The splat route (*path) will send the matched part of the route to the handler so you can't use just one route handler without attempting to interpret what the splat matches.

Upvotes: 1

Related Questions