jQuery中:
if ( event.pageX == null && event.clientX != null ) {
var doc = document.documentElement, body = document.body;
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
}
YUI中:
getPageX: function(ev) {
var x = ev.pageX;
if (!x && 0 !== x) {
x = ev.clientX || 0;
if ( this.isIE ) {
x += this._getScrollLeft();
}
}
return x;
},
getPageY: function(ev) {
var y = ev.pageY;
if (!y && 0 !== y) {
y = ev.clientY || 0;
if ( this.isIE ) {
y += this._getScrollTop();
}
}
return y;
},
_getScrollLeft: function() {
return this._getScroll()[1];
},
_getScrollTop: function() {
return this._getScroll()[0];
},
_getScroll: function() {
var dd = document.documentElement, db = document.body;
if (dd && (dd.scrollTop || dd.scrollLeft)) {
return [dd.scrollTop, dd.scrollLeft];
} else if (db) {
return [db.scrollTop, db.scrollLeft];
} else {
return [0, 0];
}
},
YUI的写法比起jQuery来确是“工程化”了很多,如果是按照代码行数发工资的话,推荐YUI,哈哈。之前翻译PPK的作品的是提到了无论如何都不要检测浏览器的类型,因为没必要,而且浏览器的UA都在胡言乱语。
关于document.documentElement和document.body
document.documentElement和document.body在不同的浏览器和不同的模式下面都会有不同的表现,已经有人做过详尽的测试了,地址在这里http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
经过测试的结论就是,在标准浏览器下面,一般都有相应代替的做法,在IE中,在documentElement存在的情况下一般都能正常显示,不存在时候使用document.body。这两个的来由应该源自HTML和xHTML。
所以在这个问题的处理上jQuery和YUI都采用了相同的办法:doc && doc.scrollLeft || body && body.scrollLeft || 0 。
关于pageX pageY和clientX clientY,scrollLeft scrollTop
对于鼠标事件,IE不支持通过pageX,pageY来获得鼠标在文档中的位置,而只有clientX、clientY,这两个参数只能获得鼠标在浏览器的可视范围内的位置。这时候就需要通过其他办法来获得鼠标在文档里面的位置,于是出现了scrollLeft和scrollTop。
有些情况下,“元素中内容(子元素)”的高度会超过“元素本身”的高度,这时候就使用scrollTop来表示超出部分的高度,scrollLeft同理。body元素的scrollTop就是指你的浏览器中被滚动条滚动了的高度。用这个值加上clientY不就是鼠标相对于文档的位置了么。在这里两个框架的也是相同的。event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0)
关于clientLeft和clientTop
然而jQuery中,以及网上搜索到的大量的实例中,还需要减掉clientLeft/Top值。
event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
这个值是做什么用的呢?可以先来查看下面的这幅图:
clientLeft的值其实就是元素的边框,YUI中没有减掉这个,难道是认为IE的body没有边框?我在IE下测试body确实有2px的clientLeft的值。所以如果要精确的得到鼠标的位置,在IE下面就必须减去这个clientLeft。