我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
当前回答
老实说,我不喜欢以前的任何解决方案。
要做到这一点,最好的方法是将“点击”事件绑定到文档,并比较该点击是否真的在元素之外(就像Art在建议中所说的那样)。
然而,您会遇到一些问题:您永远无法解除绑定,并且无法使用外部按钮打开/关闭该元素。
这就是为什么我编写了这个小插件(点击此处链接),以简化这些任务。能简单一点吗?
<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>
其他回答
我知道这个问题有一百万个答案,但我一直喜欢使用HTML和CSS来完成大部分工作。在这种情况下,z索引和定位。我找到的最简单的方法如下:
$(“#show trigger”).click(function(){$(“#element”).animate({width:'toggle'});$(“#外部元素”).show();});$(“#外部元素”).click(function(){$(“#element”).hide();$(“#外部元素”).hide();});#外部元件{位置:固定;宽度:100%;高度:100%;z指数:1;显示:无;}#元素{显示:无;填充:20px;背景色:#ccc;宽度:300px;z指数:2;位置:相对;}#显示触发器{填充:20px;背景色:#ccc;边距:20px自动;z指数:2;}<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”>菜单项1</a></div><div class=“menu item”><a href=“#2”>菜单项1</a></div><div class=“menu item”><a href=“#3”>菜单项1</a></div><div class=“menu item”><a href=“#4”>菜单项1</a></div></div><div id=“show trigger”>显示菜单</div>
这创建了一个安全的环境,因为除非菜单实际打开,否则不会触发任何内容,并且z索引保护元素中的任何内容在被单击时不会产生任何错误。
此外,您不需要jQuery用传播调用覆盖所有基础,也不需要清除所有内部元素中的错误。
该事件具有元素的名为event.path的属性,该属性是“以树顺序列出其所有祖先的静态有序列表”。要检查事件是否源自特定DOM元素或其子元素之一,只需检查该特定DOM元素的路径。它还可以用于通过在some函数中对元素检查进行逻辑“或”运算来检查多个元素。
$(“body”).click(函数){target=document.getElementById(“main”);flag=event.path.some(函数(el,i,arr){返回(el==目标)})if(标志){console.log(“内部”)}其他{console.log(“外部”)}});#主要的,主要的{显示:内联块;背景:黄色;}<script src=“https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js“></script><div id=“main”><ul><li>测试总管</li><li>测试总管</li><li>测试总管</li><li>测试总管</li><li>测试总管</li></ul></div><div id=“main2”>外部主管道</div>
所以你的情况应该是
$("body").click(function() {
target = $("#menuscontainer")[0];
flag = event.path.some(function(el, i, arr) {
return (el == target)
});
if (!flag) {
// Hide the menus
}
});
const button=document.querySelector('button')const box=document.querySelector('.box');常量切换=事件=>{event.stopPropagation();if(!event.target.closest('.box')){console.log('单击外部');box.classList.tggle(“活动”);box.classList.contains('active')? document.addEventListener('click',切换):document.removeEventListener(“单击”,切换);}其他{console.log('单击内部');}}button.addEventListener('单击',切换);.box格式{位置:绝对;显示:无;页边空白:8px;填充:20px;背景:浅灰色;}.box激活{显示:块;}<button>切换框</button><div class=“box”><form action=“”><input-type=“text”><button type=“button”>搜索</button></form></div>
使用可访问性焦点
这里有一个答案说(非常正确),关注点击事件是一个可访问性问题,因为我们想迎合键盘用户。在这里使用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可能为空。如果用户在对话框外单击,这很好,但如果用户在对话内单击,而对话框恰好不可聚焦,则会出现问题。要解决此问题,必须确保将tabIndex设置为0,以便对话框可聚焦。
$('#menucontainer').click(function(e){
e.stopPropagation();
});
$(document).on('click', function(e){
// code
});