github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/util/dom.js (about)

     1  import config from '../config'
     2  import { isIE9 } from './env'
     3  import { warn } from './debug'
     4  import { camelize } from './lang'
     5  import { removeWithTransition } from '../transition/index'
     6  
     7  /**
     8   * Query an element selector if it's not an element already.
     9   *
    10   * @param {String|Element} el
    11   * @return {Element}
    12   */
    13  
    14  export function query (el) {
    15    if (typeof el === 'string') {
    16      var selector = el
    17      el = document.querySelector(el)
    18      if (!el) {
    19        process.env.NODE_ENV !== 'production' && warn(
    20          'Cannot find element: ' + selector
    21        )
    22      }
    23    }
    24    return el
    25  }
    26  
    27  /**
    28   * Check if a node is in the document.
    29   * Note: document.documentElement.contains should work here
    30   * but always returns false for comment nodes in phantomjs,
    31   * making unit tests difficult. This is fixed by doing the
    32   * contains() check on the node's parentNode instead of
    33   * the node itself.
    34   *
    35   * @param {Node} node
    36   * @return {Boolean}
    37   */
    38  
    39  export function inDoc (node) {
    40    if (!node) return false
    41    var doc = node.ownerDocument.documentElement
    42    var parent = node.parentNode
    43    return doc === node ||
    44      doc === parent ||
    45      !!(parent && parent.nodeType === 1 && (doc.contains(parent)))
    46  }
    47  
    48  /**
    49   * Get and remove an attribute from a node.
    50   *
    51   * @param {Node} node
    52   * @param {String} _attr
    53   */
    54  
    55  export function getAttr (node, _attr) {
    56    var val = node.getAttribute(_attr)
    57    if (val !== null) {
    58      node.removeAttribute(_attr)
    59    }
    60    return val
    61  }
    62  
    63  /**
    64   * Get an attribute with colon or v-bind: prefix.
    65   *
    66   * @param {Node} node
    67   * @param {String} name
    68   * @return {String|null}
    69   */
    70  
    71  export function getBindAttr (node, name) {
    72    var val = getAttr(node, ':' + name)
    73    if (val === null) {
    74      val = getAttr(node, 'v-bind:' + name)
    75    }
    76    return val
    77  }
    78  
    79  /**
    80   * Check the presence of a bind attribute.
    81   *
    82   * @param {Node} node
    83   * @param {String} name
    84   * @return {Boolean}
    85   */
    86  
    87  export function hasBindAttr (node, name) {
    88    return node.hasAttribute(name) ||
    89      node.hasAttribute(':' + name) ||
    90      node.hasAttribute('v-bind:' + name)
    91  }
    92  
    93  /**
    94   * Insert el before target
    95   *
    96   * @param {Element} el
    97   * @param {Element} target
    98   */
    99  
   100  export function before (el, target) {
   101    target.parentNode.insertBefore(el, target)
   102  }
   103  
   104  /**
   105   * Insert el after target
   106   *
   107   * @param {Element} el
   108   * @param {Element} target
   109   */
   110  
   111  export function after (el, target) {
   112    if (target.nextSibling) {
   113      before(el, target.nextSibling)
   114    } else {
   115      target.parentNode.appendChild(el)
   116    }
   117  }
   118  
   119  /**
   120   * Remove el from DOM
   121   *
   122   * @param {Element} el
   123   */
   124  
   125  export function remove (el) {
   126    el.parentNode.removeChild(el)
   127  }
   128  
   129  /**
   130   * Prepend el to target
   131   *
   132   * @param {Element} el
   133   * @param {Element} target
   134   */
   135  
   136  export function prepend (el, target) {
   137    if (target.firstChild) {
   138      before(el, target.firstChild)
   139    } else {
   140      target.appendChild(el)
   141    }
   142  }
   143  
   144  /**
   145   * Replace target with el
   146   *
   147   * @param {Element} target
   148   * @param {Element} el
   149   */
   150  
   151  export function replace (target, el) {
   152    var parent = target.parentNode
   153    if (parent) {
   154      parent.replaceChild(el, target)
   155    }
   156  }
   157  
   158  /**
   159   * Add event listener shorthand.
   160   *
   161   * @param {Element} el
   162   * @param {String} event
   163   * @param {Function} cb
   164   * @param {Boolean} [useCapture]
   165   */
   166  
   167  export function on (el, event, cb, useCapture) {
   168    el.addEventListener(event, cb, useCapture)
   169  }
   170  
   171  /**
   172   * Remove event listener shorthand.
   173   *
   174   * @param {Element} el
   175   * @param {String} event
   176   * @param {Function} cb
   177   */
   178  
   179  export function off (el, event, cb) {
   180    el.removeEventListener(event, cb)
   181  }
   182  
   183  /**
   184   * For IE9 compat: when both class and :class are present
   185   * getAttribute('class') returns wrong value...
   186   *
   187   * @param {Element} el
   188   * @return {String}
   189   */
   190  
   191  function getClass (el) {
   192    var classname = el.className
   193    if (typeof classname === 'object') {
   194      classname = classname.baseVal || ''
   195    }
   196    return classname
   197  }
   198  
   199  /**
   200   * In IE9, setAttribute('class') will result in empty class
   201   * if the element also has the :class attribute; However in
   202   * PhantomJS, setting `className` does not work on SVG elements...
   203   * So we have to do a conditional check here.
   204   *
   205   * @param {Element} el
   206   * @param {String} cls
   207   */
   208  
   209  export function setClass (el, cls) {
   210    /* istanbul ignore if */
   211    if (isIE9 && !/svg$/.test(el.namespaceURI)) {
   212      el.className = cls
   213    } else {
   214      el.setAttribute('class', cls)
   215    }
   216  }
   217  
   218  /**
   219   * Add class with compatibility for IE & SVG
   220   *
   221   * @param {Element} el
   222   * @param {String} cls
   223   */
   224  
   225  export function addClass (el, cls) {
   226    if (el.classList) {
   227      el.classList.add(cls)
   228    } else {
   229      var cur = ' ' + getClass(el) + ' '
   230      if (cur.indexOf(' ' + cls + ' ') < 0) {
   231        setClass(el, (cur + cls).trim())
   232      }
   233    }
   234  }
   235  
   236  /**
   237   * Remove class with compatibility for IE & SVG
   238   *
   239   * @param {Element} el
   240   * @param {String} cls
   241   */
   242  
   243  export function removeClass (el, cls) {
   244    if (el.classList) {
   245      el.classList.remove(cls)
   246    } else {
   247      var cur = ' ' + getClass(el) + ' '
   248      var tar = ' ' + cls + ' '
   249      while (cur.indexOf(tar) >= 0) {
   250        cur = cur.replace(tar, ' ')
   251      }
   252      setClass(el, cur.trim())
   253    }
   254    if (!el.className) {
   255      el.removeAttribute('class')
   256    }
   257  }
   258  
   259  /**
   260   * Extract raw content inside an element into a temporary
   261   * container div
   262   *
   263   * @param {Element} el
   264   * @param {Boolean} asFragment
   265   * @return {Element|DocumentFragment}
   266   */
   267  
   268  export function extractContent (el, asFragment) {
   269    var child
   270    var rawContent
   271    /* istanbul ignore if */
   272    if (isTemplate(el) && isFragment(el.content)) {
   273      el = el.content
   274    }
   275    if (el.hasChildNodes()) {
   276      trimNode(el)
   277      rawContent = asFragment
   278        ? document.createDocumentFragment()
   279        : document.createElement('div')
   280      /* eslint-disable no-cond-assign */
   281      while (child = el.firstChild) {
   282      /* eslint-enable no-cond-assign */
   283        rawContent.appendChild(child)
   284      }
   285    }
   286    return rawContent
   287  }
   288  
   289  /**
   290   * Trim possible empty head/tail text and comment
   291   * nodes inside a parent.
   292   *
   293   * @param {Node} node
   294   */
   295  
   296  export function trimNode (node) {
   297    var child
   298    /* eslint-disable no-sequences */
   299    while (child = node.firstChild, isTrimmable(child)) {
   300      node.removeChild(child)
   301    }
   302    while (child = node.lastChild, isTrimmable(child)) {
   303      node.removeChild(child)
   304    }
   305    /* eslint-enable no-sequences */
   306  }
   307  
   308  function isTrimmable (node) {
   309    return node && (
   310      (node.nodeType === 3 && !node.data.trim()) ||
   311      node.nodeType === 8
   312    )
   313  }
   314  
   315  /**
   316   * Check if an element is a template tag.
   317   * Note if the template appears inside an SVG its tagName
   318   * will be in lowercase.
   319   *
   320   * @param {Element} el
   321   */
   322  
   323  export function isTemplate (el) {
   324    return el.tagName &&
   325      el.tagName.toLowerCase() === 'template'
   326  }
   327  
   328  /**
   329   * Create an "anchor" for performing dom insertion/removals.
   330   * This is used in a number of scenarios:
   331   * - fragment instance
   332   * - v-html
   333   * - v-if
   334   * - v-for
   335   * - component
   336   *
   337   * @param {String} content
   338   * @param {Boolean} persist - IE trashes empty textNodes on
   339   *                            cloneNode(true), so in certain
   340   *                            cases the anchor needs to be
   341   *                            non-empty to be persisted in
   342   *                            templates.
   343   * @return {Comment|Text}
   344   */
   345  
   346  export function createAnchor (content, persist) {
   347    var anchor = config.debug
   348      ? document.createComment(content)
   349      : document.createTextNode(persist ? ' ' : '')
   350    anchor.__v_anchor = true
   351    return anchor
   352  }
   353  
   354  /**
   355   * Find a component ref attribute that starts with $.
   356   *
   357   * @param {Element} node
   358   * @return {String|undefined}
   359   */
   360  
   361  var refRE = /^v-ref:/
   362  export function findRef (node) {
   363    if (node.hasAttributes()) {
   364      var attrs = node.attributes
   365      for (var i = 0, l = attrs.length; i < l; i++) {
   366        var name = attrs[i].name
   367        if (refRE.test(name)) {
   368          return camelize(name.replace(refRE, ''))
   369        }
   370      }
   371    }
   372  }
   373  
   374  /**
   375   * Map a function to a range of nodes .
   376   *
   377   * @param {Node} node
   378   * @param {Node} end
   379   * @param {Function} op
   380   */
   381  
   382  export function mapNodeRange (node, end, op) {
   383    var next
   384    while (node !== end) {
   385      next = node.nextSibling
   386      op(node)
   387      node = next
   388    }
   389    op(end)
   390  }
   391  
   392  /**
   393   * Remove a range of nodes with transition, store
   394   * the nodes in a fragment with correct ordering,
   395   * and call callback when done.
   396   *
   397   * @param {Node} start
   398   * @param {Node} end
   399   * @param {Vue} vm
   400   * @param {DocumentFragment} frag
   401   * @param {Function} cb
   402   */
   403  
   404  export function removeNodeRange (start, end, vm, frag, cb) {
   405    var done = false
   406    var removed = 0
   407    var nodes = []
   408    mapNodeRange(start, end, function (node) {
   409      if (node === end) done = true
   410      nodes.push(node)
   411      removeWithTransition(node, vm, onRemoved)
   412    })
   413    function onRemoved () {
   414      removed++
   415      if (done && removed >= nodes.length) {
   416        for (var i = 0; i < nodes.length; i++) {
   417          frag.appendChild(nodes[i])
   418        }
   419        cb && cb()
   420      }
   421    }
   422  }
   423  
   424  /**
   425   * Check if a node is a DocumentFragment.
   426   *
   427   * @param {Node} node
   428   * @return {Boolean}
   429   */
   430  
   431  export function isFragment (node) {
   432    return node && node.nodeType === 11
   433  }
   434  
   435  /**
   436   * Get outerHTML of elements, taking care
   437   * of SVG elements in IE as well.
   438   *
   439   * @param {Element} el
   440   * @return {String}
   441   */
   442  
   443  export function getOuterHTML (el) {
   444    if (el.outerHTML) {
   445      return el.outerHTML
   446    } else {
   447      var container = document.createElement('div')
   448      container.appendChild(el.cloneNode(true))
   449      return container.innerHTML
   450    }
   451  }