[转帖]Mootools源码分析-19 -- Element-6

原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-403472

原作者:我佛山人

 

/*
本部分主要为Element提供取尺寸相关的兼容方法
*/
(
function()    {

    Element.implement({
        
//使可视范围滚动到指定坐标
        scrollTo: function(x, y)    {
            
//如果当前是body,让页面的滚动条滚动
            if (isBody(this))    {
                
this.getWindow().scrollTo(x, y);
            }    
else    {
                
this.scrollLeft = x;
                
this.scrollTop = y;
            }
            
return this;
        },

        
//获取对象的布局尺寸
        getSize: function()    {
            
if (isBody(this))    return this.getWindow().getSize();
            
return {x: this.offsetWidth, y: this.offsetHeight};
        },

        
//获取对象的滚动尺寸
        getScrollSize: function()    {
            
if (isBody(this))    return this.getWindow().getScrollSize();
            
return {x: this.scrollWidth, y: this.scrollHeight};
        },

        
//获取滚动位置
        getScroll: function()    {
            
if (isBody(this))    return this.getWindow().getScroll();
            
return {x: this.scrollLeft, y: this.scrollTop};
        },

        
//获取相对文档的滚动位置
        getScrolls: function()    {
            
var element = this, position = {x: 0, y: 0};
            
while (element && !isBody(element))    {
                position.x 
+= element.scrollLeft;
                position.y 
+= element.scrollTop;
                element 
= element.parentNode;
            }
            
return position;
        },

        
//获取总的偏移量
        getOffsets: function()    {
            
var element = this, position = {x: 0, y: 0};
            
//如果是根节点,坐标为原点
            if (isBody(this))    return position;
            
while (element && !isBody(element))    {
                position.x 
+= element.offsetLeft;
                position.y 
+= element.offsetTop;
                
if (Browser.Engine.gecko)    {
                    
//firefox的处理,如果不使用盒模型,需要加上左和上边框的宽度
                    if (!borderBox(element))    {
                        position.x 
+= leftBorder(element);
                        position.y 
+= topBorder(element);
                    }
                    
var parent = element.parentNode;
                    
if (parent && styleString(parent, 'overflow'!= 'visible')    {
                        position.x 
+= leftBorder(parent);
                        position.y 
+= topBorder(parent);
                    }
                }    
else if    (element != this && (Browser.Engine.trident || Browser.Engine.webkit))    {
                    
//IE和Safari也需要加上边框,看来这里只有Opera比较符合标准,Safari次之
                    position.x += leftBorder(element);
                    position.y 
+= topBorder(element);
                }
                element 
= element.offsetParent;
                
if (Browser.Engine.trident)    {
                    
//忽略IE下没有hasLayout的element
                    while (element && !element.currentStyle.hasLayout)    element = element.offsetParent;
                }
            }
            
//firefox下不使用盒模型解决时需要再减去当前的上左边框宽度
            if (Browser.Engine.gecko && !borderBox(this))    {
                position.x 
-= leftBorder(this);
                position.y 
-= topBorder(this);
            }
            
return position;
        },

        
//获取坐标值,如果提供relative参数,则返回相对于ralative的坐标值
        getPosition: function(relative)    {
            
//根节点坐标为原点
            if (isBody(this))    return {x: 0, y: 0};
            
//取偏移值和滚动条位置
            var ōffset = this.getOffsets(), scroll = this.getScrolls();
            
//得到坐标值
            var position = {x: offset.x - scroll.x, y: offset.y - scroll.y};
            
//求相对坐标值
            var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0};
            
return {x: position.x - relativePosition.x, y: position.y - relativePosition.y};
        },

        
//获取坐标和尺寸
        getCoordinates: function(element)    {
            
//根节点处理
            if (isBody(this))    return this.getWindow().getCoordinates();
            
//分别获取坐标与尺寸
            var position = this.getPosition(element), size = this.getSize();
            
//新的表示形式
            var obj = {left: position.x, top: position.y, width: size.x, height: size.y};
            
//右下坐标的计算
            obj.right = obj.left + obj.width;
            obj.bottom 
= obj.top + obj.height;
            
return obj;
        },

        
//计算运行时坐标,会受margin-left和margin-top影响
        computePosition: function(obj)    {
            
return {left: obj.x - styleNumber(this'margin-left'), top: obj.y - styleNumber(this'margin-top')};
        },

        
//定位
        position: function(obj)    {
            
return this.setStyles(this.computePosition(obj));
        }

    });

    
//对Document和Window实现Element的同名方法,因为具体实现有别于一般Element
    Native.implement([Document, Window], {

        
//获取尺寸
        getSize: function()    {
            
var win = this.getWindow();
            
//Opera和Safari的处理
            if (Browser.Engine.presto || Browser.Engine.webkit)    return {x: win.innerWidth, y: win.innerHeight};
            
var doc = getCompatElement(this);
            
return {x: doc.clientWidth, y: doc.clientHeight};
        },

        
//获取滚动坐标
        getScroll: function()    {
            
var win = this.getWindow();
            
var doc = getCompatElement(this);
            
return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
        },

        
//获取滚动尺寸
        getScrollSize: function()    {
            
var doc = getCompatElement(this);
            
var min = this.getSize();
            
return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};
        },

        
//定位
        getPosition: function()    {
            
return {x: 0, y: 0};
        },

        
//获取尺寸和坐标
        getCoordinates: function()    {
            
var size = this.getSize();
            
return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
        }
    });

    
// 私有方法

    
//获取运行时的样式属性
    var styleString = Element.getComputedStyle;

    
//获取运行时的样式属性的数字值
    function styleNumber(element, style)    {
        
return styleString(element, style).toInt() || 0;
    };

    
//获取盒尺寸的mozilla家庭私有属性
    function borderBox(element)    {
        
return styleString(element, '-moz-box-sizing'== 'border-box';
    };

    
//获取上边框的宽度
    function topBorder(element)    {
        
return styleNumber(element, 'border-top-width');
    };

    
//获取左边框宽度
    function leftBorder(element)    {
        
return styleNumber(element, 'border-left-width');
    };

    
//测试element是否body或html节点
    function isBody(element)    {
        
return (/^(?:body|html)$/i).test(element.tagName);
    };

    
//根据当前文档是否使用标准模式而返回页面根节点,html或body
    function getCompatElement(element)    {
        
var doc = element.getDocument();
        
return (!doc.compatMode || doc.compatMode == 'CSS1Compat'? doc.html : doc.body;
    };
})();

//别名

Native.implement([Window, Document, Element], {

    
//获取高度,依赖getSize方法
    getHeight: function()    {
        
return this.getSize().y;
    },

    
//获取宽度,依赖getSize方法
    getWidth: function()    {
        
return this.getSize().x;
    },

    
//获取y轴滚动坐标,依赖getScroll方法
    getScrollTop: function()    {
        
return this.getScroll().y;
    },

    
//获取x轴滚动坐标,依赖getScroll方法
    getScrollLeft: function(){
        
return this.getScroll().x;
    },

    
//获取滚动高度,依赖getScrollSize方法
    getScrollHeight: function(){
        
return this.getScrollSize().y;
    },

    
//获取滚动宽度,依赖getScrollSize方法
    getScrollWidth: function(){
        
return this.getScrollSize().x;
    },

    
//获取y坐标,依赖getPosition方法
    getTop: function(){
        
return this.getPosition().y;
    },

    
//获取x坐标,依赖getPosition方法
    getLeft: function(){
        
return this.getPosition().x;
    }
});

 

posted @ 2009-11-06 16:45  webgis松鼠  阅读(296)  评论(0编辑  收藏  举报