BEWARE! This is an archived article. It is potentially out-of-date, incorrect, or otherwise in disagreement with my current opinions. Proceed with caution!

December 01, 2015

Spellbook Dispatcher

By Drew Barontini

Dispatcher is a JavaScript class that determines which page is active, and runs page-specific initialization code based on that determination.

Our team first discovered the pattern within the GitLab repository. They created a JavaScript class (written in CoffeeScript) to:

  • Get a data attribute from the body tag
  • Run a switch statement for that data attribute
  • And run page-specific initialization code based on which page is active
page = $( 'body' ).data( 'page' )

switch page
  when 'home'  then new Home()
  when 'about' then new About()
  # ...

And, in this instance, Home and About are other CoffeeScript classes that run setup code for the given pages.

class Home

  constructor : ->
    # ...
class About

  constructor : ->
    # ...

In their version, though, the switch statement is set up to check for each page within the same Dispatcher class. We thought this would be perfect to abstract, so we pulled it out into Spellbook.

If you’d like to learn more about Spellbook, you can read my article on it.

Setting the data attribute

In order to pull the correct page, the data attribute has to be configured correctly for each page. I’ll illustrate how to do this in Ruby on Rails, but the concept should be similar in other environments.

I did not write this. This is a result of our amazing Rails developers at Code School. I take no credit here.

In app/helpers/application_helper.rb:

def body_data_attribute(options)
  @body_data_attributes ||= {}


def body_data_attributes

def body_data_page
  path      = controller_path.split('/')
  namespace = path.first if path.second

  [namespace, controller_name, action_name].compact.join(':')

In app/layouts/application.html.haml:

- body_data_attribute 'page' => body_data_page

%body{ class: 'js-dispatcher', data: body_data_attributes }

This will generate:

<body class='js-dispatcher' data-page='users:show'>
  <!-- ... -->

And the data-page attribute will change based on the current page that’s being shown.


Let’s talk about the structure of the Dispatcher class.

We need configurable settings for:

  • Which element has the data attribute for the active page
  • The name of the data attribute on said element
  • An array of events for running the page-specific code

All code examples are written in CoffeeScript for brevity and alignment with Spellbook’s conventions. However, the same principles can be applied to vanilla JavaScript.

class @Spellbook.Classes.Dispatcher extends @Spellbook.Classes.Base

  # ...

Wait! What is the extends @Spellbook.Classes.Base bit? That’s something that my coworker, John D. Jameson, added to Spellbook. It abstracts the standard, boilerplate code into its own class.

class @Spellbook.Classes.Base

  _settings : {}

  constructor : ( @options ) -> @init?()

  _setDefaults : ( defaults ) ->
    @_settings = $.extend( defaults, @options )

This abstracts the setup code we typically write to:

  • Call an init method from the constructor
  • Merge defaults and passed-in options into a _settings object


Within the Dispatcher class, we create our init method.

init : ->
    $element : $( '.js-dispatcher' )
    dataAttr : 'dispatcher-page'
    events   : []

  • We call the @Spellbook.Classes.Base _setDefaults method for our default options to be merged with any overrides
  • We set a jQuery object with a class of .js-dispatcher as the element
  • We set the name of the data attribute on the element
  • We set an empty array of events
  • And we call a dispatch method

The events array is an array of objects, and each object contains two parts:

  1. A string representing the data attribute value
  2. A function to run the initialization code for that page
events = [
  { page : 'home', run : -> console.log( 'Hello, home page!') }
  # ...


Let’s look at the dispatch method in its entirety before we break it down.

dispatch : ( event = null ) ->
  page = @_getCurrentPage()

  return false unless page

  unless event?
    for event in
        when page  then
        when 'all' then

      if event.match if page.match( event.match )

      when page  then
      when 'all' then

Now let’s look at it piece by piece.

dispatch : ( event = null ) ->
  # ...

We have a single argument of event, which has a default value of null, if nothing is passed in.

page = @_getCurrentPage()

We call a _getCurrentPage method to determine the current page. That method looks like this:

_getCurrentPage : ->
    @_settings.$ @_settings.dataAttr )

All it’s doing is getting the data attribute value off of the element (generally the body) and returning it.

Back in our dispatch method:

return false unless page

If there isn’t a value for page (as returned by _getCurrentPage), we just want to return and stop execution of the dispatch method.

unless event?
  for event in
      when page  then
      when 'all' then

    if event.match if page.match( event.match )
  • Unless event has been directly called (not null), we loop through the events in
  • We run a switch statement to check matches on the current page
  • If it matches, we execute the run function in the event object
  • If the is 'all', run the function
if event.match if page.match( event.match )

This block is a special circumstance when we want to match multiple pages that share a similar string. For example, users:index, users:show, users:edit.

events : [
  { match : 'users', run : -> new Users() }

The new Users() class instantiation will be run on any page where the element’s data attribute contains the string 'users'.

Back in the dispatch method:

    when page  then
    when 'all' then

If the event argument of the dispatch method is not null (meaning an argument of value was passed in), run the same switch as earlier.

This is for one-off instances to pass an event object directly to the dispatch method:

dispatcher = new Spellbook.Classes.Dispatcher()
  page: 'home'
  run: -> Home.init()

And that covers all the functionality the Dispatcher class provides. Now, with it in place, we can instantiate the object and set up our calls:

new Spellbook.Classes.Dispatcher
  events: [
      page : 'home',
      run  : -> new Home() # Run page-specific JS on the Home page.
      page : 'about',
      run  : -> new About() # Run page-specific JS on the About page.

As you can see, the Dispatcher provides organization and structure to a codebase with multiple pages requiring setup code. Hopefully this can help you organize non-JS-framework codebases that rely on more traditional, “from scratch” JavaScript structure.

© 2018 Drew Barontini — Building products under Drewbio, LLC