我有一些HTML菜单,当用户单击这些菜单的标题时,它们会完整显示。 当用户在菜单区域之外单击时,我想隐藏这些元素。

jQuery可能会发生这种情况吗?

$("#menuscontainer").clickOutsideThisElement(function() {// Hide the menus
});

#1楼

将单击事件侦听器挂在文档上。 在事件侦听器内部,您可以查看事件对象 ,特别是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 #menuscontainerconsole.log("hide");}
});

#2楼

这完全适合我!

$('html').click(function (e) {if (e.target.id == 'YOUR-DIV-ID') {//do something} else {//do something}
});

#3楼

这里的其他解决方案对我不起作用,因此我不得不使用:

if(!$(event.target).is('#foo'))
{// hide menu
}

#4楼

如果您正在为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;
elsereturn true;}

#5楼

检查窗口单击事件目标(只要没有在其他任何地方捕获,它应该传播到窗口),并确保它不是任何菜单元素。 如果不是,那么您就在菜单之外。

或检查单击的位置,然后查看它是否包含在菜单区域中。


#6楼

注意:应该避免使用stopEventPropagation() ,因为它会破坏DOM中的正常事件流。 有关更多信息,请参见本文 。 考虑改用此方法

将单击事件附加到关闭窗口的文档主体。 将单独的click事件附加到容器,以停止传播到文档主体。

$(window).click(function() {
//Hide the menus if visible
});$('#menucontainer').click(function(event){event.stopPropagation();
});

#7楼

我有一个类似于Eran的示例的应用程序,除了在打开菜单时将click事件附加到主体上。

$('#menucontainer').click(function(event) {$('html').one('click',function() {// Hide the menus});event.stopPropagation();
});

有关jQuery的one()函数的更多信息


#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 treeif(!$(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");

#9楼

$("#menuscontainer").click(function() {$(this).focus();
});
$("#menuscontainer").blur(function(){$(this).hide();
});

对我有用。


#10楼

作为变体:

var $menu = $('#menucontainer');
$(document).on('click', function (e) {// If element is opened and click target is outside it, hide itif ($menu.is(':visible') && !$menu.is(e.target) && !$menu.has(e.target).length) {$menu.hide();}
});

停止事件传播没有问题,并且更好地支持同一页面上的多个菜单,在第一个菜单处于打开状态时单击第二个菜单将使stopPropagation解决方案中的第一个菜单保持打开状态。


#11楼

现在有一个用于此的插件: 外部事件 ( 博客文章 )

clickoutside处理程序(WLOG)绑定到元素时,将发生以下情况:

  • 将该元素添加到一个数组,该数组包含带有clickoutside处理程序的所有元素
  • ( 命名空间的 ) 单击处理程序已绑定到文档(如果尚未存在)
  • 在文档中的任何单击上, 都会为该数组中与click -events目标不相等或为父的那些元素触发clickoutside事件
  • 此外, clickoutside事件的event.target设置为用户单击的元素(因此,您甚至知道用户单击了什么,而不仅仅是他在外部单击了)

因此,不会停止任何事件的传播,并且可以使用外部处理程序在元素“上方”使用其他单击处理程序。


#12楼

解决方案1

与其使用event.stopPropagation()可能会有一些副作用,不如定义一个简单的标志变量并添加一个if条件。 我对此进行了测试,并且正常工作,没有stopPropagation的任何副作用:

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";}
});

解决方案2

只要一个简单的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楼

您可以侦听document上的click事件,然后使用.closest()来确保#menucontainer不是其祖先,也不是clicked元素的目标。

如果不是,则单击的元素在#menucontainer外部,您可以安全地隐藏它。

$(document).click(function(event) { $target = $(event.target);if(!$target.closest('#menucontainer').length && $('#menucontainer').is(":visible")) {$('#menucontainer').hide();}
});

编辑– 2017-06-23

如果您打算关闭菜单并想停止监听事件,则还可以在事件监听器之后进行清理。 此功能将仅清除新创建的侦听器,并保留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)
}

编辑– 2018-03-11

对于那些不想使用jQuery的人。 这是上面的纯香草代码(ECMAScript6)中的代码。

function hideOnClickOutside(element) {const outsideClickListener = event => {if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === nullelement.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: Element.closest()


#14楼

这是面向未来观众的原始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> 

如果您将在同一页面上进行多个切换,则可以使用以下方法:

  1. hidden的类名添加到可折叠项中。
  2. 单击文档后,关闭所有不包含被单击元素并且未被隐藏的隐藏元素
  3. 如果单击的元素是切换按钮,则切换指定的元素。
 (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> 

#15楼

支持最受欢迎的答案,但请添加

&& (e.target != $('html').get(0)) // ignore the scrollbar

因此,单击滚动条不会[隐藏或隐藏]您的目标元素。


#16楼

经过研究,我找到了三种可行的解决方案(我忘记了页面链接以供参考)

第一个解决方案

<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>

#17楼

一个简单的解决方案是:

$(document).mouseup(function (e)
{var container = $("YOUR SELECTOR"); // Give you class or IDif (!container.is(e.target) &&            // If the target of the click is not the desired div or sectioncontainer.has(e.target).length === 0) // ... nor a descendant-child of the container{container.hide();}
});

如果触发了div click事件之外,则上述脚本将隐藏div

您可以查看以下博客以获取更多信息: http : //www.codecanal.com/detect-click-outside-div-using-javascript/


#18楼

为了更易于使用和更具表现力的代码,我为此创建了一个jQuery插件:

$('div.my-element').clickOut(function(target) { //do something here...
});

注意: target是用户实际单击的元素。 但是回调仍然在原始元素的上下文中执行,因此您可以按照预期在jQuery回调中利用

插入:

$.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;
};

默认情况下,单击事件侦听器放置在文档上。 但是,如果您想限制事件侦听器的范围,则可以传入一个jQuery对象,该对象表示一个父级元素,该元素将是监听点击的顶级父级。 这样可以防止不必要的文档级事件侦听器。 显然,除非提供的父元素是初始元素的父元素,否则它将无法工作。

像这样使用:

$('div.my-element').clickOut($('div.my-parent'), function(target) { //do something here...
});

#19楼

如何检测元素外部的点击?

这个问题之所以如此流行并且答案如此之多,是因为它看似复杂。 经过将近八年的时间和数十个答案,我真的很惊讶地看到对可访问性的关注很少。

当用户在菜单区域之外单击时,我想隐藏这些元素。

这是一个崇高的原因,是实际的问题。 问题的标题(即大多数答案似乎试图解决的问题)包含不幸的鲱鱼。

提示:这是“点击”一词!

您实际上并不想绑定点击处理程序。

如果要绑定单击处理程序以关闭对话框,则您已经失败了。 您失败的原因是,并非所有人都触发click事件。 不使用鼠标的用户将可以通过按Tab来退出对话框(并且弹出菜单可以说是对话框的一种),然后他们将无法在不随后触发click情况下读取对话框后面的内容。事件。

因此,让我们改一下这个问题。

用户完成操作后如何关闭对话框?

这是目标。 不幸的是,现在我们需要用userisfinishedwiththedialog事件绑定userisfinishedwiththedialog ,而这种绑定并不是那么简单。

那么我们如何才能检测到用户已完成使用对话框?

focusout事件

一个很好的开始是确定焦点是否已离开对话框。

提示:请注意blur事件,如果事件绑定到冒泡阶段, blur不会传播!

jQuery的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> 

如果您在演示中玩了超过一分钟,则应该很快开始发现问题。

首先是对话框中的链接不可单击。 尝试单击它或它的选项卡将导致对话框在发生交互之前关闭。 这是因为聚焦内部元素会在再次触发focusout事件之前触发focusin事件。

解决方法是在状态循环上排队状态更改。 对于不支持setImmediate浏览器,可以使用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')); } }); 
 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> 

第二个问题是当再次按下链接时,对话框不会关闭。 这是因为对话框失去焦点,触发关闭行为,此后单击链接便触发对话框重新打开。

与上一期类似,需要管理焦点状态。 鉴于状态更改已经排队,只需在对话框触发器上处理焦点事件即可:

这看起来应该很熟悉

 $('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')); } }); 
 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> 

Esc键

如果您认为已经通过处理焦点状态完成了操作,则可以做更多的事情来简化用户体验。

这通常是“很不错的”功能,但是通常当您使用任何形式的模式或弹出窗口时, 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')); } }); 
 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> 

如果知道对话框中有可聚焦的元素,则无需直接聚焦对话框。 如果要构建菜单,则可以将焦点放在第一个菜单项上。

 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(); } } }); 
 .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; } 
 <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. 

WAI-ARIA角色和其他辅助功能支持

该答案有望涵盖此功能可访问的键盘和鼠标支持的基础知识,但是由于它已经相当大了,我将避免讨论WAI-ARIA角色和属性 ,但是我强烈建议实现者参考规范以了解详细信息。他们应该使用什么角色以及任何其他适当的属性。


#20楼

我在以下方面取得了成功:

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仅当(的点击)目标不是它的一个子。


#21楼

事件具有元素的名为event.path的属性,该属性是“所有祖先的静态有序列表(按树顺序)” 。 要检查事件是否起源于特定的DOM元素或其子元素之一,只需检查该特定DOM元素的路径即可。 通过在some函数中对元素进行逻辑OR它也可以用于检查多个元素。

 $("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}
});

#22楼

如果有人好奇这里是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';
}

});


#23楼

采用:

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楼

这是纯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;
})

#25楼

我已经使用下面的脚本并完成了jQuery。

jQuery(document).click(function(e) {var target = e.target; //target div recordedif (!jQuery(target).is('#tobehide') ) {jQuery(this).fadeOut(); //if the click element is not the above id will hide}
})

在下面找到HTML代码

<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>

您可以在这里阅读教程


#26楼

令我惊讶的是,实际上没有人承认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 = ''; }); 
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <button id="button">Click</button> </body> </html> 

#27楼

我不认为您真正需要的是在用户单击外部时关闭菜单。 您需要的是,当用户单击页面上的任意位置时,菜单关闭。 如果单击菜单,或者关闭菜单,它应该关闭吗?

上面找不到满意的答案,促使我前几天写了这篇博客 。 对于更加学究的人来说,有许多陷阱需要注意:

  1. 如果在单击时将click事件处理程序附加到body元素,请确保在关闭菜单并取消绑定事件之前等待第二次单击。 否则,打开菜单的click事件将冒泡到必须关闭菜单的侦听器中。
  2. 如果在click事件上使用event.stopPropogation(),则页面中的其他任何元素都不能具有“单击任何位置关闭”功能。
  3. 将click事件处理程序无限期地附加到body元素上并不是一种有效的解决方案
  4. 比较事件的目标以及事件的父对象与处理程序的创建者的比较,您假设您想要的是在单击菜单时关闭菜单,而您真正想要的是在单击页面上的任意位置时关闭菜单。
  5. 在body元素上侦听事件将使您的代码更加脆弱。 像这样无辜的样式会破坏它: body { margin-left:auto; margin-right: auto; width:960px;} body { margin-left:auto; margin-right: auto; width:960px;}

#28楼

我在某些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);

#29楼

$(document).click(function() {$(".overlay-window").hide();
});
$(".overlay-window").click(function() {return false;
});

如果单击文档,则隐藏给定元素,除非您单击相同的元素。


#30楼

我在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();}
});

我正在检查祖先是否不是小部件元素容器,
如果目标不是打开小部件/元素的位置,
如果我要关闭的小部件/元素已经打开(不是那么重要)。


#31楼

正如另一位张贴者所说的那样,有很多陷阱,特别是如果要显示的元素(在本例中为菜单)具有交互式元素。 我发现以下方法相当可靠:

$('#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 menuif ($(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);}})
});

如何检测元素外部的点击?相关推荐

  1. 检测React组件外部的点击

    本文翻译自:Detect click outside React component I'm looking for a way to detect if a click event happened ...

  2. js 中如何检测元素是否存在 - setInterval 方式

    js 中使用 setInterval 方式暴力检测元素是否存在 <!DOCTYPE html> <html lang="en"> <head>& ...

  3. jquery父元素和子元素点击事件传递问题_不可把父元素的事件传递给子元素_事件无限循环传递...

    前述:jquery中: 当一个元素的点击事件被触发时,会自动将该事件向父级元素逐级专递. 但是实际场景当中,我们可能会遇到需要在父级元素中定义点击事件,来触发特定子元素的点击事件,我就遇到了这么一个问 ...

  4. [css] 如何使用伪元素实现增大点击热区来增加用户体验?

    [css] 如何使用伪元素实现增大点击热区来增加用户体验? .extend-via-pseudo-elem {position: relative; }.extend-via-pseudo-elem: ...

  5. 一个元素位于另一个元素之上,点击上面的元素引发下面元素事件操作

    一个元素位于另一个元素之上,点击上面的元素引发下面元素事件操作 <body><!-- 此布局为: 上面内容盒子覆盖在了上传文本区域之上--><!-- 想要点击'上面盒子内 ...

  6. python selenium 鼠标移动到指定元素,并点击对应的元素

    在使用selenium 爬去网页信息的时候,我们经常会遇到这样的一个问题.就是某一关键字或者元素,必须是鼠标悬浮上,才会出现,然后才能点击.那下面,我们就用python实现这一功能. 举例来说: 假设 ...

  7. html 点击子元素,html如何点击子元素事件而不触发父元素的点击事件——阻止冒泡...

    如果子元素和父元素都有点击事件,会出现点击事件冒泡的情况. 1.如何避免冒泡: html: 你好, 战无不胜 [注销] js: 方法1: UserLogout.οnclick=function (e) ...

  8. jq 检测元素内html变化,jq 监听 textarea 元素内容变化的方法

    在前台是可以限制 textarea 元素内输入内容的长度的,当然是用 jquery 代码实现起来是最简单,方便的,JQ脚本通过对 textarea 元素内容变化的检测来判断内容是否超出指定的长度. j ...

  9. Ubuntu 20.04/21.04 不能检测到外部HDMI显示器

    有段时间没进Ubuntu系统了,今天接上外部显示器的时候,显示没有检测到信号.以前是好的,很奇怪怎么突然就不行了,重新拔插,换显示器也没有用.而Windows系统下是好的.刚开始以为是内核版本的问题, ...

最新文章

  1. Bind和Eval的区别详解(ZT)
  2. 超强包管理器:Anaconda 安装
  3. (转)认识原型对象和原型链
  4. 安卓手机清楚内置X5浏览器缓存
  5. C++网络编程实例之多个客户端交互(多线程)
  6. Python 获取URL访问的HEAD头信息
  7. 小型bbs论坛系统开发1 需求分析
  8. 财务系统需求分析 用户分析 功能需求
  9. C#开根号函数:math.pow()函数
  10. PCI/PCIe接口卡Windows驱动程序(4)- 驱动程序代码(源文件)
  11. 万年历(hao123)代码
  12. 中国移动的垃圾短信屏蔽算法?
  13. Virtual Box报错VT-x is not available (VERR_VMX_NO_VMX)--大踩坑(二)
  14. 联想M490 开机U盘启动 快捷键
  15. 禁用win10自带的微软输入法!
  16. S7-1200变量地址
  17. 微信小程序组件化实现歌单效果
  18. u盘格式化后如何恢复数据,三步轻松恢复!
  19. 人工神经网络是符号主义,神经网络的符号表达式
  20. SaaS安全性(摘自百科)

热门文章

  1. UEditor DIY笔记
  2. ORA-04043: 对象 dba_data_files 不存在 BUG
  3. 简化版XP按装IIS5.1实录
  4. python学习day05
  5. 什么是.NET Framework
  6. input type=file图片上传时,先预览
  7. Java 连接 SQL Server 数据库
  8. MySQL 报错记录
  9. 20145326蔡馨熤《计算机病毒》——静态分析(2)
  10. LeetCode -- Perfect Squares