Files
atom/src/stdlib/template/builder.coffee
2011-12-29 11:43:14 -06:00

72 lines
2.2 KiB
CoffeeScript

_ = require 'underscore'
$ = require 'jquery'
OpenTag = require 'template/open-tag'
CloseTag = require 'template/close-tag'
Text = require 'template/text'
module.exports =
class Builder
@elements:
normal: 'a abbr address article aside audio b bdi bdo blockquote body button
canvas caption cite code colgroup datalist dd del details dfn div dl dt em
fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup
html i iframe ins kbd label legend li map mark menu meter nav noscript object
ol optgroup option output p pre progress q rp rt ruby s samp script section
select small span strong style sub summary sup table tbody td textarea tfoot
th thead time title tr u ul video'.split /\s+/
void: 'area base br col command embed hr img input keygen link meta param
source track wbr'.split /\s+/
constructor: ->
@reset()
toHtml: ->
_.map(@document, (x) -> x.toHtml()).join('')
toFragment: ->
fragment = $(@toHtml())
fn(fragment) for fn in @postProcessingFns
fragment
tag: (name, args...) ->
options = @extractOptions(args)
@document.push(new OpenTag(name, options.attributes))
if @elementIsVoid(name)
if (options.text? or options.content?)
throw new Error("Self-closing tag #{tag} cannot have text or content")
else
options.content?()
@text(options.text) if options.text
@document.push(new CloseTag(name))
subview: (outletName, template, params) ->
subviewId = ++@subviewCount
@tag 'div', subview: subviewId
@postProcessingFns.push (view) ->
subview = template.build(params)
subview.attr('outlet', outletName)
view.find("div[subview=#{subviewId}]").replaceWith(subview)
elementIsVoid: (name) ->
name in @constructor.elements.void
extractOptions: (args) ->
options = {}
for arg in args
options.content = arg if _.isFunction(arg)
options.text = arg if _.isString(arg)
options.text = arg.toString() if _.isNumber(arg)
options.attributes = arg if _.isObject(arg) and not _.isFunction(arg)
options
text: (string) ->
@document.push(new Text(string))
reset: ->
@subviewCount = 0
@document = []
@postProcessingFns = []