freejosh 的回答有效。但是,e.stopPropagation()
如果有其他处理程序使用事件委托,则调用可能会产生不希望的副作用,因为这些处理程序可能不会被调用。
事件处理的基础之一是它们不应该尽可能地影响或依赖其他处理程序,例如,如果您有两个按钮需要显示两个不同的 div。通过调用e.stopPropagation()
,单击其中一个弹出窗口不会隐藏另一个弹出窗口。请参阅document.click 继续切换菜单以获取由于与灯箱事件处理程序发生冲突而无法正常工作的示例。因此,不影响任何其他代码的解决方案是安装一个文档单击处理程序,该处理程序仅在单击不是来自按钮或弹出窗口内时才起作用。
http://jsfiddle.net/b4PXG/2/
HTML
Here is my web page <button id="show-btn"> show popup</button>
<div id="modal" > I will show over everything <a href="http://google.com" target="_blank">Google</a></div>
JS
var modal = document.getElementById('modal');
var btn = document.getElementById('show-btn');
btn.onclick = function() {
modal.style.display = "block";
};
document.onclick = function (e) {
e = e || window.event;
var target = e.target || e.srcElement;
if (target !== btn && (!target.contains(modal) || target !== modal)) {
modal.style.display = 'none';
}
}
您可以将此模式抽象为创建文档点击处理程序的函数
/**
* Creates a handler that only gets called if the click is not within any
* of the given nodes
* @param {Function} handler The function to call (with the event object as
* as its parameter)
* @param {HTMLElement} exclude... If the click happens within any of these
* nodes, the handler won't be called
* @return {function} A function that is suitable to be
* bound to the document click handler
*/
function createDocClickHandler(handler /* [,exclude, exclude, ...] */) {
var outerArgs = arguments;
return function (e) {
e = e || window.event;
var target = e.target || e.srcElement;
// Only call the original handler if the click was outside all the excluded nodes
var isWithinExcluded = false;
for (var i=1; i < outerArgs.length; i++) {
var excluded = outerArgs[i];
if (target === excluded || excluded.contains(target)) {
isWithinExcluded = true;
break;
}
}
if (!isWithinExcluded) {
handler.call(this, e);
}
}
}
var modal = document.getElementById('modal');
var btn = document.getElementById('show-btn');
btn.onclick = function() {
modal.style.display = "block";
};
// Assign the handler that will hide the popup if the clicked
// happened outside of modal and btn
document.onclick = createDocClickHandler(function (e) {
modal.style.display = 'none';
}, modal, btn);