Last active
December 17, 2015 20:19
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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