Skip to content

Instantly share code, notes, and snippets.

@adamrenklint
Last active December 17, 2015 20:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamrenklint/5667052 to your computer and use it in GitHub Desktop.
Save adamrenklint/5667052 to your computer and use it in GitHub Desktop.
Simple mixin to glue together a controller and view presenter example for Backbone. The view is modified to not handle DOM events on its own, but offer a public interface (replacing the old events hash) for decoupled wiring with controller.
define 'ExampleController', ->
class
# Save a reference to the view
constructor: (@view) ->
# Hook our method up to the view event
implements:
'click:logo': 'clickLogo'
clickLogo: (ev) =>
console.log 'logo was clicked', ev
define 'ExampleViewPresenter', ->
class extends Backbone.View
template: '<div class="some-logo"></div>'
# Define our controllers. Could be a function, useful for subclassing.
implements: [ExampleController]
# The public interface the controllers wires up to
events:
'click .some-logo': 'click:logo'
constructor:
_.extend @, ImplementsMixin
# Overrides Backbone's delegateEvents methods to provide a decoupled interface between controllers and views
define 'ImplementsMixin', ->
mixin =
delegateEvents: (events) ->
# Kill all existing controllers
@undelegateEvents()
# If an events hash was passed as argument, use that
# If not, grab the own events hash, which could be a function
events ?= @events?() or @events
# Make a reversed copy for later lookup
reversed = _.invert events
# To store a map the used event keys and their controllers
controllers = {}
# The final event object
final = {}
# Make a list of controller classes to implement
Controllers = @implements?() or @implements
# Instantiate, pass in the view and let the controller do the rest
for Controller in Controllers or []
controller = new Controller @
# If a controller implements a handler for the event, save it for later
for event of controller.implements or {}
controllers[event] = controller
# Finally, loop the stored controllers and wire it all up
for event of controllers
# Setup the variables we need to execute the handler
selector = reversed[event]
controller = controllers[event]
methodName = controller.implements[event]
# Create the event callback
final[selector] = (ev) ->
# Execute the handler with an ASEventObject
controller[methodName].call @, {} =
event: ev,
view: @,
controller: controller,
name: event
# Finally, let Backbone do it's thing
Backbone.View.prototype.delegateEvents.call @, final
undelegateEvents: ->
# Loop and destroy
for controller in @controllers or []
controller.destroy()
# Backbone will take care of actually unbinding things
Backbone.View.prototype.undelegateEvents.call @
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment