 defaultfn = {}
 EVENTS.forEach (e) ->
     defaultfn[e] = -> throw new Error "no specific fn for #{e} defined" # dummy
+
+
+class BrowserState
+    initialize: (prev) ->
+        @manip ?= cancelable_and_retrivable_callbacks()
+        @done  ?= deferred_callbacks()
+        @manip.reset()
+
+    mergeInto: (state) ->
+        for key in SHARED
+            state[key] ?= this[key]
+            this[key] = null
+        state
+
+    destroy: (opts) ->
+        @manip?.cancel()
+        @done?.reset()
+        if opts.soft
+            this[key] = null for key in SHARED
+        else
+            delete this[key] for key in SHARED
+            delete manip
+        this
 
 
 class BrowserAdapter


    onremove: (el, opts) ->
        @fn.remove(el, opts)
        el._browser_parent_done?.replace(null)
        el._browser_done?.reset()
        el._browser_manip?.cancel()
        delete el._browser_parent_done
        delete el._browser_replace
        delete el._browser_insert
        unless opts.soft
            delete el._browser_manip
            delete el._browser_done

    # ready callbacks

    insert_callback: (el) ->
        @fn.add(el.parent, el)
        el._browser_ready?()
        el._browser_ready = yes
        el._browser_insert = yes

    parent_done_callback: (el) ->
        if el.parent is el.parent.builder
            bool = (not el.parent.parent? or
                       (el.parent.parent is el.parent.parent?.builder and # FIXME recursive?
                        el.parent.parent?._browser_insert is true))
            if bool and el.parent._browser_insert is true
                @animation.push(el._browser_insert)
            else
                el._browser_insert?()
        else
            @animation.push(el._browser_insert)

    replace_callback: (oldtag, newtag) ->
        @fn.replace(oldtag, newtag)

        do @listen
        # prefill builder with state
        @make(@builder) # create a dom object
        (@builder._browser ?= new BrowserState).done = deferred_callbacks()
        do @builder._browser.done.callback() # builder is allways done
        # register ready handler
        @template.register 'ready', (tag, next) ->
            tag._browser ?= new BrowserState
            # when tag is already in the dom its fine,
            #  else wait until it is inserted into dom
            if tag._browser.ready is yes
                next(tag)
            else
                tag._browser.ready = next
        return this

    use: (plugin) ->
