原帖地址: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;
}
});
本部分主要为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;
}
});