我有一些HTML菜单,当用户点击这些菜单的头部时,我会完全显示这些菜单。当用户点击菜单区域外时,我想隐藏这些元素。
jQuery可以这样吗?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
答案 0 :(得分:1708)
注意:使用
stopEventPropagation()
是应该避免的,因为它会破坏DOM中的正常事件流。有关详细信息,请参阅this article。请考虑使用this method代替
将单击事件附加到关闭窗口的文档正文。将单独的单击事件附加到容器,从而停止传播到文档正文。
$(window).click(function() {
//Hide the menus if visible
});
$('#menucontainer').click(function(event){
event.stopPropagation();
});
答案 1 :(得分:1258)
您可以在document
上收听点击事件,然后使用.closest()
确保#menucontainer
不是祖先或点击元素的目标
如果不是,则点击的元素位于#menucontainer
之外,您可以安全地隐藏它。
$(document).click(function(event) {
$target = $(event.target);
if(!$target.closest('#menucontainer').length &&
$('#menucontainer').is(":visible")) {
$('#menucontainer').hide();
}
});
如果您打算关闭菜单并想要停止侦听事件,您也可以在事件监听器之后进行清理。此函数将仅清除新创建的侦听器,并保留document
上的任何其他单击侦听器。使用ES2015语法:
export function hideOnClickOutside(selector) {
const outsideClickListener = (event) => {
$target = $(event.target);
if (!$target.closest(selector).length && $(selector).is(':visible')) {
$(selector).hide();
removeClickListener();
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
对于那些不想使用jQuery的人。以下是普通vanillaJS(ECMAScript6)中的上述代码。
function hideOnClickOutside(element) {
const outsideClickListener = event => {
if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
element.style.display = 'none'
removeClickListener()
}
}
const removeClickListener = () => {
document.removeEventListener('click', outsideClickListener)
}
document.addEventListener('click', outsideClickListener)
}
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ) // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js
注意:强>
这是基于Alex评论只使用!element.contains(event.target)
而不是jQuery部分。
但element.closest()
现在也可用于所有主流浏览器(W3C版本与jQuery版本略有不同)。
可在此处找到Polyfills:https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
答案 2 :(得分:243)
如何检测元素外的点击?
这个问题如此受欢迎并且答案如此之多的原因在于它看起来很复杂。经过近八年的时间和几十个答案,我真的很惊讶地看到对可访问性的关注度很低。
当用户在菜单外点击时,我想隐藏这些元素。区域。
这是一个崇高的原因,是实际的问题。问题的标题 - 大多数答案似乎试图解决 - 包含一个不幸的红鲱鱼。
提示:"点击" !
如果您要绑定点击处理程序以关闭对话框,那么您已经失败了。您失败的原因是不是每个人都会触发click
事件。不使用鼠标的用户可以通过按 Tab 来转义对话框(并且您的弹出菜单可以说是一种对话框),然后他们就无法阅读对话框后面的内容,而不会随后触发click
事件。
所以让我们改一下这个问题。
当用户完成对话时如何关闭对话框?
这是目标。不幸的是,现在我们需要绑定userisfinishedwiththedialog
事件,并且绑定不是那么简单。
那么我们怎样才能检测到用户已经完成了对话?
focusout
事件一个好的开始是确定焦点是否已离开对话框。
提示:请注意blur
事件,blur
如果事件绑定到冒泡阶段,则不会传播!
jQuery' s focusout
会做得很好。如果你不能使用jQuery,那么你可以在捕获阶段使用blur
:
element.addEventListener('blur', ..., true);
// use capture: ^^^^
此外,对于许多对话框,您需要允许容器获得焦点。添加tabindex="-1"
以允许对话框动态接收焦点,而不会中断标签流程。
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on('focusout', function () {
$(this).removeClass('active');
});

div {
display: none;
}
.active {
display: block;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
&#13;
如果您使用该演示超过一分钟,您应该很快就会看到问题。
首先,对话框中的链接不可点击。试图单击它或选项卡到它将导致对话关闭在交互发生之前。这是因为在重新触发focusout
事件之前,聚焦内部元素会触发focusin
事件。
修复是在事件循环上对状态更改进行排队。对于不支持setImmediate(...)
的浏览器,可以使用setTimeout(..., 0)
或setImmediate
来完成此操作。排队后,可以通过后续focusin
$('.submenu').on({
focusout: function (e) {
$(this).data('submenuTimer', setTimeout(function () {
$(this).removeClass('submenu--active');
}.bind(this), 0));
},
focusin: function (e) {
clearTimeout($(this).data('submenuTimer'));
}
});
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
}
});
&#13;
div {
display: none;
}
.active {
display: block;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
&#13;
第二个问题是当再次按下链接时对话框不会关闭。这是因为对话框失去焦点,触发关闭行为,之后链接点击触发对话框重新打开。
与上一期相似,需要管理焦点状态。鉴于状态变化已经排队,只需要在对话框触发器上处理焦点事件:
这应该看起来很熟悉$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
}
});
$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
&#13;
div {
display: none;
}
.active {
display: block;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
&#13;
如果您认为自己是通过处理焦点状态来完成的,那么您可以采取更多措施来简化用户体验。
这通常是一个很好的“#34;功能,但是当你有任何类型的模态或弹出窗口时, Esc 键会关闭它。
keydown: function (e) {
if (e.which === 27) {
$(this).removeClass('active');
e.preventDefault();
}
}
$('a').on('click', function () {
$(this.hash).toggleClass('active').focus();
});
$('div').on({
focusout: function () {
$(this).data('timer', setTimeout(function () {
$(this).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('timer'));
},
keydown: function (e) {
if (e.which === 27) {
$(this).removeClass('active');
e.preventDefault();
}
}
});
$('a').on({
focusout: function () {
$(this.hash).data('timer', setTimeout(function () {
$(this.hash).removeClass('active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('timer'));
}
});
&#13;
div {
display: none;
}
.active {
display: block;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#example">Example</a>
<div id="example" tabindex="-1">
Lorem ipsum <a href="http://example.com">dolor</a> sit amet.
</div>
&#13;
如果您知道对话框中有可聚焦元素,则无需直接聚焦对话框。如果您正在构建菜单,则可以改为聚焦第一个菜单项。
click: function (e) {
$(this.hash)
.toggleClass('submenu--active')
.find('a:first')
.focus();
e.preventDefault();
}
$('.menu__link').on({
click: function (e) {
$(this.hash)
.toggleClass('submenu--active')
.find('a:first')
.focus();
e.preventDefault();
},
focusout: function () {
$(this.hash).data('submenuTimer', setTimeout(function () {
$(this.hash).removeClass('submenu--active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this.hash).data('submenuTimer'));
}
});
$('.submenu').on({
focusout: function () {
$(this).data('submenuTimer', setTimeout(function () {
$(this).removeClass('submenu--active');
}.bind(this), 0));
},
focusin: function () {
clearTimeout($(this).data('submenuTimer'));
},
keydown: function (e) {
if (e.which === 27) {
$(this).removeClass('submenu--active');
e.preventDefault();
}
}
});
&#13;
.menu {
list-style: none;
margin: 0;
padding: 0;
}
.menu:after {
clear: both;
content: '';
display: table;
}
.menu__item {
float: left;
position: relative;
}
.menu__link {
background-color: lightblue;
color: black;
display: block;
padding: 0.5em 1em;
text-decoration: none;
}
.menu__link:hover,
.menu__link:focus {
background-color: black;
color: lightblue;
}
.submenu {
border: 1px solid black;
display: none;
left: 0;
list-style: none;
margin: 0;
padding: 0;
position: absolute;
top: 100%;
}
.submenu--active {
display: block;
}
.submenu__item {
width: 150px;
}
.submenu__link {
background-color: lightblue;
color: black;
display: block;
padding: 0.5em 1em;
text-decoration: none;
}
.submenu__link:hover,
.submenu__link:focus {
background-color: black;
color: lightblue;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li class="menu__item">
<a class="menu__link" href="#menu-1">Menu 1</a>
<ul class="submenu" id="menu-1" tabindex="-1">
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#1">Example 1</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#2">Example 2</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#3">Example 3</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#4">Example 4</a></li>
</ul>
</li>
<li class="menu__item">
<a class="menu__link" href="#menu-2">Menu 2</a>
<ul class="submenu" id="menu-2" tabindex="-1">
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#1">Example 1</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#2">Example 2</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#3">Example 3</a></li>
<li class="submenu__item"><a class="submenu__link" href="http://example.com/#4">Example 4</a></li>
</ul>
</li>
</ul>
lorem ipsum <a href="http://example.com/">dolor</a> sit amet.
&#13;
这个答案有希望涵盖此功能的可访问键盘和鼠标支持的基础知识,但由于它已经相当大,我将避免讨论WAI-ARIA roles and attributes,但是我高度建议实施者参考规范,了解他们应该使用什么角色以及任何其他适当属性的详细信息。
答案 3 :(得分:136)
这里的其他解决方案对我不起作用,所以我不得不使用:
if(!$(event.target).is('#foo'))
{
// hide menu
}
答案 4 :(得分:123)
我有一个与Eran的例子类似的应用程序,除了我在打开菜单时将click事件附加到正文...有点像这样:
$('#menucontainer').click(function(event) {
$('html').one('click',function() {
// Hide the menus
});
event.stopPropagation();
});
的更多信息
答案 5 :(得分:38)
$("#menuscontainer").click(function() {
$(this).focus();
});
$("#menuscontainer").blur(function(){
$(this).hide();
});
对我来说很好。
答案 6 :(得分:37)
现在有一个插件:outside events(blog post)
将 clickoutside 处理程序(WLOG)绑定到元素时会发生以下情况:
因此没有任何事件停止传播,其他 click 处理程序可能会在带有外部处理程序的元素“上方”使用。
答案 7 :(得分:36)
经过研究,我找到了三个有效的解决方案(我忘了页面链接供参考)
<script>
//The good thing about this solution is it doesn't stop event propagation.
var clickFlag = 0;
$('body').on('click', function () {
if(clickFlag == 0) {
console.log('hide element here');
/* Hide element here */
}
else {
clickFlag=0;
}
});
$('body').on('click','#testDiv', function (event) {
clickFlag = 1;
console.log('showed the element');
/* Show the element */
});
</script>
<script>
$('body').on('click', function(e) {
if($(e.target).closest('#testDiv').length == 0) {
/* Hide dropdown here */
}
});
</script>
<script>
var specifiedElement = document.getElementById('testDiv');
document.addEventListener('click', function(event) {
var isClickInside = specifiedElement.contains(event.target);
if (isClickInside) {
console.log('You clicked inside')
}
else {
console.log('You clicked outside')
}
});
</script>
答案 8 :(得分:30)
这对我很有用!!
$('html').click(function (e) {
if (e.target.id == 'YOUR-DIV-ID') {
//do something
} else {
//do something
}
});
答案 9 :(得分:25)
我认为你真正需要的是当用户点击外面时关闭菜单;您需要的是当用户点击页面上的任何位置时关闭菜单。如果您单击菜单,或关闭菜单,它应该关闭吗?
上面没有找到令人满意的答案,促使我前几天写了this blog post。对于更迂腐的人来说,有许多值得注意的问题:
body { margin-left:auto; margin-right: auto; width:960px;}
答案 10 :(得分:24)
正如另一张海报所说,有很多陷阱,特别是如果您正在显示的元素(在这种情况下是菜单)具有交互元素。 我发现以下方法相当健壮:
$('#menuscontainer').click(function(event) {
//your code that shows the menus fully
//now set up an event listener so that clicking anywhere outside will close the menu
$('html').click(function(event) {
//check up the tree of the click target to check whether user has clicked outside of menu
if ($(event.target).parents('#menuscontainer').length==0) {
// your code to hide menu
//this event listener has done its job so we can unbind it.
$(this).unbind(event);
}
})
});
答案 11 :(得分:23)
针对这种情况的简单解决方案是:
$(document).mouseup(function (e)
{
var container = $("YOUR SELECTOR"); // Give you class or ID
if (!container.is(e.target) && // If the target of the click is not the desired div or section
container.has(e.target).length === 0) // ... nor a descendant-child of the container
{
container.hide();
}
});
如果触发div
点击事件之外,上述脚本将隐藏div
。
您可以在以下博客中找到更多信息:http://www.codecanal.com/detect-click-outside-div-using-javascript/
答案 12 :(得分:20)
不是使用可能有一些副作用的event.stopPropagation(),而是定义一个简单的标志变量并添加一个if
条件。我测试了这个并正常工作,没有任何副作用的停止:
var flag = "1";
$('#menucontainer').click(function(event){
flag = "0"; // flag 0 means click happened in the area where we should not do any action
});
$('html').click(function() {
if(flag != "0"){
// Hide the menus if visible
}
else {
flag = "1";
}
});
只有一个简单的if
条件:
$(document).on('click', function(event){
var container = $("#menucontainer");
if (!container.is(event.target) && // If the target of the click isn't the container...
container.has(event.target).length === 0) // ... nor a descendant of the container
{
// Do whatever you want to do when click is outside the element
}
});
答案 13 :(得分:19)
检查窗口点击事件目标(它应该传播到窗口,只要它没有在其他任何地方捕获),并确保它不是任何菜单元素。如果不是,那么你就在菜单之外了。
或者检查点击的位置,看看它是否包含在菜单区域中。
答案 14 :(得分:17)
我在这方面取得了成功:
var $menuscontainer = ...;
$('#trigger').click(function() {
$menuscontainer.show();
$('body').click(function(event) {
var $target = $(event.target);
if ($target.parents('#menuscontainer').length == 0) {
$menuscontainer.hide();
}
});
});
逻辑是:当显示#menuscontainer
时,仅当目标(点击)不是它的子项时,将点击处理程序绑定到隐藏#menuscontainer
的正文。
答案 15 :(得分:16)
作为变体:
var $menu = $('#menucontainer');
$(document).on('click', function (e) {
// If element is opened and click target is outside it, hide it
if ($menu.is(':visible') && !$menu.is(e.target) && !$menu.has(e.target).length) {
$menu.hide();
}
});
stopping event propagation没有问题,并且更好地支持同一页面上的多个菜单,当第一个菜单打开时点击第二个菜单会在stopPropagation解决方案中保留第一个菜单。
答案 16 :(得分:13)
我在一些jQuery日历插件中找到了这个方法。
function ClickOutsideCheck(e)
{
var el = e.target;
var popup = $('.popup:visible')[0];
if (popup==undefined)
return true;
while (true){
if (el == popup ) {
return true;
} else if (el == document) {
$(".popup").hide();
return false;
} else {
el = $(el).parent()[0];
}
}
};
$(document).bind('mousedown.popup', ClickOutsideCheck);
答案 17 :(得分:12)
以下是面向未来观众的vanilla JavaScript解决方案。
单击文档中的任何元素后,如果切换了单击元素的id,或隐藏的元素未隐藏且隐藏元素不包含单击的元素,则切换元素。
(function () {
"use strict";
var hidden = document.getElementById('hidden');
document.addEventListener('click', function (e) {
if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
}, false);
})();
(function () {
"use strict";
var hidden = document.getElementById('hidden');
document.addEventListener('click', function (e) {
if (e.target.id == 'toggle' || (hidden.style.display != 'none' && !hidden.contains(e.target))) hidden.style.display = hidden.style.display == 'none' ? 'block' : 'none';
}, false);
})();
<a href="javascript:void(0)" id="toggle">Toggle Hidden Div</a>
<div id="hidden" style="display: none;">This content is normally hidden. click anywhere other than this content to make me disappear</div>
如果您要在同一页面上进行多次切换,可以使用以下内容:
hidden
添加到可折叠项目。
(function () {
"use strict";
var hiddenItems = document.getElementsByClassName('hidden'), hidden;
document.addEventListener('click', function (e) {
for (var i = 0; hidden = hiddenItems[i]; i++) {
if (!hidden.contains(e.target) && hidden.style.display != 'none')
hidden.style.display = 'none';
}
if (e.target.getAttribute('data-toggle')) {
var toggle = document.querySelector(e.target.getAttribute('data-toggle'));
toggle.style.display = toggle.style.display == 'none' ? 'block' : 'none';
}
}, false);
})();
<a href="javascript:void(0)" data-toggle="#hidden1">Toggle Hidden Div</a>
<div class="hidden" id="hidden1" style="display: none;" data-hidden="true">This content is normally hidden</div>
<a href="javascript:void(0)" data-toggle="#hidden2">Toggle Hidden Div</a>
<div class="hidden" id="hidden2" style="display: none;" data-hidden="true">This content is normally hidden</div>
<a href="javascript:void(0)" data-toggle="#hidden3">Toggle Hidden Div</a>
<div class="hidden" id="hidden3" style="display: none;" data-hidden="true">This content is normally hidden</div>
答案 18 :(得分:12)
event.composedPath()
来自:https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath
Event接口的compositionPath()方法返回事件的路径,该路径是将在其上调用侦听器的对象的数组。
const target = document.querySelector('#myTarget')
document.addEventListener('click', (event) => {
const withinBoundaries = event.composedPath().includes(target)
if (withinBoundaries) {
target.innerText = 'Click happened inside element'
} else {
target.innerText = 'Click happened **OUTSIDE** element'
}
})
/* just to make it good looking. you don't need this */
#myTarget {
margin: 50px auto;
width: 500px;
height: 500px;
background: gray;
border: 10px solid black;
}
<div id="myTarget">
click me (or not!)
</div>
答案 19 :(得分:12)
该事件有一个名为event.path的属性,该属性是“树序所有祖先的静态有序列表”。要检查事件是源自特定DOM元素还是其中一个子元素,只需检查该特定DOM元素的路径。它还可以用于通过OR
函数逻辑some
元素检查来检查多个元素。
$("body").click(function() {
target = document.getElementById("main");
flag = event.path.some(function(el, i, arr) {
return (el == target)
})
if (flag) {
console.log("Inside")
} else {
console.log("Outside")
}
});
#main {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<ul>
<li>Test-Main</li>
<li>Test-Main</li>
<li>Test-Main</li>
<li>Test-Main</li>
<li>Test-Main</li>
</ul>
</div>
<div id="main2">
Outside Main
</div>
所以对于你的情况应该是
$("body").click(function() {
target = $("#menuscontainer")[0];
flag = event.path.some(function(el, i, arr) {
return (el == target)
});
if (!flag) {
// Hide the menus
}
});
答案 20 :(得分:9)
我很惊讶没有人真正承认focusout
事件:
var button = document.getElementById('button');
button.addEventListener('click', function(e){
e.target.style.backgroundColor = 'green';
});
button.addEventListener('focusout', function(e){
e.target.style.backgroundColor = '';
});
&#13;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<button id="button">Click</button>
</body>
</html>
&#13;
答案 21 :(得分:8)
相反,使用流动中断,模糊/焦点事件或任何其他棘手的技术,只需将事件流与元素的亲缘关系匹配:
$(document).on("click.menu-outside", function(event){
// Test if target and it's parent aren't #menuscontainer
// That means the click event occur on other branch of document tree
if(!$(event.target).parents().andSelf().is("#menuscontainer")){
// Click outisde #menuscontainer
// Hide the menus (but test if menus aren't already hidden)
}
});
要删除单击外部事件侦听器,只需:
$(document).off("click.menu-outside");
答案 22 :(得分:8)
如果您是IE和FF 3. *的脚本,并且您只想知道某个框区域内是否发生了点击,您还可以使用以下内容:
this.outsideElementClick = function(objEvent, objElement){
var objCurrentElement = objEvent.target || objEvent.srcElement;
var blnInsideX = false;
var blnInsideY = false;
if (objCurrentElement.getBoundingClientRect().left >= objElement.getBoundingClientRect().left && objCurrentElement.getBoundingClientRect().right <= objElement.getBoundingClientRect().right)
blnInsideX = true;
if (objCurrentElement.getBoundingClientRect().top >= objElement.getBoundingClientRect().top && objCurrentElement.getBoundingClientRect().bottom <= objElement.getBoundingClientRect().bottom)
blnInsideY = true;
if (blnInsideX && blnInsideY)
return false;
else
return true;}
答案 23 :(得分:8)
使用:
var go = false;
$(document).click(function(){
if(go){
$('#divID').hide();
go = false;
}
})
$("#divID").mouseover(function(){
go = false;
});
$("#divID").mouseout(function (){
go = true;
});
$("btnID").click( function(){
if($("#divID:visible").length==1)
$("#divID").hide(); // Toggle
$("#divID").show();
});
答案 24 :(得分:6)
在文档上挂钩单击事件侦听器。在事件监听器中,您可以查看event object,尤其是event.target,以查看点击的元素:
$(document).click(function(e){
if ($(e.target).closest("#menuscontainer").length == 0) {
// .closest can help you determine if the element
// or one of its ancestors is #menuscontainer
console.log("hide");
}
});
答案 25 :(得分:5)
$(document).click(function() {
$(".overlay-window").hide();
});
$(".overlay-window").click(function() {
return false;
});
如果单击文档,则隐藏给定元素,除非您单击该元素。
答案 26 :(得分:5)
如果有人好奇这里是javascript解决方案(es6):
window.addEventListener('mouseup', e => {
if (e.target != yourDiv && e.target.parentNode != yourDiv) {
yourDiv.classList.remove('show-menu');
//or yourDiv.style.display = 'none';
}
})
和es5,以防万一:
window.addEventListener('mouseup', function (e) {
if (e.target != yourDiv && e.target.parentNode != yourDiv) {
yourDiv.classList.remove('show-menu');
//or yourDiv.style.display = 'none';
}
});
答案 27 :(得分:5)
我在YUI 3中这样做了:
// Detect the click anywhere other than the overlay element to close it.
Y.one(document).on('click', function (e) {
if (e.target.ancestor('#overlay') === null && e.target.get('id') != 'show' && overlay.get('visible') == true) {
overlay.hide();
}
});
我正在检查祖先是不是小部件元素容器,
如果target不是打开小部件/元素的目标,
如果我要关闭的小部件/元素已经打开(不那么重要)。
答案 28 :(得分:5)
Upvote获得最受欢迎的答案,但添加
&& (e.target != $('html').get(0)) // ignore the scrollbar
所以,点击滚动条不会[隐藏或者不管]你的目标元素。
答案 29 :(得分:5)
为了更容易使用,以及更具表现力的代码,我为此创建了一个jQuery插件:
$('div.my-element').clickOut(function(target) {
//do something here...
});
注意:目标是用户实际点击的元素。但回调仍然在原始元素的上下文中执行,因此您可以在jQuery回调中使用 this 。
插件:
$.fn.clickOut = function (parent, fn) {
var context = this;
fn = (typeof parent === 'function') ? parent : fn;
parent = (parent instanceof jQuery) ? parent : $(document);
context.each(function () {
var that = this;
parent.on('click', function (e) {
var clicked = $(e.target);
if (!clicked.is(that) && !clicked.parents().is(that)) {
if (typeof fn === 'function') {
fn.call(that, clicked);
}
}
});
});
return context;
};
默认情况下,click事件侦听器放在文档上。但是,如果要限制事件侦听器作用域,则可以传入表示父级别元素的jQuery对象,该父级别元素将成为将侦听单击的顶级父级。这可以防止不必要的文档级事件侦听器。显然,除非提供的父元素是初始元素的父元素,否则它不会起作用。
像这样使用:
$('div.my-element').clickOut($('div.my-parent'), function(target) {
//do something here...
});
答案 30 :(得分:5)
我使用下面的脚本并使用jQuery完成。
<div class="main-container">
<div> Hello I am the title</div>
<div class="tobehide">I will hide when you click outside of me</div>
</div>
下面找到HTML代码
{{1}}
您可以阅读教程here
答案 31 :(得分:4)
这是我解决这个问题的方法:
$(document).ready(function() {
$('#user-toggle').click(function(e) {
$('#user-nav').toggle();
e.stopPropagation();
});
$('body').click(function() {
$('#user-nav').hide();
});
$('#user-nav').click(function(e){
e.stopPropagation();
});
});
答案 32 :(得分:4)
我们实施了一个解决方案,部分基于上述用户的评论,这对我们来说非常有效。我们使用它来隐藏搜索框/结果,当在这些元素外部单击时,不包括最初的元素。
// HIDE SEARCH BOX IF CLICKING OUTSIDE
$(document).click(function(event){
// IF NOT CLICKING THE SEARCH BOX OR ITS CONTENTS OR SEARCH ICON
if ($("#search-holder").is(":visible") && !$(event.target).is("#search-holder *, #search")) {
$("#search-holder").fadeOut('fast');
$("#search").removeClass('active');
}
});
它还会先检查搜索框是否已经可见,在我们的例子中,它还会删除隐藏/显示搜索按钮上的活动类。
答案 33 :(得分:4)
2020解决方案。
document.addEventListener('click', ({ target }) => {
if (!target.closest('.el1, .el2, #el3')) {
alert('click outside')
}
})
答案 34 :(得分:4)
功能:
$(function() {
$.fn.click_inout = function(clickin_handler, clickout_handler) {
var item = this;
var is_me = false;
item.click(function(event) {
clickin_handler(event);
is_me = true;
});
$(document).click(function(event) {
if (is_me) {
is_me = false;
} else {
clickout_handler(event);
}
});
return this;
}
});
用法:
this.input = $('<input>')
.click_inout(
function(event) { me.ShowTree(event); },
function() { me.Hide(); }
)
.appendTo(this.node);
功能非常简单:
ShowTree: function(event) {
this.data_span.show();
}
Hide: function() {
this.data_span.hide();
}
答案 35 :(得分:4)
以下是纯javascript的简单解决方案。它与ES6 最新:
var isMenuClick = false;
var menu = document.getElementById('menuscontainer');
document.addEventListener('click',()=>{
if(!isMenuClick){
//Hide the menu here
}
//Reset isMenuClick
isMenuClick = false;
})
menu.addEventListener('click',()=>{
isMenuClick = true;
})
答案 36 :(得分:4)
以下是我要解决的问题。
$(window).click(function (event) {
//To improve performance add a checklike
//if(myElement.isClosed) return;
var isClickedElementChildOfMyBox = isChildOfElement(event,'#id-of-my-element');
if (isClickedElementChildOfMyBox)
return;
//your code to hide the element
});
var isChildOfElement = function (event, selector) {
if (event.originalEvent.path) {
return event.originalEvent.path[0].closest(selector) !== null;
}
return event.originalEvent.originalTarget.closest(selector) !== null;
}
答案 37 :(得分:4)
我最终做了这样的事情:
$(document).on('click', 'body, #msg_count_results .close',function() {
$(document).find('#msg_count_results').remove();
});
$(document).on('click','#msg_count_results',function(e) {
e.preventDefault();
return false;
});
我在新容器中有一个关闭按钮,供最终用户友好的UI用途。我不得不使用return false以便不通过。当然,在那里拥有A HREF带你到某个地方会很好,或者你可以调用一些ajax的东西。无论哪种方式,它对我都有效。正是我想要的。
答案 38 :(得分:4)
当只需要管理一个元素时,此处的解决方案可以正常工作。但是,如果存在多个元素,则问题会复杂得多。 e.stopPropagation()和其他所有技巧都不起作用。
我想出了一个解决方案,也许这不是那么容易,但它总比没有好。看看:
$view.on("click", function(e) {
if(model.isActivated()) return;
var watchUnclick = function() {
rootView.one("mouseleave", function() {
$(document).one("click", function() {
model.deactivate();
});
rootView.one("mouseenter", function() {
watchUnclick();
});
});
};
watchUnclick();
model.activate();
});
答案 39 :(得分:4)
这应该有效:
$('body').click(function (event) {
var obj = $(event.target);
obj = obj['context']; // context : clicked element inside body
if ($(obj).attr('id') != "menuscontainer" && $('#menuscontainer').is(':visible') == true) {
//hide menu
}
});
答案 40 :(得分:3)
我只想让@Pistos的回答更加明显,因为它隐藏在评论中。
这个解决方案非常适合我。简单JS:
var elementToToggle = $('.some-element');
$(document).click( function(event) {
if( $(event.target).closest(elementToToggle).length === 0 ) {
elementToToggle.hide();
}
});
在CoffeeScript中:
elementToToggle = $('.some-element')
$(document).click (event) ->
if $(event.target).closest(elementToToggle).length == 0
elementToToggle.hide()
答案 41 :(得分:3)
这对我有用
$("body").mouseup(function(e) {
var subject = $(".main-menu");
if(e.target.id != subject.attr('id') && !subject.has(e.target).length) {
$('.sub-menu').hide();
}
});
答案 42 :(得分:3)
我知道这个问题有一百万个答案,但我一直都喜欢使用HTML和CSS来完成大部分工作。在这种情况下,z-index和定位。我发现这样做的最简单方法如下:
$("#show-trigger").click(function(){
$("#element").animate({width: 'toggle'});
$("#outside-element").show();
});
$("#outside-element").click(function(){
$("#element").hide();
$("#outside-element").hide();
});
&#13;
#outside-element {
position:fixed;
width:100%;
height:100%;
z-index:1;
display:none;
}
#element {
display:none;
padding:20px;
background-color:#ccc;
width:300px;
z-index:2;
position:relative;
}
#show-trigger {
padding:20px;
background-color:#ccc;
margin:20px auto;
z-index:2;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="outside-element"></div>
<div id="element">
<div class="menu-item"><a href="#1">Menu Item 1</a></div>
<div class="menu-item"><a href="#2">Menu Item 1</a></div>
<div class="menu-item"><a href="#3">Menu Item 1</a></div>
<div class="menu-item"><a href="#4">Menu Item 1</a></div>
</div>
<div id="show-trigger">Show Menu</div>
&#13;
这创建了一个安全的环境,因为除非菜单实际打开并且z-index保护元素中的任何内容在被点击时不会产生任何失火,否则不会触发任何内容。
此外,您不需要jQuery通过传播调用来覆盖所有基础,并且必须清除所有内部元素以防止失火。
答案 43 :(得分:3)
如果您使用&#34; Pop-up&#34;等工具,您可以使用&#34; onFocusOut&#34;事件
window.onload=function(){
document.getElementById("inside-div").focus();
}
function loseFocus(){
alert("Clicked outside");
}
&#13;
#container{
background-color:lightblue;
width:200px;
height:200px;
}
#inside-div{
background-color:lightgray;
width:100px;
height:100px;
}
&#13;
<div id="container">
<input type="text" id="inside-div" onfocusout="loseFocus()">
</div>
&#13;
答案 44 :(得分:3)
$(document).on("click",function (event)
{
console.log(event);
if ($(event.target).closest('.element').length == 0)
{
//your code here
if ($(".element").hasClass("active"))
{
$(".element").removeClass("active");
}
}
});
尝试使用此编码来获得解决方案。
答案 45 :(得分:3)
此处还有一个解决方案:
用法:
<div onClick="$('#menu').toggle();$('#menu').clickOutside(function() { $(this).hide(); $(this).clickOutside('disable'); });">Open / Close Menu</div>
<div id="menu" style="display: none; border: 1px solid #000000; background: #660000;">I am a menu, whoa is me.</div>
插件:
(function($) {
var clickOutsideElements = [];
var clickListener = false;
$.fn.clickOutside = function(options, ignoreFirstClick) {
var that = this;
if (ignoreFirstClick == null) ignoreFirstClick = true;
if (options != "disable") {
for (var i in clickOutsideElements) {
if (clickOutsideElements[i].element[0] == $(this)[0]) return this;
}
clickOutsideElements.push({ element : this, clickDetected : ignoreFirstClick, fnc : (typeof(options) != "function") ? function() {} : options });
$(this).on("click.clickOutside", function(event) {
for (var i in clickOutsideElements) {
if (clickOutsideElements[i].element[0] == $(this)[0]) {
clickOutsideElements[i].clickDetected = true;
}
}
});
if (!clickListener) {
if (options != null && typeof(options) == "function") {
$('html').click(function() {
for (var i in clickOutsideElements) {
if (!clickOutsideElements[i].clickDetected) {
clickOutsideElements[i].fnc.call(that);
}
if (clickOutsideElements[i] != null) clickOutsideElements[i].clickDetected = false;
}
});
clickListener = true;
}
}
}
else {
$(this).off("click.clickoutside");
for (var i = 0; i < clickOutsideElements.length; ++i) {
if (clickOutsideElements[i].element[0] == $(this)[0]) {
clickOutsideElements.splice(i, 1);
}
}
}
return this;
}
})(jQuery);
答案 46 :(得分:3)
标记为已接受答案的答案没有考虑到您可以在元素上叠加,例如对话框,弹出窗口,日期选择器等。这些中的单击不应隐藏元素。
我已经制作了自己的版本,并考虑到了这一点。它是作为KnockoutJS绑定创建的,但它可以很容易地转换为仅jQuery。
它通过对具有可见的z-index或绝对位置的所有元素的第一个查询起作用。然后,如果点击外部,它会针对我要隐藏的元素测试这些元素。如果它是一个命中我计算一个新的绑定矩形,它考虑了重叠边界。
ko.bindingHandlers.clickedIn = (function () {
function getBounds(element) {
var pos = element.offset();
return {
x: pos.left,
x2: pos.left + element.outerWidth(),
y: pos.top,
y2: pos.top + element.outerHeight()
};
}
function hitTest(o, l) {
function getOffset(o) {
for (var r = { l: o.offsetLeft, t: o.offsetTop, r: o.offsetWidth, b: o.offsetHeight };
o = o.offsetParent; r.l += o.offsetLeft, r.t += o.offsetTop);
return r.r += r.l, r.b += r.t, r;
}
for (var b, s, r = [], a = getOffset(o), j = isNaN(l.length), i = (j ? l = [l] : l).length; i;
b = getOffset(l[--i]), (a.l == b.l || (a.l > b.l ? a.l <= b.r : b.l <= a.r))
&& (a.t == b.t || (a.t > b.t ? a.t <= b.b : b.t <= a.b)) && (r[r.length] = l[i]));
return j ? !!r.length : r;
}
return {
init: function (element, valueAccessor) {
var target = valueAccessor();
$(document).click(function (e) {
if (element._clickedInElementShowing === false && target()) {
var $element = $(element);
var bounds = getBounds($element);
var possibleOverlays = $("[style*=z-index],[style*=absolute]").not(":hidden");
$.each(possibleOverlays, function () {
if (hitTest(element, this)) {
var b = getBounds($(this));
bounds.x = Math.min(bounds.x, b.x);
bounds.x2 = Math.max(bounds.x2, b.x2);
bounds.y = Math.min(bounds.y, b.y);
bounds.y2 = Math.max(bounds.y2, b.y2);
}
});
if (e.clientX < bounds.x || e.clientX > bounds.x2 ||
e.clientY < bounds.y || e.clientY > bounds.y2) {
target(false);
}
}
element._clickedInElementShowing = false;
});
$(element).click(function (e) {
e.stopPropagation();
});
},
update: function (element, valueAccessor) {
var showing = ko.utils.unwrapObservable(valueAccessor());
if (showing) {
element._clickedInElementShowing = true;
}
}
};
})();
答案 47 :(得分:3)
对于iPad和iPhone等触控设备,我们可以使用以下代码:
$(document).on('touchstart', function (event) {
var container = $("YOUR CONTAINER SELECTOR");
if (!container.is(e.target) && // If the target of the click isn't the container...
container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.hide();
}
});
答案 48 :(得分:2)
说实话,我不喜欢以前的任何解决方案。
执行此操作的最佳方法是将“click”事件绑定到文档,并比较该点击是否真的在元素之外(就像Art在他的建议中所说的那样)。
然而,你会遇到一些问题:你永远无法解开它,你也无法使用外部按钮打开/关闭该元素。
这就是为什么我写this small plugin (click here to link)来简化这些任务的原因。它会更简单吗?
<a id='theButton' href="#">Toggle the menu</a><br/>
<div id='theMenu'>
I should be toggled when the above menu is clicked,
and hidden when user clicks outside.
</div>
<script>
$('#theButton').click(function(){
$('#theMenu').slideDown();
});
$("#theMenu").dClickOutside({ ignoreList: $("#theButton") }, function(clickedObj){
$(this).slideUp();
});
</script>
答案 49 :(得分:2)
最广泛的方法是选择网页上除了您不希望检测到点击次数的元素之外的所有内容,并在打开菜单时绑定点击事件。
然后当菜单关闭时,取消绑定。
使用.stopPropagation来防止事件影响菜单容器的任何部分。
$("*").not($("#menuscontainer")).bind("click.OutsideMenus", function ()
{
// hide the menus
//then remove all of the handlers
$("*").unbind(".OutsideMenus");
});
$("#menuscontainer").bind("click.OutsideMenus", function (event)
{
event.stopPropagation();
});
答案 50 :(得分:2)
我相信这样做的最佳方法就是这样。
$(document).on("click", function(event) {
clickedtarget = $(event.target).closest('#menuscontainer');
$("#menuscontainer").not(clickedtarget).hide();
});
这种类型的解决方案可以轻松地用于多个菜单以及通过javascript动态添加的菜单。基本上它只允许您单击文档中的任何位置,并检查您单击的元素,并选择它最接近的“#menuscontainer”。然后它会隐藏所有菜单容器,但不包括您单击的那个。
不确定您的菜单是如何构建的,但可以随意在JSFiddle中复制我的代码。这是一个非常简单但功能齐全的菜单/模态系统。您需要做的就是构建html菜单,代码将为您完成工作。
答案 51 :(得分:2)
对某些人来说,这可能是一个更好的解决方法。
$(".menu_link").click(function(){
// show menu code
});
$(".menu_link").mouseleave(function(){
//hide menu code, you may add a timer for 3 seconds before code to be run
});
我知道mouseleave不仅意味着在外面点击,还意味着离开该元素的区域。
一旦菜单本身位于menu_link
元素内,则菜单本身不应成为点击或继续前进的问题。
答案 52 :(得分:2)
focusout
提高可访问性这里有一个答案(完全正确)说,关注 click
事件是一个可访问性问题,因为我们想要满足键盘用户的需求。 focusout
事件在这里使用是正确的,但它可以比在其他答案中更简单地完成(在纯 JavaScript 中也是如此):
使用 focusout
的“问题”是,如果对话框/模态/菜单中的元素失去焦点,那么“内部”的事件仍然会被触发。我们可以通过查看 event.relatedTarget
(它告诉我们哪个元素将获得焦点)来检查情况并非如此。
dialog = document.getElementById("dialogElement")
dialog.addEventListener("focusout", function (event) {
if (
// we are still inside the dialog so don't close
dialog.contains(event.relatedTarget) ||
// we have switched to another tab so probably don't want to close
!document.hasFocus()
) {
return;
}
dialog.close(); // or whatever logic you want to use to close
});
上面有一个小问题,那就是 relatedTarget
可能是 null
。如果用户在对话框外单击,这很好,但如果用户在对话框内单击并且对话框碰巧不可聚焦,则会出现问题。要解决此问题,您必须确保设置 tabIndex=0
以使您的对话框可聚焦。
答案 53 :(得分:2)
$('#propertyType').on("click",function(e){
self.propertyTypeDialog = !self.propertyTypeDialog;
b = true;
e.stopPropagation();
console.log("input clicked");
});
$(document).on('click','body:not(#propertyType)',function (e) {
e.stopPropagation();
if(b == true) {
if ($(e.target).closest("#configuration").length == 0) {
b = false;
self.propertyTypeDialog = false;
console.log("outside clicked");
}
}
// console.log($(e.target).closest("#configuration").length);
});
答案 54 :(得分:2)
jQuery().ready(function(){
$('#nav').click(function (event) {
$(this).addClass('activ');
event.stopPropagation();
});
$('html').click(function () {
if( $('#nav').hasClass('activ') ){
$('#nav').removeClass('activ');
}
});
});
答案 55 :(得分:2)
这对我来说非常合适:
$('body').click(function() {
// Hide the menus if visible.
});
答案 56 :(得分:2)
假设您要检测的div是用户在外部还是内部单击的ID,例如:“ my-special-widget”。
听身体点击事件:
for b in zip(zip(*zip(*a))):
...: print(b)
...:
((<range_iterator object at 0x2b688d65b630>, <range_iterator object at 0x2b688d65b7e0>, <range_iterator object at 0x2b688d65b540>),)
((<range_iterator object at 0x2b688d65ba50>, <range_iterator object at 0x2b688d65b6f0>, <range_iterator object at 0x2b688d65b0c0>),)
在这种情况下,您不会中断页面中某些元素的正常点击流程,因为您没有使用“ stopPropagation”方法。
答案 57 :(得分:2)
这是我的代码:
// Listen to every click
$('html').click(function(event) {
if ( $('#mypopupmenu').is(':visible') ) {
if (event.target.id != 'click_this_to_show_mypopupmenu') {
$('#mypopupmenu').hide();
}
}
});
// Listen to selector's clicks
$('#click_this_to_show_mypopupmenu').click(function() {
// If the menu is visible, and you clicked the selector again we need to hide
if ( $('#mypopupmenu').is(':visible') {
$('#mypopupmenu').hide();
return true;
}
// Else we need to show the popup menu
$('#mypopupmenu').show();
});
答案 58 :(得分:1)
所有这些答案都可以解决问题,但我想贡献一个能真正满足需要的现代es6解决方案。我只是希望让某人对此可运行的演示感到满意。
window.clickOutSide = (element, clickOutside, clickInside) => {
document.addEventListener('click', (event) => {
if (!element.contains(event.target)) {
if (typeof clickInside === 'function') {
clickOutside();
}
} else {
if (typeof clickInside === 'function') {
clickInside();
}
}
});
};
window.clickOutSide(document.querySelector('.block'), () => alert('clicked outside'), () => alert('clicked inside'));
.block {
width: 400px;
height: 400px;
background-color: red;
}
<div class="block"></div>
答案 59 :(得分:1)
隐藏fileTreeClass
如果在其外部点击
jQuery(document).mouseup(function (e) {
var container = $(".fileTreeClass");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
container.hide();
}
});
答案 60 :(得分:1)
简单的插件:
$.fn.clickOff = function(callback, selfDestroy) {
var clicked = false;
var parent = this;
var destroy = selfDestroy || true;
parent.click(function() {
clicked = true;
});
$(document).click(function(event) {
if (!clicked && parent.is(':visible')) {
if(callback) callback.call(parent, event)
}
if (destroy) {
//parent.clickOff = function() {};
//parent.off("click");
//$(document).off("click");
parent.off("clickOff");
}
clicked = false;
});
};
使用:
$("#myDiv").clickOff(function() {
alert('clickOff');
});
答案 61 :(得分:1)
还在寻找用于检测外部点击的完美解决方案吗?别再看了!引入了Clickout-Event,这是一个为点击事件和其他类似事件提供通用支持的软件包,它可以在所有场景中使用:纯HTML onclickout
属性,.addEventListener('clickout')
普通您将其命名为JavaScript,jQuery的.on('clickout')
,Vue.js的v-on:clickout
指令。只要前端框架内部使用addEventListener
来处理事件,Clickout-Event都可以使用。只需在页面中的任意位置添加脚本标签,它就可以像魔术一样工作。
HTML属性
<div onclickout="console.log('clickout detected')">...</div>
Vanilla JavaScript
document.getElementById('myId').addEventListener('clickout', myListener);
jQuery
$('#myId').on('clickout', myListener);
Vue.js
<div v-on:clickout="open=false">...</div>
角度
<div (clickout)="close()">...</div>
答案 62 :(得分:0)
一种用纯 JavaScript 编写的方法
let menu = document.getElementById("menu");
document.addEventListener("click", function(){
// Hide the menus
menu.style.display = "none";
}, false);
document.getElementById("menuscontainer").addEventListener("click", function(e){
// Show the menus
menu.style.display = "block";
e.stopPropagation();
}, false);
答案 63 :(得分:0)
const button = document.querySelector('button')
const box = document.querySelector('.box');
const toggle = event => {
event.stopPropagation();
if (!event.target.closest('.box')) {
console.log('Click outside');
box.classList.toggle('active');
box.classList.contains('active')
? document.addEventListener('click', toggle)
: document.removeEventListener('click', toggle);
} else {
console.log('Click inside');
}
}
button.addEventListener('click', toggle);
.box {
position: absolute;
display: none;
margin-top: 8px;
padding: 20px;
background: lightgray;
}
.box.active {
display: block;
}
<button>Toggle box</button>
<div class="box">
<form action="">
<input type="text">
<button type="button">Search</button>
</form>
</div>
答案 64 :(得分:0)
这是我对这个问题找到的最简单的答案:
window.addEventListener('click', close_window = function () {
if(event.target !== windowEl){
windowEl.style.display = "none";
window.removeEventListener('click', close_window, false);
}
});
您将看到我将函数命名为“close_window”,以便在窗口关闭时删除事件侦听器。
答案 65 :(得分:0)
我已经阅读了 2021 年的所有内容,但如果没有错,没有人建议像这样简单的方法来解除绑定和删除事件。使用上面的两个答案和一个更多的小技巧,所以把所有的都放在一个(也可以在函数中添加参数以传递选择器,以获得更多的弹出窗口)。 可能有人知道这个笑话也可以通过这种方式完成:
<div id="container" style="display:none"><h1>my menu is nice but disappear if i click outside it</h1></div>
<script>
function printPopup(){
$("#container").css({ "display":"block" });
var remListener = $(document).mouseup(function (e) {
if ($(e.target).closest("#container").length === 0 && (e.target != $('html').get(0)))
{
//alert('closest call');
$("#container").css({ "display":"none" });
remListener.unbind('mouseup'); // isn't it?
}
});
}
printPopup();
</script>
干杯
答案 66 :(得分:0)
这对我来说很好。我不是专家。
$(document).click(function(event) {
var $target = $(event.target);
if(!$target.closest('#hamburger, a').length &&
$('#hamburger, a').is(":visible")) {
$('nav').slideToggle();
}
});
答案 67 :(得分:0)
首先,您必须使用mouseenter和mouseleave事件跟踪鼠标在element1内部还是外部。 然后,您可以创建一个element2,该元素覆盖整个屏幕以检测任何单击,并根据您是在element1内部还是外部进行相应的反应。
出于明显的原因,我强烈建议同时处理初始化和清理工作,并尽可能将element2设为临时。
在下面的示例中,叠加层是放置在某处的元素,可以通过单击内部来选择,而通过单击外部来取消选择。 _init和_release方法被称为自动初始化/清除过程的一部分。 该类继承自具有内部元素和外部元素的ClickOverlay,请不必担心。我使用externalElement.parentNode.appendChild来避免冲突。
import ClickOverlay from './ClickOverlay.js'
/* CSS */
// .unselect-helper {
// position: fixed; left: -100vw; top: -100vh;
// width: 200vw; height: 200vh;
// }
// .selected {outline: 1px solid black}
export default class ResizeOverlay extends ClickOverlay {
_init(_opts) {
this.enterListener = () => this.onEnter()
this.innerElement.addEventListener('mouseenter', this.enterListener)
this.leaveListener = () => this.onLeave()
this.innerElement.addEventListener('mouseleave', this.leaveListener)
this.selectListener = () => {
if (this.unselectHelper)
return
this.unselectHelper = document.createElement('div')
this.unselectHelper.classList.add('unselect-helper')
this.unselectListener = () => {
if (this.mouseInside)
return
this.clearUnselectHelper()
this.onUnselect()
}
this.unselectHelper.addEventListener('pointerdown'
, this.unselectListener)
this.outerElement.parentNode.appendChild(this.unselectHelper)
this.onSelect()
}
this.innerElement.addEventListener('pointerup', this.selectListener)
}
_release() {
this.innerElement.removeEventListener('mouseenter', this.enterListener)
this.innerElement.removeEventListener('mouseleave', this.leaveListener)
this.innerElement.removeEventListener('pointerup', this.selectListener)
this.clearUnselectHelper()
}
clearUnselectHelper() {
if (!this.unselectHelper)
return
this.unselectHelper.removeEventListener('pointerdown'
, this.unselectListener)
this.unselectHelper.remove()
delete this.unselectListener
delete this.unselectHelper
}
onEnter() {
this.mouseInside = true
}
onLeave() {
delete this.mouseInside
}
onSelect() {
this.innerElement.classList.add('selected')
}
onUnselect() {
this.innerElement.classList.remove('selected')
}
}
答案 68 :(得分:0)
最简单的方法:mouseleave(function())
答案 69 :(得分:0)
$(document).on('click.menu.hide', function(e){
if ( !$(e.target).closest('#my_menu').length ) {
$('#my_menu').find('ul').toggleClass('active', false);
}
});
$(document).on('click.menu.show', '#my_menu li', function(e){
$(this).find('ul').toggleClass('active');
});
div {
float: left;
}
ul {
padding: 0;
position: relative;
}
ul li {
padding: 5px 25px 5px 10px;
border: 1px solid silver;
cursor: pointer;
list-style: none;
margin-top: -1px;
white-space: nowrap;
}
ul li ul:before {
margin-right: -20px;
position: absolute;
top: -17px;
right: 0;
content: "\25BC";
}
ul li ul li {
visibility: hidden;
height: 0;
padding-top: 0;
padding-bottom: 0;
border-width: 0 0 1px 0;
}
ul li ul li:last-child {
border: none;
}
ul li ul.active:before {
content: "\25B2";
}
ul li ul.active li {
display: list-item;
visibility: visible;
height: inherit;
padding: 5px 25px 5px 10px;
}
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<div>
<ul id="my_menu">
<li>Menu 1
<ul>
<li>subMenu 1</li>
<li>subMenu 2</li>
<li>subMenu 3</li>
<li>subMenu 4</li>
</ul>
</li>
<li>Menu 2
<ul>
<li>subMenu 1</li>
<li>subMenu 2</li>
<li>subMenu 3</li>
<li>subMenu 4</li>
</ul>
</li>
<li>Menu 3</li>
<li>Menu 4</li>
<li>Menu 5</li>
<li>Menu 6</li>
</ul>
</div>
这是jsbin版本http://jsbin.com/xopacadeni/edit?html,css,js,output
答案 70 :(得分:0)
只是警告使用它:
$('html').click(function() {
// Hide the menus if visible
});
$('#menucontainer').click(function(event){
event.stopPropagation();
});
阻止 Ruby on Rails UJS驱动程序正常工作。例如,link_to 'click', '/url', :method => :delete
将无效。
这可能是一种解决方法:
$('html').click(function() {
// Hide the menus if visible
});
$('#menucontainer').click(function(event){
if (!$(event.target).data('method')) {
event.stopPropagation();
}
});
答案 71 :(得分:0)
这是一个更通用的解决方案,允许观看多个元素,并动态添加和删除队列中的元素。
它拥有一个全局队列( autoCloseQueue ) - 一个对象容器,用于在外部点击时应关闭的元素。
每个队列对象键应该是DOM元素id,值应该是具有2个回调函数的对象:
{onPress: someCallbackFunction, onOutsidePress: anotherCallbackFunction}
将此文件放入文档就绪回调中:
window.autoCloseQueue = {}
$(document).click(function(event) {
for (id in autoCloseQueue){
var element = autoCloseQueue[id];
if ( ($(e.target).parents('#' + id).length) > 0) { // This is a click on the element (or its child element)
console.log('This is a click on an element (or its child element) with id: ' + id);
if (typeof element.onPress == 'function') element.onPress(event, id);
} else { //This is a click outside the element
console.log('This is a click outside the element with id: ' + id);
if (typeof element.onOutsidePress == 'function') element.onOutsidePress(event, id); //call the outside callback
delete autoCloseQueue[id]; //remove the element from the queue
}
}
});
然后,当创建id为“ menuscontainer ”的DOM元素时,只需将此对象添加到队列中:
window.autoCloseQueue['menuscontainer'] = {onOutsidePress: clickOutsideThisElement}
答案 72 :(得分:0)
当您单击元素的开/关时,这将切换导航菜单。
$(document).on('click', function(e) {
var elem = $(e.target).closest('#menu'),
box = $(e.target).closest('#nav');
if (elem.length) {
e.preventDefault();
$('#nav').toggle();
} else if (!box.length) {
$('#nav').hide();
}
});
<li id="menu"><a></a></li>
<ul id="nav" > //Nav will toggle when you Click on Menu(it can be an icon in this example)
<li class="page"><a>Page1</a></li>
<li class="page"><a>Pag2</a></li>
<li class="page"><a>Page3</a></li>
<li class="page"><a>Page4</a></li>
</ul>
答案 73 :(得分:0)
$('#menucontainer').click(function(e){
e.stopPropagation();
});
$(document).on('click', function(e){
// code
});
答案 74 :(得分:0)
$('html').click(function() {
//Hide the menus if visible
});
$('#menucontainer').click(function(event){
event.stopPropagation();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<button id='#menucontainer'>Ok</button>
</html>
答案 75 :(得分:0)
试试这个:
$('html').click(function(e) {
if($(e.target).parents('#menuscontainer').length == 0) {
$('#menuscontainer').hide();
}
});
https://jsfiddle.net/4cj4jxy0/
但请注意,如果点击事件无法到达html
标记,则无法使用此功能。 (也许其他元素有stopPropagation()
)。
答案 76 :(得分:0)
如果您只是想在单击按钮时显示一个窗口,并在外部单击时取消此窗口(或再次按下该按钮),这个下方工作正常
document.body.onclick = function() { undisp_menu(); };
var menu_on = 0;
function menu_trigger(event){
if (menu_on == 0)
{
// otherwise u will call the undisp on body when
// click on the button
event.stopPropagation();
disp_menu();
}
else{
undisp_menu();
}
}
function disp_menu(){
menu_on = 1;
var e = document.getElementsByClassName("menu")[0];
e.className = "menu on";
}
function undisp_menu(){
menu_on = 0;
var e = document.getElementsByClassName("menu")[0];
e.className = "menu";
}
请勿忘记按钮
<div class="button" onclick="menu_trigger(event)">
<div class="menu">
和css:
.menu{
display: none;
}
.on {
display: inline-block;
}
答案 77 :(得分:-1)
Outside click plugin!
Usage:
$('.target-element').outsideClick(function(event){
//code that fires when user clicks outside the element
//event = the click event
//$(this) = the '.target-element' that is firing this function
}, '.excluded-element')
The code for it:
(function($) {
//when the user hits the escape key, it will trigger all outsideClick functions
$(document).on("keyup", function (e) {
if (e.which == 27) $('body').click(); //escape key
});
//The actual plugin
$.fn.outsideClick = function(callback, exclusions) {
var subject = this;
//test if exclusions have been set
var hasExclusions = typeof exclusions !== 'undefined';
//switches click event with touch event if on a touch device
var ClickOrTouchEvent = "ontouchend" in document ? "touchend" : "click";
$('body').on(ClickOrTouchEvent, function(event) {
//click target does not contain subject as a parent
var clickedOutside = !$(event.target).closest(subject).length;
//click target was on one of the excluded elements
var clickedExclusion = $(event.target).closest(exclusions).length;
var testSuccessful;
if (hasExclusions) {
testSuccessful = clickedOutside && !clickedExclusion;
} else {
testSuccessful = clickedOutside;
}
if(testSuccessful) {
callback.call(subject, event);
}
});
return this;
};
}(jQuery));
Adapted from this answer https://stackoverflow.com/a/3028037/1611058
答案 78 :(得分:-1)
使用not():
$("#id").not().click(function() {
alert('Clicked other that #id');
});
答案 79 :(得分:-2)
这是一个经典案例,对HTML的调整将是一个更好的解决方案。为什么不设置不包含菜单项的元素?然后您不需要添加传播。
gotoAndPlay(5);
答案 80 :(得分:-2)
作为wrapper to this great answer from Art,并使用OP最初请求的语法,这里是一个jQuery扩展,可以记录在set元素之外发生的点击。
$.fn.clickOutsideThisElement = function (callback) {
return this.each(function () {
var self = this;
$(document).click(function (e) {
if (!$(e.target).closest(self).length) {
callback.call(self, e)
}
})
});
};
然后你可以这样打电话:
$("#menuscontainer").clickOutsideThisElement(function() {
// handle menu toggle
});
答案 81 :(得分:-2)
您可以将tabindex设置为DOM元素。当用户在DOM元素外部单击时,这将触发模糊事件。
<div tabindex="1">
Focus me
</div>
document.querySelector("div").onblur = function(){
console.log('clicked outside')
}
document.querySelector("div").onfocus = function(){
console.log('clicked inside')
}
答案 82 :(得分:-3)
$("html").click(function(){
if($('#info').css("opacity")>0.9) {
$('#info').fadeOut('fast');
}
});
答案 83 :(得分:-3)
$("body > div:not(#dvid)").click(function (e) {
//your code
});
答案 84 :(得分:-3)
答案 85 :(得分:-3)
试试这段代码:
if ($(event.target).parents().index($('#searchFormEdit')) == -1 &&
$(event.target).parents().index($('.DynarchCalendar-topCont')) == -1 &&
(_x < os.left || _x > (os.left + 570) || _y < os.top || _y > (os.top + 155)) &&
isShowEditForm) {
setVisibleEditForm(false);
}
答案 86 :(得分:-3)
<div class="feedbackCont" onblur="hidefeedback();">
<div class="feedbackb" onclick="showfeedback();" ></div>
<div class="feedbackhide" tabindex="1"> </div>
</div>
function hidefeedback(){
$j(".feedbackhide").hide();
}
function showfeedback(){
$j(".feedbackhide").show();
$j(".feedbackCont").attr("tabindex",1).focus();
}
这是我提出的最简单的解决方案。