var _ = require('../util')
var compiler = require('../compiler')
var templateParser = require('../parsers/template')
var transition = require('../transition')
var Cache = require('../cache')
var cache = new Cache(1000)

module.exports = {

  bind: function () {
    var el = this.el
    if (!el.__vue__) {
      this.start = _.createAnchor('v-if-start')
      this.end = _.createAnchor('v-if-end')
      _.replace(el, this.end)
      _.before(this.start, this.end)
      if (_.isTemplate(el)) {
        this.template = templateParser.parse(el, true)
      } else {
        this.template = document.createDocumentFragment()
        this.template.appendChild(templateParser.clone(el))
      }
      // compile the nested partial
      var cacheId = (this.vm.constructor.cid || '') + el.outerHTML
      this.linker = cache.get(cacheId)
      if (!this.linker) {
        this.linker = compiler.compile(
          this.template,
          this.vm.$options,
          true // partial
        )
        cache.put(cacheId, this.linker)
      }
    } else {
      process.env.NODE_ENV !== 'production' && _.warn(
        'v-if="' + this.expression + '" cannot be ' +
        'used on an instance root element.'
      )
      this.invalid = true
    }
  },

  update: function (value) {
    if (this.invalid) return
    if (value) {
      // avoid duplicate compiles, since update() can be
      // called with different truthy values
      if (!this.unlink) {
        this.link(
          templateParser.clone(this.template),
          this.linker
        )
      }
    } else {
      this.teardown()
    }
  },

  link: function (frag, linker) {
    var vm = this.vm
    this.unlink = linker(vm, frag, this._host, this._scope)
    transition.blockAppend(frag, this.end, vm)
    // call attached for all the child components created
    // during the compilation
    if (_.inDoc(vm.$el)) {
      var children = this.getContainedComponents()
      if (children) children.forEach(callAttach)
    }
  },

  teardown: function () {
    if (!this.unlink) return
    // collect children beforehand
    var children
    if (_.inDoc(this.vm.$el)) {
      children = this.getContainedComponents()
    }
    transition.blockRemove(this.start, this.end, this.vm)
    if (children) children.forEach(callDetach)
    this.unlink()
    this.unlink = null
  },

  getContainedComponents: function () {
    var vm = this.vm
    var start = this.start.nextSibling
    var end = this.end

    function contains (c) {
      var cur = start
      var next
      while (next !== end) {
        next = cur.nextSibling
        if (
          cur === c.$el ||
          cur.contains && cur.contains(c.$el)
        ) {
          return true
        }
        cur = next
      }
      return false
    }

    return vm.$children.length &&
      vm.$children.filter(contains)
  },

  unbind: function () {
    if (this.unlink) this.unlink()
  }

}

function callAttach (child) {
  if (!child._isAttached) {
    child._callHook('attached')
  }
}

function callDetach (child) {
  if (child._isAttached) {
    child._callHook('detached')
  }
}

@@ -28,194 +28,55 @@
 var 
-compiler = require('../compiler')%0Avar templateParser = require('../parsers/template')%0Avar transition = require('../transition')%0Avar Cache = require('../cache')%0Avar cache = new Cache(1000
+FragmentFactory = require('../fragment/factory'
 )%0A%0Am
@@ -175,59 +175,14 @@
 his.
-start = _.createAnchor('v-if-start')%0A      this.end
+anchor
  = _
@@ -204,12 +204,8 @@
 v-if
--end
 ')%0A 
@@ -232,214 +232,22 @@
 his.
-end)%0A      _.before(this.start, this.end)%0A      if (_.isTemplate(el)) %7B%0A        this.template = templateParser.parse(el, true)%0A      %7D else %7B%0A        this.template = document.createDocumentFragment(
+anchor
 )%0A      
   th
@@ -246,414 +246,55 @@
     
- 
- 
 this.
-template.appendChild(templateParser.clone(el))%0A      %7D%0A      // compile the nested partial%0A      var cacheId = (this.vm.constructor.cid %7C%7C '') + el.outerHTML%0A      this.linker = cache.get(cacheId)%0A      if (!this.linker) %7B%0A        this.linker = compiler.compile(%0A          this.template,%0A          this.vm.$options,%0A          true // partial%0A        )%0A        cache.put(cacheId, this.linker)%0A      %7D
+factory = new FragmentFactory(this.vm, el)
 %0A   
@@ -581,110 +581,8 @@
 ) %7B%0A
-      // avoid duplicate compiles, since update() can be%0A      // called with different truthy values%0A
     
@@ -593,22 +593,20 @@
  (!this.
-unlink
+frag
 ) %7B%0A    
@@ -618,91 +618,15 @@
 his.
-link(%0A          templateParser.clone(this.template),%0A          this.linker%0A        
+create(
 )%0A  
@@ -680,20 +680,22 @@
   %7D,%0A%0A  
-link
+create
 : functi
@@ -702,150 +702,105 @@
 on (
-frag, linker) %7B%0A    var vm = this.vm%0A    this.unlink = linker(vm, frag, this._host, this._scope)%0A    transition.blockAppend(frag, this.end, vm
+) %7B%0A    this.frag = this.factory.create(this._host, this._scope)%0A    this.frag.before(this.anchor
 )%0A  
@@ -901,16 +901,21 @@
 _.inDoc(
+this.
 vm.$el))
@@ -1069,22 +1069,20 @@
  (!this.
-unlink
+frag
 ) return
@@ -1228,59 +1228,24 @@
    t
-ransition.blockRemove(this.start, this.end, this.vm
+his.frag.remove(
 )%0A  
@@ -1294,24 +1294,29 @@
 h)%0A    this.
+frag.
 unlink()%0A   
@@ -1321,22 +1321,20 @@
    this.
-unlink
+frag
  = null%0A
@@ -1425,25 +1425,17 @@
 his.
-start.nextSibling
+frag.node
 %0A   
@@ -1450,19 +1450,22 @@
  = this.
-end
+anchor
 %0A%0A    fu
@@ -1883,20 +1883,31 @@
 his.
-unlink) this
+frag) %7B%0A      this.frag
 .unl
@@ -1914,18 +1914,23 @@
 ink()%0A  
+  %7D%0A  
 %7D
-%0A
 %0A%7D%0A%0Afunc

use fragment in v-if