zoukankan      html  css  js  c++  java
  • 读Ext之五(Dom的低级封装)

    上篇看了ext-base-event.js(Ext.lib.Event),这篇看ext-base-dom.js(Ext.lib.Dom)。
    后续EventManager.js(Ext.EventManager)其中会用到该篇的Ext.lib.Dom。

    整体浏览ext-base-dom.js可以看到还是一个匿名函数执行,与上一篇不同的是这次并非返回包装好的对象pub,而是直接将对象赋值给Ext.lib.Dom。

    (function(){
    	var doc = document,
    		...;
    		
    	Ext.lib.Dom = {        
    		...
        };
    })();
    

    一些变量声明,

    var doc = document,
    	isCSS1 = doc.compatMode == "CSS1Compat",
    	MAX = Math.max,		
        ROUND = Math.round,
    	PARSEINT = parseInt;
    

    doc、Max、ROUND、PARSEINT为简写。好处在上一篇已经提到,clue 还提到了这样写提高了压缩率。即document,Math.max等不会被压缩工具进行名称替换,doc,MAX等则会,可用 YUI Compressor 测试下。

    isCSS1用来判断浏览器的文档模式(doctype),为true是标准模式,false是怪异模式。第一篇 提到了Ext.js中有个Ext.isStrict,和这里的isCSS1是一样的。

    Ext作者没有使用Ext.isStrict而是新增了一个变量isCSS1个人猜测原因同doc,MAX,亦或是为了保持此处代码一致性。

    接下来是Ext.lib.Dom对象的定义,先看第一个方法,

    isAncestor : function(p, c) {
        var ret = false;
    	
    	p = Ext.getDom(p);
    	c = Ext.getDom(c);
    	if (p && c) {
    		if (p.contains) {
    			return p.contains(c);
    		} else if (p.compareDocumentPosition) {
    			return !!(p.compareDocumentPosition(c) & 16);
    		} else {
    			while (c = c.parentNode) {
    				ret = c == p || ret;	        			
    			}
    		}	            
    	}	
    	return ret;
    },
    

    这个方法用来判断元素c(child)是否是p(parent)的子节点。这里有contains和compareDocumentPosition各浏览器 兼容列表 。这个方法与ext-base-event.js的私有方法elContains(上一篇已提到)作用类似,不知为何Ext作者要冗余。

    接下来是几个获取视图,文档,视窗宽高的方法,

    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;
    },
    

    这里仅讲述宽。
    getViewportWidth 获取视口的宽。即怪异模式且非Opera使用doc.body.clientWidth获取,IE使用doc.documentElement.clientWidth获取,其它浏览器使用self.innerWidth获取。

    getDocumentWidth 获取文档的宽。我们知道如果文档中出现水平滚动条,那么文档的宽将大于视口。因此比较scroll宽度和文档宽度,取其中较大的。
    这里仍仍然需要区分浏览器的文档模式,怪异模式使用doc.body.scrollWidth,标准模式使用doc.documentElement.scrollWidth获取。

    getViewWidth 是对以上两个方法的封装,full为true则取整个文档宽(含滚动),否则只取文档可视区域宽。


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

    getY : function(el) {
        return this.getXY(el)[1];
    },
    getX : function(el) {
        return this.getXY(el)[0];
    },
    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){
            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");
    
                while (p) {
    	            pe = fly(p);		
                    x += p.offsetLeft;
                    y += p.offsetTop;
    
                    hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
                    		
                    if (Ext.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;
                        }
                    }
                    p = p.offsetParent;
                }
    
                if (Ext.isSafari && hasAbsolute) {
                    x -= bd.offsetLeft;
                    y -= bd.offsetTop;
                }
    
                if (Ext.isGecko && !hasAbsolute) {
                    dbd = fly(bd);
                    x += PARSEINT(dbd.getStyle("borderLeftWidth"), 10) || 0;
                    y += PARSEINT(dbd.getStyle("borderTopWidth"), 10) || 0;
                }
    
                p = el.parentNode;
                while (p && p != bd) {
                    if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
                        x -= p.scrollLeft;
                        y -= p.scrollTop;
                    }
                    p = p.parentNode;
                }
                ret = [x,y];
            }
     	}
        return ret
    },
    

    核心是getXY方法,getX和getY都是调用getXY。获取html元素在页面中(窗口客户区域)的位置(top,left)不是件容易的事。
    该方法实现用到了Ext.Element相关方法,后续阅读。

    接下来是设置元素位置的方法,

    setXY : function(el, xy) {
        (el = Ext.fly(el, '_setXY')).position();
        
        var pts = el.translatePoints(xy),
        	style = el.dom.style,
        	pos;            	
        
        for (pos in pts) {	            
            if(!isNaN(pts[pos])) style[pos] = pts[pos] + "px"
        }
    },
    setX : function(el, x) {
        this.setXY(el, [x, false]);
    },
    setY : function(el, y) {
        this.setXY(el, [false, y]);
    }
    

    核心是setXY,setX和setY都是调用setXY。setXY也依赖于Ext.fly,Ext.fly实际上是Ext.Element.fly。后续阅读。

    ext-base-dom.js

  • 相关阅读:
    经典8锁问题--助你彻底搞懂锁的概念
    linux上安装mysql
    Jenkins安装详解
    第一篇:实时网络日志分析器和交互式查看器--GoAccess安装
    Centos7上安装python3.7
    Nginx报错收集
    免费yum源镜像地址
    nginx日志文件切割
    腾讯云绑定和配置弹性网卡和添加弹性网卡
    LNMP-WEB应用环境搭建
  • 原文地址:https://www.cnblogs.com/snandy/p/2472100.html
Copyright © 2011-2022 走看看