ExtJs源码分析与学习—ExtJs元素Element(四)

元素的操作Ext.DomHelper

 

      该类中的函数主要来简化创建DOM元素操作,采用单例模式实现。主要提供了createHtml和createDom函数。createHtml函数根据配置来创建HTML标签,最终通过innerHTML插入到文档中,二createDom函数根据配置来创建DOM对象,最终通过appendChild或insertBefore函数插入到文档中。下面先看方法createHtml

 

Js代码    收藏代码
  1.     function createHtml(o){  
  2.         var b = '',  
  3.             attr,  
  4.             val,  
  5.             key,  
  6.             cn;  
  7.   
  8.         if(typeof o == "string"){  
  9.             b = o;  
  10.         } else if (Ext.isArray(o)) {  
  11.             for (var i=0; i < o.length; i++) {  
  12.                 if(o[i]) {  
  13.                     b += createHtml(o[i]);  
  14.                 }  
  15.             };  
  16.         } else {  
  17.             b += '<' + (o.tag = o.tag || 'div');  
  18.             for (attr in o) {  
  19.                 val = o[attr];  
  20.                 if(!confRe.test(attr)){  
  21.                     if (typeof val == "object") {  
  22.                         b += ' ' + attr + '="';  
  23.                         for (key in val) {  
  24.                             b += key + ':' + val[key] + ';';  
  25.                         };  
  26.                         b += '"';  
  27.                     }else{  
  28.                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';  
  29.                     }  
  30.                 }  
  31.             };  
  32.             // Now either just close the tag or try to add children and close the tag.  
  33.             if (emptyTags.test(o.tag)) {  
  34.                 b += '/>';  
  35.             } else {  
  36.                 b += '>';  
  37.                 if ((cn = o.children || o.cn)) {  
  38.                     b += createHtml(cn);  
  39.                 } else if(o.html){  
  40.                     b += o.html;  
  41.                 }  
  42.                 b += '</' + o.tag + '>';  
  43.             }  
  44.         }  
  45.         return b;  
  46. }  

     该方法即是内部私有方法,又是类的静态方法(createHtml : createHtml,利用这句把私有方法赋给类的静态方法),可以通过方法 markup返回元素的装饰(markup)

 

Js代码    收藏代码
  1. markup : function(o){  
  2.     return createHtml(o);  
  3. },  

 

     下面详细的讲解一些该方法的内部实现,执行该方法会根据传入参数类型的不同分为三种情况

  • 字符串:直接返回
  • 数组:循环递归调用
  • 对象:处理后转换为html字符串再返回

     前两种情况很简单,以下是其简单例子

 

Js代码    收藏代码
  1. var str = Ext.DomHelper.createHtml('<div>demo1</div>');  
  2. alert(str); // <div>demo1</div>  
  3.   
  4. var str = Ext.DomHelper.createHtml(['<div>demo1</div>','<div>demo2</div>']);  
  5. alert(str); // <div>demo1</div><div>demo2</div>  

 

    这里主要看第三种情况,首先看以下例子

 

Js代码    收藏代码
  1. var spec = {  
  2.     id: 'my-ul',  
  3.     tag: 'ul',  
  4.     cls: 'my-list',  
  5.     style : {width:'20px',height:'30px'},  
  6.     // append children after creating  
  7.     children: [     // may also specify 'cn' instead of 'children'  
  8.         {tag: 'li', id: 'item0', html: 'List Item 0'},  
  9.         {tag: 'li', id: 'item1', html: 'List Item 1'},  
  10.         {tag: 'li', id: 'item2', html: 'List Item 2'}  
  11.     ]  
  12. };  
  13.   
  14. var str = Ext.DomHelper.createHtml(spec);  
  15. alert(str); // <ul id="my-ul" class="my-list" style="width:20px;height:30px;">  
  16. //<li id="item0">List Item 0</li><li id="item1">List Item 1</li><li id="item2">List Item 2</li></ul>  

 

实现代码中
b += '<' + (o.tag = o.tag || 'div');
首先生成父节点,默认为div
if(!confRe.test(attr)){
排除掉这些标签tag|children|cn|html

if (typeof val == "object") {
    b += ' ' + attr + '="';
    for (key in val) {
       b += key + ':' + val[key] + ';';
    };
    b += '"';
}else{
       b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
}
上面的语句分为两种情况,如果val是对象时,比如style : {width:'20px',height:'30px'},会遍历该对象转化为字符串;如果不是对象时,会直接与b连接,注意对html元素的class,for属性做了特殊处理,因为js中class是保留字,for是关键字。

if (emptyTags.test(o.tag)) {
     b += '/>';
}
对于html中单标签(即没有内容的标签),直接结束,比如br、hr

else {
  b += '>';
  if ((cn = o.children || o.cn)) {
     b += createHtml(cn);
  } else if(o.html){
       b += o.html;
  }
   b += '</' + o.tag + '>';
}

如果是children或cn则需要递归遍历孩子节点,如果是html则赋值。
该函数中特殊情况利用正则表达式来实现,这种实现可参考。
createHtml最终返回的是html片段,该片段会通过innerHTML添加到文档中去。

 

    下面看方法

 

Js代码    收藏代码
  1. applyStyles : function(el, styles){  
  2.        if (styles) {  
  3.            var matches;  
  4.   
  5.            el = Ext.fly(el);  
  6.            if (typeof styles == "function") {  
  7.                styles = styles.call();  
  8.            }  
  9.            if (typeof styles == "string") {  
  10.                  
  11.                cssRe.lastIndex = 0;  
  12.                while ((matches = cssRe.exec(styles))) {  
  13.                    el.setStyle(matches[1], matches[2]);  
  14.                }  
  15.            } else if (typeof styles == "object") {  
  16.                el.setStyle(styles);  
  17.            }  
  18.        }  
  19.    },  

      该方法的功能为把指定的样式应用到元素,styles 可以是表示样式的特定格式字符串,如“width:100px”,也可以是对象的形式如{width:"100px"},还可以是能返回这些格式的函数。
      下面看元素插入方法,该类提供了以下插入方法

 

Java代码    收藏代码
  1. insertBefore : function(el, o, returnElement) 在指定元素之前插入新元素  
  2. insertAfter : function(el, o, returnElement) 在指定元素之后插入新元素  
  3. insertFirst : function(el, o, returnElement) 在指定元素内部首位置插入新元素  
  4. append : function(el, o, returnElement) 在指定元素内部尾部插入新元素  
  5. overwrite : function(el, o, returnElement) 创建新的Dom元素并覆盖el的内容  

 

     前四个方法是调用doInsert插入DOM元素,最后一个方法是插入HTML片段。而doInsert调用了关键方法insertHtml,下面看该代码的实现

 

Js代码    收藏代码
  1. insertHtml : function(where, el, html){  
  2.        var hash = {},  
  3.            hashVal,  
  4.            setStart,  
  5.            range,  
  6.            frag,  
  7.            rangeEl,  
  8.            rs;  
  9.   
  10.        where = where.toLowerCase();  
  11.        // add these here because they are used in both branches of the condition.  
  12.        hash[beforebegin] = ['BeforeBegin''previousSibling'];  
  13.        hash[afterend] = ['AfterEnd''nextSibling'];  
  14.   
  15.        if (el.insertAdjacentHTML) {  
  16.            if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){  
  17.                return rs;  
  18.            }  
  19.            // add these two to the hash.  
  20.            hash[afterbegin] = ['AfterBegin''firstChild'];  
  21.            hash[beforeend] = ['BeforeEnd''lastChild'];  
  22.            if ((hashVal = hash[where])) {  
  23.                el.insertAdjacentHTML(hashVal[0], html);  
  24.                return el[hashVal[1]];  
  25.            }  
  26.        } else {  
  27.            range = el.ownerDocument.createRange();  
  28.            setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');  
  29.            if (hash[where]) {  
  30.                range[setStart](el);  
  31.                frag = range.createContextualFragment(html);  
  32.                el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);  
  33.                return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];  
  34.            } else {  
  35.                rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';  
  36.                if (el.firstChild) {  
  37.                    range[setStart](el[rangeEl]);  
  38.                    frag = range.createContextualFragment(html);  
  39.                    if(where == afterbegin){  
  40.                        el.insertBefore(frag, el.firstChild);  
  41.                    }else{  
  42.                        el.appendChild(frag);  
  43.                    }  
  44.                } else {  
  45.                    el.innerHTML = html;  
  46.                }  
  47.                return el[rangeEl];  
  48.            }  
  49.        }  
  50.        throw 'Illegal insertion point -> "' + where + '"';  
  51.    },  

 

     该方法内部分别实现了支持el.insertAdjacentHTML的浏览器和不支持的浏览器,支持el.insertAdjacentHTML的浏览器(IE/Chrome/Safari/Opera)使用el.insertAdjacentHTML。不支持el.insertAdjacentHTML的浏览器(Firefox)使用range.createContextualFragment+el.insertBefore/el.appendChild。对于IE中不支持Table的innerHTML写操作,该方法进行了特殊处理,使用div,把table添加到div中,并返回table,间接实现。下面代码在IE中会报错,连最新的IE9也不支持。

 

Js代码    收藏代码
  1. var table = document.createElement('table');    
  2. table.innerHTML = '<tr><td>Test table innerHTML</td></tr>';  
  3. document.body.appendChild(table);  

 

    再看以下例子

Js代码    收藏代码
  1. <table id='insertTable' border='1'></table>  
  2.     var ieTable = {  
  3.          tag: 'tbody',  
  4.          children: [  
  5.               {tag: 'tr',  
  6.                  children: [  
  7.                    {tag: 'td',html:'Test table innerHTML in IE'},  
  8.                    {tag: 'td',html:'Nasty code for IE is broken table implementation'}  
  9.                  ]  
  10.                              }  
  11.                         ]  
  12.     };  
  13.     var table1 = Ext.get('insertTable');  
  14.     Ext.DomHelper.append(table1,ieTable);  
 

      需要说明一下,在文件DomHelper-more.js中进行了扩展,实际上是对DOM元素的创建采用方法createDom,部分实现调用了createHtml中的方法,也可以利用参数useDom来限制使用createDom。createDom的实现与createHtml类似。

你可能感兴趣的:(html,function,浏览器,table,ExtJs,styles)