`
jljlpch
  • 浏览: 319366 次
  • 性别: Icon_minigender_1
  • 来自: 南昌
社区版块
存档分类
最新评论

DomHelper源码分析

    博客分类:
  • Ext
阅读更多
Ext.DomHelper = function(){
    var tempTableEl = null;
    var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
    var tableRe = /^table|tbody|tr|td$/i;
    
    // build as innerHTML where available
    var createHtml = function(o){
    	
    	//如果是string,直接返回
        if(typeof o == 'string'){
            return o;
        }
        //如果是数组,逐个递归createHtml,串联起来返回。
        var b = "";
        if (Ext.isArray(o)) {
            for (var i = 0, l = o.length; i < l; i++) {
                b += createHtml(o[i]);
            }
            return b;
        }
        //是object,默认的tag:div.
        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;
            
            //处理style 属性
            if(attr == "style"){
                var s = o["style"];
                //如style是函数,就执行取得返回string
                if(typeof s == "function"){
                    s = s.call();
                }
                //如style是string
                if(typeof s == "string"){
                    b += ' style="' + s + '"';
                }
                //如style是object {height:50,width:30}之类的style的属性
                else if(typeof s == "object"){
                    b += ' style="';
                    for(var key in s){
                        if(typeof s[key] != "function"){
                            b += key + ":" + s[key] + ";";
                        }
                    }
                    b += '"';
                }
            }else{
            	//处理cls属性,即class
                if(attr == "cls"){
                    b += ' class="' + o["cls"] + '"';
                }
                //for属性
                else if(attr == "htmlFor"){
                    b += ' for="' + o["htmlFor"] + '"';
                }else{
                	//其它的属性pass to 标签属性中去
                    b += " " + attr + '="' + o[attr] + '"';
                }
            }
        }
        //对于没有内容的标签,如<hr/>
        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 += "</" + o.tag + ">";
        }
        return b;
    };

    // build as dom
    /** @ignore */
    var createDom = function(o, parentNode){
        var el;
        //o是数组 Allow Arrays of siblings to be inserted
        if (Ext.isArray(o)) { 
        	// in one shot using a DocumentFragment
            el = document.createDocumentFragment(); 
            //创建一组兄弟节点
            for(var i = 0, l = o.length; i < l; i++) {
                createDom(o[i], el);
            }
        }
        //o 是string  // Allow a string as a child spec.
        else if (typeof o == "string)") {        
            el = document.createTextNode(o);//创建文本节点
        } 
        //o是object
        else {
            el = document.createElement(o.tag||'div');
            // In IE some elements don't have setAttribute
            var useSet = !!el.setAttribute; 
            for(var attr in o){
                if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || attr == "style" || typeof o[attr] == "function") continue;
                //class属性
                if(attr=="cls"){
                    el.className = o["cls"];
                }else{
                	//为dom set 属性
                    if(useSet) el.setAttribute(attr, o[attr]);
                    else el[attr] = o[attr];
                }
            }
            //set Style属性
            Ext.DomHelper.applyStyles(el, o.style);
           
            //create 子节点
            var cn = o.children || o.cn;
            if(cn){
                createDom(cn, el);
            } else if(o.html){
                el.innerHTML = o.html;
            }
        }
        //加到parentNode中
        if(parentNode){
           parentNode.appendChild(el);
        }
        return el;
    };

    //处理IE table的兼容
    //把<table>html</table>、<table><tbody>html</tbody></table>
    //<table><tbody><tr>html></tr></tbody></table>
    //s:start,e:end,h:html
    //<div><table><tbody><tr><td>html</td></tr></tbody></table></div>
    //4:<td>html</td>  3:<tr><td>html</td></tr>    2:<tbody><tr><td>html</td></tr></tbody>
    var ieTable = function(depth, s, h, e){
    	//table EL
        tempTableEl.innerHTML = [s, h, e].join('');
        var i = -1, el = tempTableEl;
        while(++i < depth){
            el = el.firstChild;
        }
        return el;
    };

    // kill repeat to save bytes
    var ts = '<table>',
        te = '</table>',
        tbs = ts+'<tbody>',
        tbe = '</tbody>'+te,
        trs = tbs + '<tr>',
        tre = '</tr>'+tbe;

    /**
     * @ignore
     * Nasty code for IE's broken table implementation
     */
    var insertIntoTable = function(tag, where, el, html){
       //创建tempTableEl
    	if(!tempTableEl){
            tempTableEl = document.createElement('div');
        }
        var node;//插入的元素
        var before = null;//定义插入的位置,在before这个节点之前插入
        if(tag == 'td'){//td
        	//在td内,不需要特殊处理
            if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
                return;
            }
            //在td前,该节点之前插入
            if(where == 'beforebegin'){
                before = el;
                el = el.parentNode;
            }
            //在td后,该节点之后插入
            else{
                before = el.nextSibling;
                el = el.parentNode;
            }
            //node是<td>html</td>
            node = ieTable(4, trs, html, tre);
        }
        else if(tag == 'tr'){//tr
        	//tr前
            if(where == 'beforebegin'){
                before = el;
                el = el.parentNode;
                //node:<tr><td>html</td></tr>
                node = ieTable(3, tbs, html, tbe);
            } 
            //tr后
            else if(where == 'afterend'){
                before = el.nextSibling;
                el = el.parentNode;
                  //node:<tr><td>html</td></tr>
                node = ieTable(3, tbs, html, tbe);
            }
            //tr内
            else{ // INTO a TR
                if(where == 'afterbegin'){
                    before = el.firstChild;
                }
                //node是<td>html</td
                node = ieTable(4, trs, html, tre);
            }
        } else if(tag == 'tbody'){//tbody
        	//tbody前
            if(where == 'beforebegin'){
                before = el;
                el = el.parentNode;
                //node是<tbody><tr><td>html</td></tr></tbody>
                node = ieTable(2, ts, html, te);
            } 
            //tbody后
            else if(where == 'afterend'){
                before = el.nextSibling;
                el = el.parentNode;
                //node是<tbody><tr><td>html</td></tr></tbody>
                node = ieTable(2, ts, html, te);
            } else{
                if(where == 'afterbegin'){
                    before = el.firstChild;
                }
                 //node:<tr><td>html</td></tr>
                node = ieTable(3, tbs, html, tbe);
            }
        } else{ // TABLE
        	//不需要特殊处理
            if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
                return;
            }
            if(where == 'afterbegin'){
                before = el.firstChild;
            }
            //node是<tbody><tr><td>html</td></tr></tbody>
            node = ieTable(2, ts, html, te);
        }
        //el子节点before前插入node节点
        el.insertBefore(node, before);
        return node;
    };


    return {
    /** True to force the use of DOM instead of html fragments @type Boolean */
    useDom : false,

    /**
     * Returns the markup for the passed Element(s) config.
     * @param {Object} o The DOM object spec (and children)
     * @return {String}
     */
    //得到html标签的string
    markup : function(o){
        return createHtml(o);
    },

    /**
     * Applies a style specification to an element.
     * @param {String/HTMLElement} el The element to apply styles to
     * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
     * a function which returns such a specification.
     */
    //为元素增加style,style可能是string,objcet,function。
    applyStyles : function(el, styles){
        if(styles){
           el = Ext.fly(el);
           //styles是string
           if(typeof styles == "string"){
           	//height:50px; width:30px;
               var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
               var matches;
               //set Style
               while ((matches = re.exec(styles)) != null){
                   el.setStyle(matches[1], matches[2]);
               }
           }
           //styles是object
           else if (typeof styles == "object"){
           	//set style
               for (var style in styles){
                  el.setStyle(style, styles[style]);
               }
           }
          //style是 function
           else if (typeof styles == "function"){
           	//styles.call() 可能返回string,object
                Ext.DomHelper.applyStyles(el, styles.call());
           }
        }
    },

    /**
     * Inserts an HTML fragment into the DOM.
     * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
     * @param {HTMLElement} el The context element
     * @param {String} html The HTML fragmenet
     * @return {HTMLElement} The new node
     */
    insertHtml : function(where, el, html){
        where = where.toLowerCase();
        if(el.insertAdjacentHTML){//ie
        	//insert table
            if(tableRe.test(el.tagName)){
                var rs;
                //如果是table前,后,或td之内,由于返回null.所以就不会执行 return rs;
                if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
                    return rs;
                }
            }
            //在对应的位置插入html,返回插入的元素
            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 + '"';
        }
        //其它浏览器
        //先创建元素Dom range对象
        var range = el.ownerDocument.createRange();
        var frag;
        switch(where){
             case "beforebegin":
             //设定range 开始的位置,在 el之前,
                range.setStartBefore(el);
                //不能直接插入html string,要先生成上下文相关的Fragment
                frag = range.createContextualFragment(html);
                //插入
                el.parentNode.insertBefore(frag, el);
                return el.previousSibling;
             case "afterbegin":
               //有元素
                if(el.firstChild){
                	//设定range 开始的位置 ,在el firstChild之前
                	//为insertBefore定位
                    range.setStartBefore(el.firstChild);
                    frag = range.createContextualFragment(html);
                    el.insertBefore(frag, el.firstChild);
                    return el.firstChild;
                }else{
                	//直接用innerHTML
                    el.innerHTML = html;
                    return el.firstChild;
                }
            case "beforeend":
                //有元素
                if(el.lastChild){
                	//设定range 开始的位置,在 el firstChild之后                
                    range.setStartAfter(el.lastChild);
                    frag = range.createContextualFragment(html);
                    el.appendChild(frag);
                    
                    return el.lastChild;
                }else{
                	//直接用innerHTML
                    el.innerHTML = html;
                    return el.lastChild;
                }
            case "afterend":
                //设定range开始的位置,在 el之后
                range.setStartAfter(el);
                frag = range.createContextualFragment(html);
                el.parentNode.insertBefore(frag, el.nextSibling);
                return el.nextSibling;
            }
            throw 'Illegal insertion point -> "' + where + '"';
    },

    /**
     * Creates new DOM element(s) and inserts them before el.
     * @param {Mixed} el The context element
     * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
     * @param {Boolean} returnElement (optional) true to return a Ext.Element
     * @return {HTMLElement/Ext.Element} The new node
     */
    insertBefore : function(el, o, returnElement){
        return this.doInsert(el, o, returnElement, "beforeBegin");
    },

    /**
     * Creates new DOM element(s) and inserts them after el.
     * @param {Mixed} el The context element
     * @param {Object} o The DOM object spec (and children)
     * @param {Boolean} returnElement (optional) true to return a Ext.Element
     * @return {HTMLElement/Ext.Element} The new node
     */
    insertAfter : function(el, o, returnElement){
        return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
    },

    /**
     * Creates new DOM element(s) and inserts them as the first child of el.
     * @param {Mixed} el The context element
     * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
     * @param {Boolean} returnElement (optional) true to return a Ext.Element
     * @return {HTMLElement/Ext.Element} The new node
     */
    insertFirst : function(el, o, returnElement){
        return this.doInsert(el, o, returnElement, "afterBegin", "firstChild");
    },

    // private
    doInsert : function(el, o, returnElement, pos, sibling){
        el = Ext.getDom(el);
        var newNode;
        if(this.useDom){
        	//创建Dom
            newNode = createDom(o, null);
            //在指定的地方插入newNode
            (sibling === "firstChild" ? el : el.parentNode).insertBefore(newNode, sibling ? el[sibling] : el);
        }else{
            var html = createHtml(o);
            newNode = this.insertHtml(pos, el, html);
        }
        return returnElement ? Ext.get(newNode, true) : newNode;
    },

    /**
     * Creates new DOM element(s) and appends them to el.
     * @param {Mixed} el The context element
     * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
     * @param {Boolean} returnElement (optional) true to return a Ext.Element
     * @return {HTMLElement/Ext.Element} The new node
     */
    append : function(el, o, returnElement){
        el = Ext.getDom(el);
        var newNode;
        if(this.useDom){
            newNode = createDom(o, null);
            el.appendChild(newNode);
        }else{
            var html = createHtml(o);
            newNode = this.insertHtml("beforeEnd", el, html);
        }
        return returnElement ? Ext.get(newNode, true) : newNode;
    },

    /**
     * Creates new DOM element(s) and overwrites the contents of el with them.
     * @param {Mixed} el The context element
     * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
     * @param {Boolean} returnElement (optional) true to return a Ext.Element
     * @return {HTMLElement/Ext.Element} The new node
     */
    overwrite : function(el, o, returnElement){
        el = Ext.getDom(el);
        //采用innerHTML
        el.innerHTML = createHtml(o);
        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
    },

    /**
     * Creates a new Ext.Template from the DOM object spec.
     * @param {Object} o The DOM object spec (and children)
     * @return {Ext.Template} The new template
     */
    createTemplate : function(o){
        var html = createHtml(o);
        return new Ext.Template(html);
    }
    };
}();

 

分享到:
评论

相关推荐

    掏钱学Ext(完整版) 附全部源码

    8.3.1. DomHelper用来生成小片段 8.3.2. 批量生成还是需要Template模板 9. 沉寂吧!我们要自己的控件。 9.1. 下拉树形选择框TreeField 9.2. 带全选的checkbox树形CheckBoxTree 9.3. 带全选的checkbox的grid ...

    ext 中文 api

    API 参考 API 参考里面详细描述了所有能在 Ext 类库里面找到的类和组件。最常用的类有: Ext.Element Ext.BorderLayout Ext.DomHelper Ext.TabPanel Ext.UpdateManager

    Ext grid To Excel

    fd=Ext.DomHelper.append(Ext.getBody(),{tag:'form',method:'post',id:'frmDummy',action:'exportexcel.jsp', target:'_blank',name:'frmDummy',cls:'x-hidden',cn:[ {tag:'input',name:'exportContent',id:'...

    ext JS API 实战

    其它控件都是建立在这些底层api的基础上,底层api位于源代码目录的core子目录中,包括DomHelper.js、Element.js等文件,如图xx所示。 控件(widgets):控件是指可以直接在页面中创建的可视化组件,比如面板、...

    ExtJs学习笔记,共30讲

    ExtJs学习笔记,共30讲 1. ExtJs 结构树 2 2. 对ExtJs的态度 3 3. Ext.form概述 4 4. Ext.TabPanel篇 5 5. Function扩展篇 7 ...27. extJs 2.0学习笔记(DomHelper.js篇) 76 28. extJs 2.0学习笔记(ext.js篇) 77

    extJs 2.1学习笔记

    extJs 2.1学习笔记 此资料收集于网上.. 1. ExtJs 结构树 2 2. 对ExtJs的态度 3 3. Ext.form概述 4 4. Ext.TabPanel篇 5 ...27. extJs 2.0学习笔记(DomHelper.js篇) 76 28. extJs 2.0学习笔记(ext.js篇) 77

    esperanto-problem:说明世界语 CLI 问题的回购

    世界语问题说明世界语 CLI 问题的回购。 运行esperanto -b -i htmlbars-runtime.js -o htmlbars-runtime-bundle.js --strict 查看runtime-bundle文件。 在底部注意以下代码行: ...__export ( 'DOMHelper' , function

    Sencha Touch权威指南

    XTemplate模板、Domhelper组件、DataView组件、List组件、Sheet组件使用详解;地图与多媒体,对Map组件、Video组件和Audio组件进行了详尽的讲解;具有关联关系的模型,详细讲解了如何定义一对多、多对一和一对一的...

    ExtJS 2.0实用简明教程 之Ext类库简介

    其它控件都是建立在这些底层api的基础上,底层api位于源代码目录的core子目录中,包括DomHelper.js、Element.js等文件,如图xx所示。   控件(widgets):控件是指可以直接在页面中创建的可视化组件,比如面板、选项...

    EXTJS总结.txt

    可以是插入一个元素,也可以是创建一个元素(要创建的话请使用“DomHelper配置项对象”作为参数传入),总之,这个元素作为当前元素的第一个子元素出现。 var el = Ext.get('elId1'); // 插入的dom节点作为第一个...

    Ext深入浅出 数据传输

    11.2.1 用DomHelper生成小片段..272 11.2.2 Ext.DomHelper. applyStyles函数.............275 11.2.3 Template模板....................276 11.2.4 Ext.DomHelper. createTemplate函数......278 11.2.5 复杂模板...

    ExtJSWeb应用程序开发指南(第2版)

    6.3.2 Ext.core.DomHelper.applyStyles() 6.3.3 createTemplate() 6.3.4 insertAfter() 6.3.5 insertBefore() 6.3.6 insertFirst() 6.3.7 insertHtml() 6.3.8 overwrite() 6.4 Ext.core....

    ExtJS入门教程(超级详细)

    9、Ext.DomHelper类 …………………… 14 10、Ext.Template类 …………………… 14 11、Ext.EventManager类 ……………… 15 12、Ext.EventObject类 ………………… 15 13、Ext.CompositeElement类 ………… 16 14、...

    Ext 开发指南 学习资料

    8.3.1. DomHelper用来生成小片段 8.3.2. 批量生成还是需要Template模板 8.3.3. 醍醐灌顶,功能强劲的模板引擎XTemplate。 8.4. Ext.data命名空间 8.4.1. proxy系列 8.4.1.1. 人畜无害MemoryProxy 8.4.1.2. 常规武器...

    EXT核心API详解

    9、Ext.DomHelper类 …………………… 14 10、Ext.Template类 …………………… 14 11、Ext.EventManager类 ……………… 15 12、Ext.EventObject类 ………………… 15 13、Ext.CompositeElement类 ………… 16 14、...

    EXT教程EXT用大量的实例演示Ext实例

    8.3.1. DomHelper用来生成小片段 8.3.2. 批量生成还是需要Template模板 8.4. Ext.data命名空间 8.4.1. proxy系列 8.4.1.1. 人畜无害的MemoryProxy 8.4.1.2. 常规武器HttpProxy 8.4.1.3. 洲际导弹...

    EXT2.0中文教程

    8.3.1. DomHelper用来生成小片段 8.3.2. 批量生成还是需要Template模板 8.4. Ext.data命名空间 8.4.1. proxy系列 8.4.1.1. 人畜无害的MemoryProxy 8.4.1.2. 常规武器HttpProxy 8.4.1.3. 洲际导弹ScriptTagProxy ...

    轻松搞定Extjs_原创

    二、Ext.DomHelper类 36 三、Ext.XTemplate 38 四、小结 39 第七章:格式化 40 一、用户需要优秀体验的内容 40 二、Ext.util.Format类 40 三、再谈XTemplete 44 四、如果连Format都不能满足XTemplete的需要呢? 45 ...

    精通JS脚本之ExtJS框架.part2.rar

    6.3.6 DomHelper简介 6.4 DomQuery入门 6.4.1 元素选择符Selector 6.4.2 属性选择符Attributes Selectors 6.4.3 CSS值元素选择符 6.4.4 Ext.query与Ext.select 6.5 应用模板 6.5.1 Ext.Template 6.5.2 Ext....

Global site tag (gtag.js) - Google Analytics