all files / vdom/ VElement.js

93.33% Statements 84/90
84.13% Branches 53/63
90.91% Functions 10/11
93.33% Lines 84/90
21 statements, 5 functions, 11 branches Ignored     
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165    12× 12× 12× 12×       2150× 1698× 452× 452×   451×   451×     452×   452× 245× 245×   245×   245×       452× 452× 452×                         19×     447× 412× 489×     447×   452×         110× 110× 110× 83× 83× 83×     110× 110× 110×   106× 106× 106× 100×     106×                           328×                                                      
import { avalon, document, msie } from '../seed/core'
 
export function VElement(type, props, children, isVoidTag) {
    this.nodeName = type
    this.props = props
    this.children = children
    this.isVoidTag = isVoidTag
}
VElement.prototype = {
    constructor: VElement,
    toDOM() {
        if (this.dom)
            return this.dom
        var dom, tagName = this.nodeName
        if (avalon.modern && svgTags[tagName]) {
            dom = createSVG(tagName)
                /* istanbul ignore next*/
        } else Iif (!avalon.modern && (VMLTags[tagName] || rvml.test(tagName))) {
            dom = createVML(tagName)
        } else {
            dom = document.createElement(tagName)
        }
 
        var props = this.props || {}
 
        for (var i in props) {
            var val = props[i]
            Eif (skipFalseAndFunction(val)) {
                /* istanbul ignore if*/
                Iif (specalAttrs[i] && avalon.msie < 8) {
                    specalAttrs[i](dom, val)
                } else {
                    dom.setAttribute(i, val + '')
                }
            }
        }
        var c = this.children || []
        var template = c[0] ? c[0].nodeValue : ''
        switch (this.nodeName) {
            case 'script':
                dom.type = 'noexec'
                 dom.text = template
                 try{
                     dom.innerHTML = template
                 }catch(e){}
                dom.type = props.type || ''
                break
            case 'noscript':
                dom.textContent = template
            case 'style':
            case 'xmp':
            case 'template':
                try {
                    dom.innerHTML = template
                } catch (e) {
                    /* istanbul ignore next*/
                    hackIE(dom, this.nodeName, template)
                }
                break
            case 'option':
                //IE6-8,为option添加文本子节点,不会同步到text属性中
                /* istanbul ignore next */
                Iif (msie < 9)
                    dom.text = template
            default:
                /* istanbul ignore next */
                if (!this.isVoidTag && this.children) {
                    this.children.forEach(el =>
                        c && dom.appendChild(avalon.vdom(c, 'toDOM'))
                    )
                }
                break
        }
        return this.dom = dom
    },
    /* istanbul ignore next */
   
    toHTML() {
        var arr = []
        var props = this.props || {}
        for (var i in props) {
            var val = props[i]
            Eif (skipFalseAndFunction(val)) {
                arr.push(i + '=' + avalon.quote(props[i] + ''))
            }
        }
        arr = arr.length ? ' ' + arr.join(' ') : ''
        var str = '<' + this.nodeName + arr
        if (this.isVoidTag) {
            return str + '/>'
        }
        str += '>'
        Eif (this.children) {
            str += this.children.map(
                el => (el ? avalon.vdom(el, 'toHTML') : '')
            ).join('')
        }
        return str + '</' + this.nodeName + '>'
    }
}
 function hackIE(dom, nodeName, template) {
        switch (nodeName) {
            case 'style':
                dom.setAttribute('type', 'text/css')
                dom.styleSheet.cssText = template
                break
            case 'xmp': //IE6-8,XMP元素里面只能有文本节点,不能使用innerHTML
            case 'noscript':
                dom.textContent = template
                break
        }
    }
function skipFalseAndFunction(a) {
    return a !== false && (Object(a) !== a)
}
/* istanbul ignore next */
var specalAttrs = {
    "class": function(dom, val) {
        dom.className = val
    },
    style: function(dom, val) {
        dom.style.cssText = val
    },
    type: function(dom, val) {
        try { //textarea,button 元素在IE6,7设置 type 属性会抛错
            dom.type = val
        } catch (e) {}
    },
    'for': function(dom, val) {
        dom.setAttribute('for', val)
        dom.htmlFor = val
    }
}
 
function createSVG(type) {
    return document.createElementNS('http://www.w3.org/2000/svg', type)
}
var svgTags = avalon.oneObject('circle,defs,ellipse,image,line,' +
    'path,polygon,polyline,rect,symbol,text,use,g,svg')
 
var rvml = /^\w+\:\w+/
    /* istanbul ignore next*/
function createVML(type) {
    if (document.styleSheets.length < 31) {
        document.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
    } else {
        // no more room, add to the existing one
        // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
        document.styleSheets[0].addRule(".rvml", "behavior:url(#default#VML)");
    }
    var arr = type.split(':')
    if (arr.length === 1) {
        arr.unshift('v')
    }
    var tag = arr[1]
    var ns = arr[0]
    if (!document.namespaces[ns]) {
        document.namespaces.add(ns, "urn:schemas-microsoft-com:vml")
    }
    return document.createElement('<' + ns + ':' + tag + ' class="rvml">');
}
 
var VMLTags = avalon.oneObject('shape,line,polyline,rect,roundrect,oval,arc,' +
    'curve,background,image,shapetype,group,fill,' +
    'stroke,shadow, extrusion, textbox, imagedata, textpath')