先前在做ASTreeView右键菜单时遇到一个问题,是这样的:
因为页面的布局中,放置ASTreeView控件的容器叫container,当用户右键点击树节点时,edit, delete节点的菜单出现。由于container的position是relative的,右键菜单的div的position是absolute的,所以,设置菜单div的left, top属性时,会根据container的位置去定位,如图所示:
当用户点击右键,我们可以获取当前鼠标的坐标,这时,如果直接将鼠标的x,y坐标赋值给菜单的left和top就会出问题。因为鼠标坐标的原点是窗口的左上角,而菜单的原点是container的左上角。
那如何让菜单显示在鼠标点击的位置呢?接下来的代码将一步一步地实现:
首先是获取鼠标坐标的代码:
function getMousePos(e) { e = e || event; var posx = 0; var posy = 0; if ( e.pageX && e.pageY ) { posx = e.pageX; posy = e.pageY; } else if (e.clientX && e.clientY ) { posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } return { 'x' : posx, 'y' : posy } }
接着我们将要得到container相对于窗口左上角的距离,当然,这要考虑container的父节点,也就是要一直递归到根节点:
function getTotalOffset( elem ){ var offsetTotalX = 0; var offsetTotalY = 0; var pOffsetElem = elem.offsetParent; while( pOffsetElem ){ offsetTotalX += pOffsetElem.offsetLeft; offsetTotalY += pOffsetElem.offsetTop; pOffsetElem = pOffsetElem.offsetParent; } return { 'x' : offsetTotalX, 'y' : offsetTotalY } }
最后在设置菜单位置的时候,将鼠标的位置,减去container的offset:
var pos = getMousePos(e); var offset = getTotalOffset(elem); menu.style.left = ( pos.x - offset.x ) + 'px'; menu.style.top = ( pos.y - offset.y ) + 'px';
这样,菜单就能显示在鼠标点击的位置啦!
完整示例下载: