   # Sets the value for the binding. This Basically just runs the binding routine
   # with the suplied value formatted.
   set: (value) =>
-    value = if value instanceof Function and @options.special isnt 'event'
+    value = if value instanceof Function and !@binder.function
       @formattedValue value.call @model
     else
       @formattedValue value
 
-    if @options.special is 'event'
-      @currentListener = @routine @el, @model, value, @currentListener
-    else if @options.special is 'iteration'
-      @routine @el, value, @
-    else
-      @routine @el, value
+    @binder.routine?.call @, @el, value
 
   # Syncs up the view binding with the model.
   sync: =>

  # element, the type of binding, the model object and the keypath at which
  # to listen for changes.
  constructor: (@el, @type, @model, @keypath, @options = {}) ->
    @routine = switch @options.special
      when 'event'     then eventBinding @type
      when 'class'     then classBinding @type
      when 'iteration' then iterationBinding @type
      else Rivets.routines[@type] || attributeBinding @type

    @formatters = @options.formatters || []

  # Returns true|false depending on whether or not the binding should also
  # observe the DOM element for changes in order to propagate those changes
  # back to the model object.
  isBidirectional: =>
    @type in ['value', 'checked', 'unchecked']

  # Applies all the current formatters to the supplied value and returns the
  # formatted value.

    when 'select-multiple' then o.value for o in el when o.selected
    else el.value

# Core binding routines.
Rivets.routines =
  enabled: (el, value) ->
    el.disabled = !value

  disabled: (el, value) ->
    el.disabled = !!value

  checked:
    publishes: true
    bind: (el) ->
      bindEvent el, 'change', @publish
    unbind: (el) ->
      unbindEvent el, 'change', @publish
    routine: (el, value) ->
      if el.type is 'radio'
        el.checked = el.value is value
      else
        el.checked = !!value

  unchecked:
    publishes: true
    bind: (el) ->
      bindEvent el, 'change', @publish
    unbind: (el) ->
      unbindEvent el, 'change', @publish
    routine: (el, value) ->
      if el.type is 'radio'
        el.checked = el.value isnt value
      else
        el.checked = !value

  show: (el, value) ->
    el.style.display = if value then '' else 'none'

  hide: (el, value) ->
    el.style.display = if value then 'none' else ''

  html: (el, value) ->
    el.innerHTML = if value? then value else ''

  value:
    publishes: true
    bind: (el) ->
      bindEvent el, 'change', @publish
    unbind: (el) ->
      unbindEvent el, 'change', @publish
    routine: (el, value) ->
      if el.type is 'select-multiple'
        o.selected = o.value in value for o in el if value?
      else
        el.value = if value? then value else ''

  text: (el, value) ->
    if el.innerText?
      el.innerText = if value? then value else ''
    else
      el.textContent = if value? then value else ''

  "on-*":
    function: true
    routine: (el, value) ->
      unbindEvent el, @args[0], @currentListener if @currentListener
      @currentListener = bindEvent el, @args[0], value, @model

  "each-*":
    block: true
    bind: (el, collection) ->
      el.removeAttribute ['data', rivets.config.prefix, @type].join('-').replace '--', '-'
    routine: (el, collection) ->
      if @iterated?
        for view in @iterated
          view.unbind()
          e.parentNode.removeChild e for e in view.els
      else
        @marker = document.createComment " rivets: #{@type} "
        el.parentNode.insertBefore @marker, el
        el.parentNode.removeChild el

      @iterated = []

      for item in collection
        data = {}
        data[n] = m for n, m of @view.models
        data[@args[0]] = item
        itemEl = el.cloneNode true
        previous = @iterated[@iterated.length - 1] or @marker
        @marker.parentNode.insertBefore itemEl, previous.nextSibling ? null
        @iterated.push rivets.bind itemEl, data

  "class-*": (el, value) ->
    elClass = " #{el.className} "

    if !value is (elClass.indexOf(" #{@args[0]} ") isnt -1)
      el.className = if value
        "#{el.className} #{@args[0]}"
      else
        elClass.replace(" #{@args[0]} ", ' ').trim()

  "*": (el, value) ->
    if value
      el.setAttribute @type, value
    else
      el.removeAttribute @type

# Default configuration.
Rivets.config =
