我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
当前回答
这是我解决问题的方法。
$(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;
}
其他回答
首先,您必须使用mouseenter和mouseleave事件跟踪鼠标是在元素1内部还是外部。然后,您可以创建一个覆盖整个屏幕的element2来检测任何点击,并根据您是在element1内部还是外部做出相应的反应。
我强烈建议同时处理初始化和清理,出于明显的原因,element2应尽可能临时。
在下面的示例中,覆盖是位于某个位置的元素,可以通过单击内部来选择,也可以通过单击外部来取消选择。_init和_release方法是自动初始化/清理过程的一部分。该类继承自具有内部和外部元素的ClickOverlay,不用担心。我使用了outerElement.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')
}
}
解决方案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
}
});
对于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();
}
});
这对我来说非常及时:
$('body').click(function() {
// Hide the menus if visible.
});
检查窗口单击事件目标(它应该传播到窗口,只要它没有在其他地方被捕获),并确保它不是任何菜单元素。如果不是,那么你就在菜单之外。
或者检查单击的位置,看看它是否包含在菜单区域中。