Ext源码解析:3, DomHelper.js

阅读更多
from http://www.beyondrails.com/blogs/21

Ext的DomHelper主要是定义了一些操作Dom元素的Helper方法:
insertBefore
insertAfter
insertFirst
append
overwrite
insertHtml
applyStyles


Ext支持纯HTML或者数组或一个JavaScript对象来描述用来添加或覆盖的元素,底层实现为私有的createHtml方法:
var createHtml = function(o){
    if(typeof o == 'string'){
        return o;
    }
    var b = "";
    if (Ext.isArray(o)) {
        for (var i = 0, l = o.length; i < l; i++) {
            b += createHtml(o[i]);
        }
        return b;
    }
    if(!o.tag){
        o.tag = "div";
    }
    b += "<" + o.tag;
    for(var attr in o){
        if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
        if(attr == "style"){
            var s = o["style"];
            if(typeof s == "function"){
                s = s.call();
            }
            if(typeof s == "string"){
                b += ' style="' + s + '"';
            }else if(typeof s == "object"){
                b += ' style="';
                for(var key in s){
                    if(typeof s[key] != "function"){
                        b += key + ":" + s[key] + ";";
                    }
                }
                b += '"';
            }
        }else{
            if(attr == "cls"){
                b += ' class="' + o["cls"] + '"';
            }else if(attr == "htmlFor"){
                b += ' for="' + o["htmlFor"] + '"';
            }else{
                b += " " + attr + '="' + o[attr] + '"';
            }
        }
    }
    if(emptyTags.test(o.tag)){
        b += "/>";
    }else{
        b += ">";
        var cn = o.children || o.cn;
        if(cn){
            b += createHtml(cn);
        } else if(o.html){
            b += o.html;
        }
        b += "";
    }
    return b;
}

可以看到,
如果参数是String则表示是html,则直接返回;
如果参数是Array则为每个数组元素调用createHtml
如果参数是Object则根据属性来拼接html字符串

其中insertBefore、insertAfter、insertFirst、append都会调用insertHtml方法:
insertHtml : function(where, el, html){
    where = where.toLowerCase();
    if(el.insertAdjacentHTML){
        if(tableRe.test(el.tagName)){
            var rs;
            if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
                return rs;
            }
        }
        switch(where){
            case "beforebegin":
                el.insertAdjacentHTML('BeforeBegin', html);
                return el.previousSibling;
            case "afterbegin":
                el.insertAdjacentHTML('AfterBegin', html);
                return el.firstChild;
            case "beforeend":
                el.insertAdjacentHTML('BeforeEnd', html);
                return el.lastChild;
            case "afterend":
                el.insertAdjacentHTML('AfterEnd', html);
                return el.nextSibling;
        }
        throw 'Illegal insertion point -> "' + where + '"';
    }
    var range = el.ownerDocument.createRange();
    var frag;
    switch(where){
         case "beforebegin":
            range.setStartBefore(el);
            frag = range.createContextualFragment(html);
            el.parentNode.insertBefore(frag, el);
            return el.previousSibling;
         case "afterbegin":
            if(el.firstChild){
                range.setStartBefore(el.firstChild);
                frag = range.createContextualFragment(html);
                el.insertBefore(frag, el.firstChild);
                return el.firstChild;
            }else{
                el.innerHTML = html;
                return el.firstChild;
            }
        case "beforeend":
            if(el.lastChild){
                range.setStartAfter(el.lastChild);
                frag = range.createContextualFragment(html);
                el.appendChild(frag);
                return el.lastChild;
            }else{
                el.innerHTML = html;
                return el.lastChild;
            }
        case "afterend":
            range.setStartAfter(el);
            frag = range.createContextualFragment(html);
            el.parentNode.insertBefore(frag, el.nextSibling);
            return el.nextSibling;
        }
        throw 'Illegal insertion point -> "' + where + '"';
}

insertHtml方法则先尝试调用insertAdjacentHTML,但由于insertAdjacentHTML只支持IE,所以后面又对其他浏览器做了相应的alternative,模拟IE下的insertAdjacentHTML方法
基本思路是使用createRange来创建一个Range对象,并通过调用setStartBefore或setStartAfter来设置Range相对于其他Node的位置,最后调用createContextualFragment返回一个Dom片段,然后调用insertBefore或appendChild来完成插入html
具体参考 Mozilla Developer Center

overwrite方法则实际上是替换Dom元素的innerHTML,而不是顾名思义的“覆盖”
overwrite : function(el, o, returnElement){
    el = Ext.getDom(el);
    el.innerHTML = createHtml(o);
    return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
}

你可能感兴趣的:(EXT,HTML,IE,JavaScript,浏览器)