Created
December 8, 2011 17:57
-
-
Save ggoodman/1447830 to your computer and use it in GitHub Desktop.
Declarative client-side view engine in 100% Coffee-Script
This file contains 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
### | |
WARNIG: This was 100% written in notepad without debugging. | |
### | |
class lumbar.View | |
@attachDefaults: | |
mountPoint: "@" | |
mountMethod: "html" | |
type: "one" | |
@attach: (name, options = {}) -> | |
@attachedViews ?= {} | |
@attachedViews[name] = _.defaults options, @attachDefaults | |
mountMethod: "html" # Replace contents with rendered template | |
renderEvents: "all" # Re-render on 'all' events | |
template: -> | |
initialize: -> | |
setMountPoint: (@mountPoint) -> | |
setMountMethod: (@mountMethod) -> | |
render: => | |
@$ = $(CoffeeKup.render @template, @getViewModel()) | |
if @mountPoint | |
@mountPoint[@mountMethod](@$) | |
@emit "mounted" | |
@emit "rendered" | |
@renderAttachedViews() | |
@ | |
renderAttachedView: (name, options) -> | |
# Check to see if the viewModel needs to be lazy-loaded | |
if options.createViewModel and not options.viewModel | |
throw new Error("createViewModel must be a function") unless _.isFunction(options.createViewModel) | |
options.viewModel = options.createViewModel.call(@) | |
throw new Error("Missing or invalid viewModel") unless options.viewModel instanceof lumbar.View | |
childView.setMountPoint if options.mountPoint is "@" then @$ else @$.find(options.mountPoint) | |
childView.setMountMethod options.mountMethod | |
childView.render() | |
renderAttachedViewList: (name, options) -> | |
if options.createIterator and not options.iterator | |
throw new Error("createIterator must be a function") unless _.isFunction(options.createIterator) | |
options.iterator = options.createIterator.call(@) | |
throw new Error("Missing or invalid iterator") unless _.isFunction(options.iterator) | |
self = @ | |
options.iterator.call @, name, options, (viewModel) -> | |
self.renderAttachedView name, _.extend {}, options, | |
type: "one" | |
viewModel: viewModel | |
renderAttachedViews: -> | |
for name, options of @attachedViews | |
if options.type is "one" then @renderAttachedView(name, options) | |
else if options.type is "many" then @renderAttachedViewList(name, options) | |
else throw new Error("Invalid attachment type: #{options.type}") | |
@ | |
constructor: (options = {}) -> | |
@[key] = value for key, value of options when not @[key] | |
# Transfer over things set-up through constructor-level methods | |
@attachDefaults = @constructor.attachDefaults | |
@attach = @constructor.attach | |
@attachedViews = @constructor.attachedViews | |
@initialize(arguments...) | |
class lumbar.CollectionView | |
@attachDefaults: | |
mountMethod: "append" | |
iterator: (name, options, cb) -> | |
# Return a function that iterates through the collection | |
throw new Error("Invalid or missing modelViewClass") unless options.modelViewClass | |
-> @collection.each (model) -> new options.modelViewClass(model: model) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment