view.coffee | |
---|---|
define ['subscriber', 'state_machine', 'ext/string'], (Subscriber, StateMachine, StringEx) ->
'use strict' | |
# | Private Methods |
# | |
Wrap method with an before[methodName] and after[methodName] | wrapMethods = (methodNames) ->
instance = @ |
Inner function that encapsulate the original method with after and before methods | wrapMethod = (methodName) ->
func = instance[methodName]
return instance[methodName] = -> |
Call the before[methodName] method | beforeRet = instance["before#{StringEx.upcase(methodName)}"].apply instance, arguments |
Here we verify if the object returned has the method done, if so, we'r talking about a object implementing the deferred object of jQuery. What we need here is defer the execution of the executing of the method and their after[method] counterpart right after the deferred object is resolved. | if beforeRet? and _.has beforeRet, 'done' |
Wait until the deferred is resolved | beforeRet.done () => |
Call the original method | func.apply instance, arguments |
Call after[methodName] method | instance["after#{StringEx.upcase(methodName)}"].apply instance, arguments |
if the object doesnt return anything, just call the methods | else |
Call the original method | func.apply @, arguments |
Call after[methodName] method | instance["after#{StringEx.upcase(methodName)}"].apply instance, arguments
return func
|
Use the inner function to wrap the method names passed as arguments | wrapMethod name for name in methodNames |
# | View Class |
# | class View extends Backbone.View |
View should inherit the defaults from Subscriber class | _(View.prototype).defaults(Subscriber);
_(View.prototype).defaults(StateMachine); |
Public Properties | dispose: false
containerSelector: null
autoRender: false
states: {}
transitions: {}
subscriptions: {}
|
Constructor | constructor: (options = {}) ->
@_registeredCollections = {} |
State machine required properties | @currentState = 'normal' |
Wrap render and initialize method with some before and after callbacks | wrapMethods.apply this, [['render', 'initialize']] |
Call super | super options |
Initialize method | initialize: (options={}) -> |
Call super | super options |
Render the view. | render: () -> |
console.log 'render' | |
This method is called before the method render. | beforeRender: () -> |
console.log 'beforeRender' | calls = []
for collection in @getRegisteredCollections()
calls.push collection.fetch()
return $.when.apply(@, calls) |
This method is called after the method render. | afterRender: () -> |
console.log 'afterRender' | if @containerSelector?
@containerSelector.empty().append(@$el) |
This method is called before the method initialize. | beforeInitialize: (options) -> |
console.log 'beforeInitialize' | for subscription, method of @subscriptions
unless _.isFunction @[method]
throw new Error("The method #{method} does not exist #{@cid}")
@subscribeEvent subscription, @[method] |
Verify if the have a option called containerSelector and, if so, find the DOM object | if options and options.containerSelector?
if _.isString options.containerSelector
@containerSelector = $(options.containerSelector) |
Verify is the collections property is set on options object | if _.has(options, 'collections')
for name, collection of options.collections
@registerViewCollection name, collection |
This method is called after the method initialize. | afterInitialize: (options) -> |
console.log 'afterInitialize' | |
Initialize the state machine | @startStateMachine() |
if we haven't a @containerSelector declared, skip | unless @containerSelector
return |
Render automatically if set by options or instance property and the option do not override it | byOption = options and options.autoRender is true
byDefault = @autoRender and not byOption
@render() if byOption or byDefault |
Return all registered collections | getRegisteredCollections: ->
return _( @_registeredCollections ).values();
|
Return a collection by it's name | getRegisteredCollection: (name) ->
if _.has(@_registeredCollections, name)
return @_registeredCollections[name];
return null |
Register a collection that will be used on the view. All collections registered using this method will be automatic disposed on view's dispose. If a collection is already registered, nothing happens @param collection The collection to be registered | registerViewCollection: (name, collection) ->
unless _.has( @_registeredCollections, name )
@_registeredCollections[name] = collection
|
Unregister a given collection. @param collection The collection to be unregistered | unregisterViewCollection: (name) ->
unless _.has(@_registeredCollections, name)
throw new Error("View#unregisterViewCollection: The collection with name #{ name } sent is not registered on this view")
collection = @_registeredCollections[name]
collection.dispose() |
Remove the collection from the array and dispose it | delete @_registeredCollections[name]
|
Unregister all collections registered on this view. Check the method unregisterViewCollection for more details | unregisterViewAllCollections: ->
for name in _.keys( @_registeredCollections )
@unregisterViewCollection name |
Adds a new event to the related model | modelBind: (eventType, handlerFunc, model) ->
unless model?
model = @model or @collection |
Unbinds a event from the related model | modelUnbind: (eventType, handlerFunc, model) ->
unless model?
model = @model or @collection |
Dispose method | dispose: ->
@unregisterViewAllCollections()
@unsubscribeAllEvents()
@disposed = yes
View
|