月度归档:2010年11月

鼠标位置的检测,jQuery和YUI中的实现

 
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。