日期:2014-05-16  浏览次数:20358 次

Extjs源码之--Ext.lib.Dom(Dom的基本封装)
Extjs的对Dom最基础的封装,主要包括:元素的包含关系,元素或文档的可视宽高,获取元素的位置,设置元素的位置,这些都是elment最基础的属性,这涉及到各个浏览器兼容器问题,如果想获得详细解答,可以看看 Nicholas C.Zakas 的《javascript高级程序设计》第二版 第11章261-268页

(function(){
	var doc = document,
                  //浏览器盒状模式:BackCompa->Quirks Modet和CSS1Compat->Standards Mode 跟文档声明相关
		isCSS1 = doc.compatMode == "CSS1Compat",//Ext.isStrict就是这么做的,为什么Ext不用这个,这里重新设置下,而且下面也有用这个,有点想不通这么做的用意
		MAX = Math.max,		
        ROUND = Math.round,
		PARSEINT = parseInt;
		
	Ext.lib.Dom = {
	    isAncestor : function(p, c) {//判断p是否包含子节点c
		    var ret = false;
			
			p = Ext.getDom(p);
			c = Ext.getDom(c);
			if (p && c) {
          //contains IE,Safari 3+,Opear 8+,Chorme 支持 contains
				if (p.contains) {
					return p.contains(c);
				} else if (p.compareDocumentPosition) {//ff 支持compareDocumentPosition,并有返回值,1->无关 2->居前 3->居后 8->包含 16->被包含
					return !!(p.compareDocumentPosition(c) & 16);
				} else {//循环查找的方式
					while (c = c.parentNode) {
						ret = c == p || ret;	        			
					}
				}	            
			}	
			return ret;
		},
	//这个调用下面的方法	
        getViewWidth : function(full) {
            return full ? this.getDocumentWidth() : this.getViewportWidth();
        },
        //这个调用下面的方法	
        getViewHeight : function(full) {
            return full ? this.getDocumentHeight() : this.getViewportHeight();
        },
        //接下来的四个方法很简单,也就是从浏览器版本和盒子模型上的兼容性做判断
        getDocumentHeight: function() {            
            return MAX(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, this.getViewportHeight());
        },

        getDocumentWidth: function() {            
            return MAX(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, this.getViewportWidth());
        },

        getViewportHeight: function(){
	        return Ext.isIE ? 
	        	   (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
	        	   self.innerHeight;
        },

        getViewportWidth : function() {
	        return !Ext.isStrict && !Ext.isOpera ? doc.body.clientWidth :
	        	   Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
        },
        
        getY : function(el) {
            return this.getXY(el)[1];
        },

        getX : function(el) {
            return this.getXY(el)[0];
        },
        //核心获取节点的x y 是位置
        getXY : function(el) {
            var p, 
            	pe, 
            	b,
            	bt, 
            	bl,     
            	dbd,       	
            	x = 0,
            	y = 0, 
            	scroll,
            	hasAbsolute, 
            	bd = (doc.body || doc.documentElement),
            	ret = [0,0];
            	
            el = Ext.getDom(el);

            if(el != bd){
            //getBoundingClientRect,IE,FF3+,Opera9.5+ 都支持,IE和其他浏览器对于文档的位置是不一样的,IE为(2,2),其他为(0,0)
	            if (el.getBoundingClientRect) {
	                b = el.getBoundingClientRect();
	                scroll = fly(document).getScroll();
	                ret = [ROUND(b.left + scroll.left), ROUND(b.top + scroll.top)];
	            } else {  
		            p = el;		
		            hasAbsolute = fly(el).isStyle("position", "absolute");
		//循环向上查找元素,并改变元素的x,y
		            while (p) {
			            pe = fly(p);		
		                x += p.offsetLeft;
		                y += p.offsetTop;
		
		                hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
		                		
		                if (Ext.isGecko) {		  //isGecko 需要加上边框值                  
		                    y += bt = PARSEINT(pe.getStyle("borderTopWidth"), 10) || 0;
		                    x += bl = PARSEINT(pe.getStyle("borderLeftWidth"), 10) || 0;	
		
		                    if (p != el && !pe.isStyle('overflow','visible')) {
		                        x += bl;
		                        y += bt;