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

从这一节开始分析ExtJs对元素(Element)的封装与扩展,首先看Ext.lib.Dom

 

类Ext.lib.Dom

 

      该类源代码对应的文件为ext-base-dom.js。Ext.lib.Dom主要实现了对document中元素部分方法的兼容性实现。在前面事件(Ext.EventManager)的讲解中已经用到了该类。
      该类的实现采用了匿名闭包自执行函数实现,执行完该函数,把封装好的对象赋给了对象Ext.lib.Dom,实现了对该类的封装,这种实现的好处把不需要暴露的变量封装到闭包中,同时这些变量的作用域随Ext.lib.Dom自始自终,而不是调用后立马回收。援引别人写的一段话“严格意义上讲任何一个function在执行时就构成一个闭包,闭包的实质是作用域。普通的function,内部声明的变量在执行完会全被回收掉,这时闭包也被回收了,所以这种闭包对我们没有用处,他只是个作用域。如果一个function的局部变量在执行时被生命周期更长的变量引用,那么这个function执行完时就不能回收掉这个局部变量,这个局部变量的生命周期超出了他的作用域,这时的作用域也不能被回收掉,就形成了典型的闭包。闭包的作用就是使局部变量拥有更大的生命周期,甚至全局的生命周期,这使得闭包可以保存function执行时的状态,特别是那种function中又返回一个function时,被返回的function就可以访问父function执行时的所有局部变量(典型的带状态函数)。因为JS中回收一个变量不是看作用域是否结束,而是看引用数。”

 

      先看Ext.lib.Dom一些变量的声明

 

Js代码    收藏代码
  1. var doc = document,  
  2.       isCSS1 = doc.compatMode == "CSS1Compat",  
  3.       MAX = Math.max,         
  4.       ROUND = Math.round,  
  5.       PARSEINT = parseInt;  
 

      这些变量的声明一是全局管理,二是可以提高js文件代码的压缩率,http://yui.2clics.net/    可以在线压缩js文件。
isCSS1用来判断浏览器的文档模式(doctype),true为标准模式,false为怪异模式。在Ext类中用Ext.isStrict来判断,这里采用isCSS1,实现的功能是一样的。
      下面看Ext.lib.Dom中方法的定义,首先看方法isAncestor

 

Js代码    收藏代码
  1.             isAncestor : function(p, c) {  
  2.     var ret = false;  
  3.       
  4.     p = Ext.getDom(p);  
  5.     c = Ext.getDom(c);  
  6.     if (p && c) {  
  7.         if (p.contains) {  
  8.             return p.contains(c);  
  9.         } else if (p.compareDocumentPosition) {  
  10.             return !!(p.compareDocumentPosition(c) & 16);  
  11.         } else {  
  12.             while (c = c.parentNode) {  
  13.                 ret = c == p || ret;  
  14.             }  
  15.         }  
  16.     }  
  17.     return ret;  
  18. },  
 

      该方法的功能为判断c是否是p的子元素,并且实现了各浏览器的兼容contains和compareDocumentPosition,关于这两个方法的讲解,参照 javascript contains和compareDocumentPosition 方法来确定是否HTML节点 。在ext-base-event.js  Ext.lib.EventObject 中有类似实现elContains。

     接下来是返回文档和页面视图高宽,代码如下:

 

Js代码    收藏代码
  1.       /** 
  2. * 如果full为真返回页面的实际宽度,否则返回可视宽度 
  3. * 实际宽度指整个页面的宽度,包括滚动条看不到的区域,而可视宽度指当前可以看到的宽度 
  4. */  
  5.       getViewWidth : function(full) {  
  6.           return full ? this.getDocumentWidth() : this.getViewportWidth();  
  7.       },  
  8.   
  9.       /** 
  10.        * 如果full为真返回页面的实际高度,否则返回可视高度 
  11.        */  
  12.       getViewHeight : function(full) {  
  13.           return full ? this.getDocumentHeight() : this.getViewportHeight();  
  14.       },  
  15.   
  16.       /** 
  17.        * 得到页面的实际高度 
  18.        */  
  19.       getDocumentHeight: function() {              
  20.           return MAX(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, this.getViewportHeight());  
  21.       },  
  22.   
  23.       /** 
  24.        * 得到页面的实际宽度 
  25.        */  
  26.       getDocumentWidth: function() {              
  27.           return MAX(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, this.getViewportWidth());  
  28.       },  
  29.   
  30.       /** 
  31.        * 得到页面的可视高度 
  32.        */  
  33.       getViewportHeight: function(){  
  34.        return Ext.isIE ?   
  35.            (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :  
  36.            self.innerHeight;  
  37.       },  
  38.   
  39.       /** 
  40.        * 得到页面的可视宽度 
  41.        */  
  42.       getViewportWidth : function() {  
  43.        return !Ext.isStrict && !Ext.isOpera ? doc.body.clientWidth :  
  44.            Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;  
  45.       },  

      这一组方法可以分为两类,返回页面的实际高宽度和返回页面的可视宽度,当出现滚动条时,实际高宽度会大于可视高宽度,方法处理了不同浏览器之间的兼容。关于效果请看以下例子

 

Html代码    收藏代码
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
  2.      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  3. <html xmlns="http://www.w3.org/1999/xhtml" lang="zh-CN">  
  4.     <head>  
  5.         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  6.         <title>Ext中getDocumentWidth与getViewportWidth的区别</title>  
  7.         <link rel="stylesheet" type="text/css"  
  8.             href="../ext-3.3.1/resources/css/ext-all.css" />  
  9.         <script type="text/javascript"  
  10.             src="../ext-3.3.1/adapter/ext/ext-base-debug.js"></script>  
  11.         <script type="text/javascript"  
  12.             src="../ext-3.3.1/ext-all-debug-w-comments.js"></script>  
  13.         <script type="text/javascript"  
  14.             src="../ext-3.3.1/src/locale/ext-lang-zh_CN.js"></script>  
  15.         <script type="text/javascript" src="../ext-3.3.1/src/debug.js"></script>  
  16.         <script type="text/javascript">  
  17.                 Ext.onReady(function() {  
  18.                     Ext.BLANK_IMAGE_URL = '../ext-3.3.1/resources/images/default/s.gif';  
  19.                     Ext.QuickTips.init();  
  20.                     var dom = Ext.lib.Dom;  
  21.                     alert("页面的实际宽度:"+dom.getDocumentWidth());  
  22.                     alert("页面的可视宽度:"+dom.getViewportWidth());  
  23.                 });  
  24.         </script>  
  25.     </head>  
  26.     <body>  
  27.     <div style="width:2000px;">  
  28.      Ext中getDocumentWidth与getViewportWidth的区别Ext中getDocumentWidth与getViewportWidth的区别Ext中getDocumentWidth与getViewportWidth的区别  
  29.      Ext中getDocumentWidth与getViewportWidth的区别  
  30.     </div>  
  31.     </body>  
  32. </html>  

 接下来的方法是获取元素相对于文档的位置

 

Js代码    收藏代码
  1. /** 
  2.          * 得到给定元素的left 
  3.          */  
  4.         getX : function(el) {  
  5.             return this.getXY(el)[0];  
  6.         },  
  7.   
  8.         /** 
  9.          * 得到给定元素的[top,left] 
  10.          */  
  11.         getXY : function(el) {  
  12.             var p,   
  13.                 pe,   
  14.                 b,  
  15.                 bt,   
  16.                 bl,       
  17.                 dbd,          
  18.                 x = 0,  
  19.                 y = 0,   
  20.                 scroll,  
  21.                 hasAbsolute,   
  22.                 bd = (doc.body || doc.documentElement),  
  23.                 ret = [0,0];  
  24.                   
  25.             el = Ext.getDom(el);  
  26.   
  27.             if(el != bd){  
  28.                 if (el.getBoundingClientRect) {  
  29.                     b = el.getBoundingClientRect();  
  30.                     scroll = fly(document).getScroll();  
  31.                     ret = [ROUND(b.left + scroll.left), ROUND(b.top + scroll.top)];  
  32.                 } else {//不支持getBoundingClientRect,实现起来比较啰嗦,得循环获得元素在页面中的绝对位置  
  33.                     p = el;       
  34.                     hasAbsolute = fly(el).isStyle("position""absolute");  
  35.           
  36.                     while (p) {  
  37.                         pe = fly(p);          
  38.                         x += p.offsetLeft;  
  39.                         y += p.offsetTop;  
  40.           
  41.                         hasAbsolute = hasAbsolute || pe.isStyle("position""absolute");  
  42.                                   
  43.                         if (Ext.isGecko) {                            
  44.                             y += bt = PARSEINT(pe.getStyle("borderTopWidth"), 10) || 0;  
  45.                             x += bl = PARSEINT(pe.getStyle("borderLeftWidth"), 10) || 0;      
  46.           
  47.                             if (p != el && !pe.isStyle('overflow','visible')) {  
  48.                                 x += bl;  
  49.                                 y += bt;  
  50.                             }  
  51.                         }  
  52.                         p = p.offsetParent;  
  53.                     }  
  54.           
  55.                     if (Ext.isSafari && hasAbsolute) {  
  56.                         x -= bd.offsetLeft;  
  57.                         y -= bd.offsetTop;  
  58.                     }  
  59.           
  60.                     if (Ext.isGecko && !hasAbsolute) {  
  61.                         dbd = fly(bd);  
  62.                         x += PARSEINT(dbd.getStyle("borderLeftWidth"), 10) || 0;  
  63.                         y += PARSEINT(dbd.getStyle("borderTopWidth"), 10) || 0;  
  64.                     }  
  65.           
  66.                     p = el.parentNode;  
  67.                     while (p && p != bd) {  
  68.                         if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display""inline"))) {  
  69.                             x -= p.scrollLeft;  
  70.                             y -= p.scrollTop;  
  71.                         }  
  72.                         p = p.parentNode;  
  73.                     }  
  74.                     ret = [x,y];  
  75.                 }  
  76.             }  
  77.             return ret;  
  78.         },  

 

      这里需要说明一下关于方法el.getBoundingClientRect,该方法获得页面中某个元素的左、上、右和下分别相对浏览器视窗的位置。该方法已经不再是IE Only了,FF3.0+和Opera9.5+已经支持了该方法,可以说在获得页面元素位置上效率能有很大的提高,在以前版本的Opera和Firefox中必须通过循环来获得元素在页面中的绝对位置。见代码中不支持的实现。关于该方法的运行效果看以下例子

 

Html代码    收藏代码
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3.     <head>  
  4.         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  5.         <title>方法getBoundingClientRect Demo</title>  
  6.     </head>  
  7.   
  8.     <body style="width: 2000px; height: 1000px;">  
  9.         <div id="demo"  
  10.             style="position: absolute; left: 518px; right: 100px; width: 500px; height: 500px; background: #CC0000; top: 114px;">  
  11.             Demo为了方便就直接用绝对定位的元素  
  12.         </div>  
  13.     </body>  
  14. </html>  
  15. <script>  
  16.    document.getElementById('demo').onclick=function (){  
  17.         if (document.documentElement.getBoundingClientRect) {   
  18.             alert("left:"+this.getBoundingClientRect().left)  
  19.             alert("top:"+this.getBoundingClientRect().top)  
  20.             alert("right:"+this.getBoundingClientRect().right)  
  21.             alert("bottom:"+this.getBoundingClientRect().bottom)  
  22.             var Xthis.getBoundingClientRect().left+document.documentElement.scrollLeft;  
  23.             var Y = this.getBoundingClientRect().top+document.documentElement.scrollTop;  
  24.             alert("Demo的位置是X:"+X+";Y:"+Y)  
  25.         }   
  26.    }  
  27. </script>  

你可能感兴趣的:(function,浏览器,Opera,ExtJs,scroll,BT)