Jump To …

elementFactory.coffee

ElementFactory =
  Elements: input: {}

  createElement: (el) ->
    if 'input' == name = el.nodeName.toLowerCase()
      El = ElementFactory.Elements[name][el.type.toLowerCase()] || Input
    else
      El = ElementFactory.Elements[name] || Element

    new El(el)


class Element
  constructor: (@el) ->
    @attributes         = {}
    @childNodes         = getChildNodes @el
    @nodeName           = @el.nodeName.toLowerCase()
    @classNames         = @el.className.split ' '
    @originalAttributes = {}

  empty: chainable ->
    @el.removeChild child while child = @el.firstChild

  reset: ->
    for name, attribute of @attributes
      attribute.set attribute.templateValue

  render: (value) -> @attr 'text', value

  attr: (name, value) ->
    attribute = @attributes[name] ||= AttributeFactory.createAttribute @el, name, value
    attribute.set value

  renderDirectives: (model, index, attributes) ->
    for own name, directive of attributes when typeof directive == 'function'
      value = directive.call model,
        element: @el
        index:   index
        value:   @attributes[name]?.templateValue || ''

      @attr(name, value) if value?


class Select extends Element
  ElementFactory.Elements['select'] = this

  constructor: (el) ->
    super el
    @elements = getElements el

  render: (value) ->
    value = value.toString()
    for option in @elements when option.nodeName == 'option'
      option.attr 'selected', option.el.value == value


class VoidElement extends Element

From http://www.w3.org/TR/html-markup/syntax.html: void elements in HTML

  VOID_ELEMENTS = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img',
    'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']

  for nodeName in VOID_ELEMENTS
    ElementFactory.Elements[nodeName] = this

  attr: (name, value) -> super name, value unless name in ['text', 'html']


class Input extends VoidElement
  render: (value) -> @attr 'value', value


class Checkbox extends Input
  ElementFactory.Elements['input']['checkbox'] = this

  render: (value) -> @attr 'checked', Boolean(value)


class Radio extends Checkbox
  ElementFactory.Elements['input']['radio'] = this