| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- import config from '../config'
- import { isIE9 } from './env'
- import { warn } from './debug'
- import { camelize } from './lang'
- import { removeWithTransition } from '../transition/index'
- /**
- * Query an element selector if it's not an element already.
- *
- * @param {String|Element} el
- * @return {Element}
- */
- export function query (el) {
- if (typeof el === 'string') {
- var selector = el
- el = document.querySelector(el)
- if (!el) {
- process.env.NODE_ENV !== 'production' && warn(
- 'Cannot find element: ' + selector
- )
- }
- }
- return el
- }
- /**
- * Check if a node is in the document.
- * Note: document.documentElement.contains should work here
- * but always returns false for comment nodes in phantomjs,
- * making unit tests difficult. This is fixed by doing the
- * contains() check on the node's parentNode instead of
- * the node itself.
- *
- * @param {Node} node
- * @return {Boolean}
- */
- export function inDoc (node) {
- var doc = document.documentElement
- var parent = node && node.parentNode
- return doc === node ||
- doc === parent ||
- !!(parent && parent.nodeType === 1 && (doc.contains(parent)))
- }
- /**
- * Get and remove an attribute from a node.
- *
- * @param {Node} node
- * @param {String} _attr
- */
- export function getAttr (node, _attr) {
- var val = node.getAttribute(_attr)
- if (val !== null) {
- node.removeAttribute(_attr)
- }
- return val
- }
- /**
- * Get an attribute with colon or v-bind: prefix.
- *
- * @param {Node} node
- * @param {String} name
- * @return {String|null}
- */
- export function getBindAttr (node, name) {
- var val = getAttr(node, ':' + name)
- if (val === null) {
- val = getAttr(node, 'v-bind:' + name)
- }
- return val
- }
- /**
- * Insert el before target
- *
- * @param {Element} el
- * @param {Element} target
- */
- export function before (el, target) {
- target.parentNode.insertBefore(el, target)
- }
- /**
- * Insert el after target
- *
- * @param {Element} el
- * @param {Element} target
- */
- export function after (el, target) {
- if (target.nextSibling) {
- before(el, target.nextSibling)
- } else {
- target.parentNode.appendChild(el)
- }
- }
- /**
- * Remove el from DOM
- *
- * @param {Element} el
- */
- export function remove (el) {
- el.parentNode.removeChild(el)
- }
- /**
- * Prepend el to target
- *
- * @param {Element} el
- * @param {Element} target
- */
- export function prepend (el, target) {
- if (target.firstChild) {
- before(el, target.firstChild)
- } else {
- target.appendChild(el)
- }
- }
- /**
- * Replace target with el
- *
- * @param {Element} target
- * @param {Element} el
- */
- export function replace (target, el) {
- var parent = target.parentNode
- if (parent) {
- parent.replaceChild(el, target)
- }
- }
- /**
- * Add event listener shorthand.
- *
- * @param {Element} el
- * @param {String} event
- * @param {Function} cb
- */
- export function on (el, event, cb) {
- el.addEventListener(event, cb)
- }
- /**
- * Remove event listener shorthand.
- *
- * @param {Element} el
- * @param {String} event
- * @param {Function} cb
- */
- export function off (el, event, cb) {
- el.removeEventListener(event, cb)
- }
- /**
- * In IE9, setAttribute('class') will result in empty class
- * if the element also has the :class attribute; However in
- * PhantomJS, setting `className` does not work on SVG elements...
- * So we have to do a conditional check here.
- *
- * @param {Element} el
- * @param {String} cls
- */
- function setClass (el, cls) {
- /* istanbul ignore if */
- if (isIE9 && el.hasOwnProperty('className')) {
- el.className = cls
- } else {
- el.setAttribute('class', cls)
- }
- }
- /**
- * Add class with compatibility for IE & SVG
- *
- * @param {Element} el
- * @param {String} cls
- */
- export function addClass (el, cls) {
- if (el.classList) {
- el.classList.add(cls)
- } else {
- var cur = ' ' + (el.getAttribute('class') || '') + ' '
- if (cur.indexOf(' ' + cls + ' ') < 0) {
- setClass(el, (cur + cls).trim())
- }
- }
- }
- /**
- * Remove class with compatibility for IE & SVG
- *
- * @param {Element} el
- * @param {String} cls
- */
- export function removeClass (el, cls) {
- if (el.classList) {
- el.classList.remove(cls)
- } else {
- var cur = ' ' + (el.getAttribute('class') || '') + ' '
- var tar = ' ' + cls + ' '
- while (cur.indexOf(tar) >= 0) {
- cur = cur.replace(tar, ' ')
- }
- setClass(el, cur.trim())
- }
- if (!el.className) {
- el.removeAttribute('class')
- }
- }
- /**
- * Extract raw content inside an element into a temporary
- * container div
- *
- * @param {Element} el
- * @param {Boolean} asFragment
- * @return {Element}
- */
- export function extractContent (el, asFragment) {
- var child
- var rawContent
- /* istanbul ignore if */
- if (
- isTemplate(el) &&
- el.content instanceof DocumentFragment
- ) {
- el = el.content
- }
- if (el.hasChildNodes()) {
- trimNode(el)
- rawContent = asFragment
- ? document.createDocumentFragment()
- : document.createElement('div')
- /* eslint-disable no-cond-assign */
- while (child = el.firstChild) {
- /* eslint-enable no-cond-assign */
- rawContent.appendChild(child)
- }
- }
- return rawContent
- }
- /**
- * Trim possible empty head/tail textNodes inside a parent.
- *
- * @param {Node} node
- */
- export function trimNode (node) {
- trim(node, node.firstChild)
- trim(node, node.lastChild)
- }
- function trim (parent, node) {
- if (node && node.nodeType === 3 && !node.data.trim()) {
- parent.removeChild(node)
- }
- }
- /**
- * Check if an element is a template tag.
- * Note if the template appears inside an SVG its tagName
- * will be in lowercase.
- *
- * @param {Element} el
- */
- export function isTemplate (el) {
- return el.tagName &&
- el.tagName.toLowerCase() === 'template'
- }
- /**
- * Create an "anchor" for performing dom insertion/removals.
- * This is used in a number of scenarios:
- * - fragment instance
- * - v-html
- * - v-if
- * - v-for
- * - component
- *
- * @param {String} content
- * @param {Boolean} persist - IE trashes empty textNodes on
- * cloneNode(true), so in certain
- * cases the anchor needs to be
- * non-empty to be persisted in
- * templates.
- * @return {Comment|Text}
- */
- export function createAnchor (content, persist) {
- var anchor = config.debug
- ? document.createComment(content)
- : document.createTextNode(persist ? ' ' : '')
- anchor.__vue_anchor = true
- return anchor
- }
- /**
- * Find a component ref attribute that starts with $.
- *
- * @param {Element} node
- * @return {String|undefined}
- */
- var refRE = /^v-ref:/
- export function findRef (node) {
- if (node.hasAttributes()) {
- var attrs = node.attributes
- for (var i = 0, l = attrs.length; i < l; i++) {
- var name = attrs[i].name
- if (refRE.test(name)) {
- return camelize(name.replace(refRE, ''))
- }
- }
- }
- }
- /**
- * Map a function to a range of nodes .
- *
- * @param {Node} node
- * @param {Node} end
- * @param {Function} op
- */
- export function mapNodeRange (node, end, op) {
- var next
- while (node !== end) {
- next = node.nextSibling
- op(node)
- node = next
- }
- op(end)
- }
- /**
- * Remove a range of nodes with transition, store
- * the nodes in a fragment with correct ordering,
- * and call callback when done.
- *
- * @param {Node} start
- * @param {Node} end
- * @param {Vue} vm
- * @param {DocumentFragment} frag
- * @param {Function} cb
- */
- export function removeNodeRange (start, end, vm, frag, cb) {
- var done = false
- var removed = 0
- var nodes = []
- mapNodeRange(start, end, function (node) {
- if (node === end) done = true
- nodes.push(node)
- removeWithTransition(node, vm, onRemoved)
- })
- function onRemoved () {
- removed++
- if (done && removed >= nodes.length) {
- for (var i = 0; i < nodes.length; i++) {
- frag.appendChild(nodes[i])
- }
- cb && cb()
- }
- }
- }
|