最近在工作中接触到了这样一个问题:当把用于选择尺寸的下拉列表(html select标签实现)打开后,不选择,然后移动鼠标到页面头部的菜单栏,此时菜单栏接受onmouseover事件,显示一个DIV实现的菜单,但这个操作并没有将页面焦点从select上移开,即select依然处于打开状态,问题出现了,打开的option列表覆盖住了弹出的菜单!用户体验不好。
这个问题的本质原因是,在浏览器中,select所弹出的option列表的层级会高于DIV的层级,即其默认就是显示在DIV的上方,这个无法通过z-index样式进行变更。搜索了一下,网上也给出了一些方法,主要是通过iframe来实现,因为iframe的显示层级比select的option列表还要高!但对我遇到的这个问题,这种方式的解决点放置菜单处了,即我要改写菜单的实现方式处的代码,而菜单这段代码是被整个系统所引用,这个改动波及范围太广,容易引发别的问题,并且很难测试全面!
和同事讨论了一下后,我们决定把解决点移到select这边,我们的思路是:定义一个较大的DIV(或页面本身存在这样的DIV)能将这个select(包括其弹出的option列表)完全包含进去,然后给这个DIV定义一个onmouseout事件,如果鼠标移出这个DIV,则调用select对象的onblur方法,将其焦点去掉,即将select弹出的option列表收回!这样,当用户打开了select后,将鼠标移向了页面头部的菜单栏,在这个过程中,这个select会自动关闭,也就不会影响菜单的显示效果。并且用户在这个DIV内的操作,并不会和以前有什么区别。
在写代码过程中,发现了一个比较有意思的情况,就是DIV中包含的元素,当鼠标在DIV内运动,移到了其内部的某个元素,同样会触发其onmouseout事件!
附上代码,供大家参考:
<html>
<head>
<script type="text/javascript">
function testkkk(oEvent, divObj){
// get the scroll's position
var scrollTop = document.documentElement.scrollTop;
var scrollLeft = document.documentElement.scrollLeft;
// get current mouse x axis
var mcurrentX = oEvent.clientX + scrollLeft;
// get current mouse y axis
var mcurrentY = oEvent.clientY + scrollTop;
// in the IE browser, when your mouse hover on the select option, the value of mcurrentX and mcurrentY will be negative
if(mcurrentX < 0 || mcurrentY < 0){
return;
}
// get div parent element
var divParent = divObj.offsetParent;
var parentOffsetLeft = 0;
var parentOffsetTop = 0;
if(divParent){
parentOffsetLeft = divParent.offsetLeft;
parentOffsetTop = divParent.offsetTop;
}
// think about there are some difference among the browers, it will shrink the mouse move area 10px
// get the div element's x axis
var areaX = divObj.offsetLeft + parentOffsetLeft + 10;
// get the div element's y axis
var areaY = divObj.offsetTop + parentOffsetTop + 10;
// calculate the x axis of the div's right down corner
var areaLX = areaX + divObj.offsetWidth -10;
// calculate the y axis of the div's right down corner
var aredLY = areaY + divObj.offsetHeight -10;
if(mcurrentX <= areaX || mcurrentX >= areaLX || mcurrentY <= areaY || mcurrentY >= aredLY ){
var selObj = divObj.getElementsByTagName("select")[0];
if(selObj != null){
//alert("mcurrentX : " + mcurrentX + " , mcurrentY : " + mcurrentY + " , " + " areaX: " + areaX + " , " + " areaY : " + areaY + " , areaLX : " + areaLX + " , aredLY: " + aredLY);
selObj.blur();
}
}
}
</script>
</head>
<body >
<div>
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
</div>
<div id = "ddddddd" style="background:#FF0000;width:500px;" οnmοuseοut="testkkk(event, this)">
<input type="text" id="jjjdddd" /> <br>
<input type="button" value="测试按钮" id="test" />
<input type="hidden" id= "jjtest" />
<br/>
<br/>
<br/>
测试Select: <select name="selcon" id="selTestdddd" >
<option> aaa</option>
<option> bbb</option>
<option> ccc</option>
</select>
<br/>
<br/>
<div>
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
adfdsafsadfsadfsadfdsafasdf<br/>;
</div>
</div>
</body>
</html>
在实现过程中,要综合考虑Scroll滚动条和综合父容器的相对位置计算实际元素的实际坐标!
页面红色区域就是设定的DIV,然后内部包含了select和其他一些元素,用户打开select后,在DIV内部运动,select不会有变化,当用户的鼠标移出这块红色区域,则select自动关闭!