我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
当前回答
这应该是有效的:
$('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
}
});
其他回答
使用可访问性焦点
这里有一个答案说(非常正确),关注点击事件是一个可访问性问题,因为我们想迎合键盘用户。在这里使用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,以便对话框可聚焦。
当只有一个元素需要管理时,这里的解决方案工作得很好。然而,如果有多个元素,问题就复杂得多。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();
});
我在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();
}
});
我正在检查祖先是否不是小部件元素容器,如果目标不是打开控件/元素的对象,如果我想关闭的小部件/元素已经打开(不那么重要)。
解决方案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
}
});
经过研究,我找到了三种可行的解决方案
第一种解决方案
<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>