text: 
  /**
   * Convert the item looped into an object used to extend the child tag properties
   * @param   { Object } expr - object containing the keys used to extend the children tags
   * @param   { * } key - value to assign to the new object returned
   * @param   { * } val - value containing the position of the item in the array
   * @returns { Object } - new object containing the values of the original item
   *
   * The variables 'key' and 'val' are arbitrary.
   * They depend on the collection type looped (Array, Object)
   * and on the expression used on the each tag
   *
   */
  function mkitem(expr, key, val) {
    var item = {}
    item[expr.key] = key
    if (expr.pos) item[expr.pos] = val
    return item
  }
  
  /**
   * Unmount the redundant tags
   * @param   { Array } items - array containing the current items to loop
   * @param   { Array } tags - array containing all the children tags
   */
  function unmountRedundant(items, tags) {
  
    var i = tags.length,
      j = items.length,
      t
  
    while (i > j) {
      t = tags[--i]
      tags.splice(i, 1)
      t.unmount()
    }
  }
  
  /**
   * Move the nested custom tags in non custom loop tags
   * @param   { Object } child - non custom loop tag
   * @param   { Number } i - current position of the loop tag
   */
  function moveNestedTags(child, i) {
    Object.keys(child.tags).forEach(function(tagName) {
      var tag = child.tags[tagName]
      if (isArray(tag))
        each(tag, function (t) {
          moveChildTag(t, tagName, i)
        })
      else
        moveChildTag(tag, tagName, i)
    })
  }
  
  /**
   * Adds the elements for a virtual tag
   * @param { Tag } tag - the tag whose root's children will be inserted or appended
   * @param { Node } src - the node that will do the inserting or appending
   * @param { Tag } target - only if inserting, insert before this tag's first child
   */
  function addVirtual(tag, src, target) {
    var el = tag._root, sib
    tag._virts = []
    while (el) {
      sib = el.nextSibling
      if (target)
        src.insertBefore(el, target._root)
      else
        src.appendChild(el)
  
      tag._virts.push(el) // hold for unmounting
      el = sib
    }
  }
  
  /**
   * Move virtual tag and all child nodes
   * @param { Tag } tag - first child reference used to start move
   * @param { Node } src  - the node that will do the inserting
   * @param { Tag } target - insert before this tag's first child
   * @param { Number } len - how many child nodes to move
   */
  function moveVirtual(tag, src, target, len) {
    var el = tag._root, sib, i = 0
    for (; i < len; i++) {
      sib = el.nextSibling
      src.insertBefore(el, target._root)
      el = sib
    }
  }
  
  
  /**
   * Manage tags having the 'each'
   * @param   { Object } dom - DOM node we need to loop
   * @param   { Tag } parent - parent tag instance where the dom node is contained
   * @param   { String } expr - string contained in the 'each' attribute
   */
  function _each(dom, parent, expr) {
  
    // remove the each property from the original tag
    remAttr(dom, 'each')
  
    var mustReorder = typeof getAttr(dom, 'no-reorder') !== T_STRING || remAttr(dom, 'no-reorder'),
      tagName = getTagName(dom),
      impl = __tagImpl[tagName] || { tmpl: dom.outerHTML },
      useRoot = SPECIAL_TAGS_REGEX.test(tagName),
      root = dom.parentNode,
      ref = document.createTextNode(''),
      child = getTag(dom),
      isOption = /^option$/i.test(tagName), // the option tags must be treated differently
      tags = [],
      oldItems = [],
      hasKeys,
      isVirtual = dom.tagName == 'VIRTUAL'
  
    // parse the each expression
    expr = tmpl.loopKeys(expr)
  
    // insert a marked where the loop tags will be injected
    root.insertBefore(ref, dom)
  
    // clean template code
    parent.one('before-mount', function () {
  
      // remove the original DOM node
      dom.parentNode.removeChild(dom)
      if (root.stub) root = parent.root
  
    }).on('update', function () {
      // get the new items collection
      var items = tmpl(expr.val, parent),
        // create a fragment to hold the new DOM nodes to inject in the parent tag
        frag = document.createDocumentFragment()
  
  
  
      // object loop. any changes cause full redraw
      if (!isArray(items)) {
        hasKeys = items || false
        items = hasKeys ?
          Object.keys(items).map(function (key) {
            return mkitem(expr, key, items[key])
          }) : []
      }
  
      // loop all the new items
      items.forEach(function(item, i) {
        // reorder only if the items are objects
        var _mustReorder = mustReorder && item instanceof Object,
          oldPos = oldItems.indexOf(item),
          pos = ~oldPos && _mustReorder ? oldPos : i,
          // does a tag exist in this position?
          tag = tags[pos]
  
        item = !hasKeys && expr.key ? mkitem(expr, item, i) : item
  
        // new tag
        if (
          !_mustReorder && !tag // with no-reorder we just update the old tags
          ||
          _mustReorder && !~oldPos || !tag // by default we always try to reorder the DOM elements
        ) {
  
          tag = new Tag(impl, {
            parent: parent,
            isLoop: true,
            hasImpl: !!__tagImpl[tagName],
            root: useRoot ? root : dom.cloneNode(),
            item: item
          }, dom.innerHTML)
  
          tag.mount()
          if (isVirtual) tag._root = tag.root.firstChild // save reference for further moves or inserts
          // this tag must be appended
          if (i == tags.length) {
            if (isVirtual)
              addVirtual(tag, frag)
            else frag.appendChild(tag.root)
          }
          // this tag must be insert
          else {
            if (isVirtual)
              addVirtual(tag, root, tags[i])
            else root.insertBefore(tag.root, tags[i].root)
            oldItems.splice(i, 0, item)
          }
  
          tags.splice(i, 0, tag)
          pos = i // handled here so no move
        } else tag.update(item)
  
        // reorder the tag if it's not located in its previous position
        if (pos !== i && _mustReorder) {
          // update the DOM
          if (isVirtual)
            moveVirtual(tag, root, tags[i], dom.childNodes.length)
          else root.insertBefore(tag.root, tags[i].root)
          // update the position attribute if it exists
          if (expr.pos)
            tag[expr.pos] = i
          // move the old tag instance
          tags.splice(i, 0, tags.splice(pos, 1)[0])
          // move the old item
          oldItems.splice(i, 0, oldItems.splice(pos, 1)[0])
          // if the loop tags are not custom
          // we need to move all their custom tags into the right position
          if (!child && tag.tags) moveNestedTags(tag, i)
        }
  
        // cache the original item to use it in the events bound to this node
        // and its children
        tag._item = item
        // cache the real parent tag internally
        defineProperty(tag, '_parent', parent)
  
      })
  
      // remove the redundant tags
      unmountRedundant(items, tags)
  
      // insert the new nodes
      if (isOption) root.appendChild(frag)
      else root.insertBefore(frag, ref)
  
      // set the 'tags' property of the parent tag
      // if child is 'undefined' it means that we don't need to set this property
      // for example:
      // we don't need store the `myTag.tags['div']` property if we are looping a div tag
      // but we need to track the `myTag.tags['child']` property looping a custom child node named `child`
      if (child) parent.tags[tagName] = tags
  
      // clone the items array
      oldItems = items.slice()
  
    })
  
  }
  