让div如右键菜单一样聪明
先看下面一个命题:
在页面上有一个div,当你用鼠标点击页面时,如果鼠标点在div以内,则不进行任何动作,而如果鼠标点在div以外,则需要让其隐藏。
实际上,这就和右键菜单有点类似,如果你点击右键菜单以外的地方,它就会隐藏起来,如果点击右键菜单的分隔符等不会引起响应的地方,右键菜单则会继续显示。反过来,也就是说,我们用具有这样特性的div可以来模拟右键菜单等的行为。
看到这样命题,也许是由于命题本身的诱导,很多人都会不约而同地想到同一个办法:计算出div的区域,得到鼠标点击时的坐标,然后计算这个坐标是否落在div的区域内;如果在,继续显示该div,否则隐藏。
这种思路是相当简单和直接的,不过要真正实现它却不简单——需要考虑到各个浏览器的兼容性才能准确得出div的位置。然后每次有鼠标点击事件时都要捕捉鼠 标位置并对其进行相关的比较,最终决定是否隐藏div。在最开始的地方,我就在冥思苦想这种方案的实现,实践了好久效果都不太理想。后来,思路一换,发现 原来有一种方法,可以绕过浏览器兼容性和鼠标点击区域的判断,且能对鼠标点击做出相当准确和迅速的响应。你是否会觉得不可思议呢?不过,这是真的。
首先来看一个简单的例子,从中体验一下浏览器的有关特性:
当你用鼠标点击div以外区域时,只会引起一次alert;当点击div区域以内,则会依次弹出两次提示窗口,分别显示“popDiv clicked”和“document clicked”。没错,这就是我们要利用的浏览器特性。为了保险起见,你可以在各种浏览器里边进行反复测试,只要确认弹出提示的次序和次数都保持不变就 可以了。
我们已经看到了,如果给div和document都定义click事件,那么点击div以外当然只会引起document的click事件,点击div以 内则会依次引起div和document的click事件。恩,我们是否可以重新来考虑命题的实现方案呢——定义一个标识符,默认值为false,当点击 div时将其置换为true,那么当document的click事件被触发时,就可以通过检测这个标识符来判断鼠标是否点击过div以内的区域了。
想到就马上来做,试试照下边修改script标签内的代码:
怎么样?操作很简单吧,但命题中要求的效果却已经圆满解决了。当然,用上边这样的方法来定义click事件会使其他绑定到该div或者document上 的click事件失效。所以,需要改用addEventListener或attachEvent的方法,才能使他们的click事件能动态绑定和移除。
在页面上有一个div,当你用鼠标点击页面时,如果鼠标点在div以内,则不进行任何动作,而如果鼠标点在div以外,则需要让其隐藏。
实际上,这就和右键菜单有点类似,如果你点击右键菜单以外的地方,它就会隐藏起来,如果点击右键菜单的分隔符等不会引起响应的地方,右键菜单则会继续显示。反过来,也就是说,我们用具有这样特性的div可以来模拟右键菜单等的行为。
看到这样命题,也许是由于命题本身的诱导,很多人都会不约而同地想到同一个办法:计算出div的区域,得到鼠标点击时的坐标,然后计算这个坐标是否落在div的区域内;如果在,继续显示该div,否则隐藏。
这种思路是相当简单和直接的,不过要真正实现它却不简单——需要考虑到各个浏览器的兼容性才能准确得出div的位置。然后每次有鼠标点击事件时都要捕捉鼠 标位置并对其进行相关的比较,最终决定是否隐藏div。在最开始的地方,我就在冥思苦想这种方案的实现,实践了好久效果都不太理想。后来,思路一换,发现 原来有一种方法,可以绕过浏览器兼容性和鼠标点击区域的判断,且能对鼠标点击做出相当准确和迅速的响应。你是否会觉得不可思议呢?不过,这是真的。
首先来看一个简单的例子,从中体验一下浏览器的有关特性:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<style type="text/css">
#popDiv{
width:400px;
height:200px;
border:solid 1px #333;
}
</style>
<body>
<div id="popDiv"></div>
</body>
<script type="text/javascript">
function $(i){return document.getElementById(i);}
$('popDiv').onclick=function(){
alert('popDiv clicked');
};
document.onclick = function() {
alert('document clicked');
};
</script>
</html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<style type="text/css">
#popDiv{
width:400px;
height:200px;
border:solid 1px #333;
}
</style>
<body>
<div id="popDiv"></div>
</body>
<script type="text/javascript">
function $(i){return document.getElementById(i);}
$('popDiv').onclick=function(){
alert('popDiv clicked');
};
document.onclick = function() {
alert('document clicked');
};
</script>
</html>
当你用鼠标点击div以外区域时,只会引起一次alert;当点击div区域以内,则会依次弹出两次提示窗口,分别显示“popDiv clicked”和“document clicked”。没错,这就是我们要利用的浏览器特性。为了保险起见,你可以在各种浏览器里边进行反复测试,只要确认弹出提示的次序和次数都保持不变就 可以了。
我们已经看到了,如果给div和document都定义click事件,那么点击div以外当然只会引起document的click事件,点击div以 内则会依次引起div和document的click事件。恩,我们是否可以重新来考虑命题的实现方案呢——定义一个标识符,默认值为false,当点击 div时将其置换为true,那么当document的click事件被触发时,就可以通过检测这个标识符来判断鼠标是否点击过div以内的区域了。
想到就马上来做,试试照下边修改script标签内的代码:
function $(i){return document.getElementById(i);}
var divClicked = false;
$('popDiv').onclick=function(){
divClicked = true;
};
document.onclick = function() {
if(!divClicked) $('popDiv').style.display = 'none';
divClicked = false; // 点击过后将标识重置为false
};
var divClicked = false;
$('popDiv').onclick=function(){
divClicked = true;
};
document.onclick = function() {
if(!divClicked) $('popDiv').style.display = 'none';
divClicked = false; // 点击过后将标识重置为false
};
怎么样?操作很简单吧,但命题中要求的效果却已经圆满解决了。当然,用上边这样的方法来定义click事件会使其他绑定到该div或者document上 的click事件失效。所以,需要改用addEventListener或attachEvent的方法,才能使他们的click事件能动态绑定和移除。