我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
我有一些HTML菜单,当用户单击这些菜单的头部时,我会完全显示这些菜单。当用户在菜单区域外单击时,我希望隐藏这些元素。
jQuery是否可以实现这样的功能?
$("#menuscontainer").clickOutsideThisElement(function() {
// Hide the menus
});
当前回答
用纯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);
其他回答
还在寻找检测外部点击的完美解决方案?别再看了!介绍Clickout Event,这是一个为Clickout和其他类似事件提供通用支持的包,它适用于所有场景:普通HTML onclickout属性、普通JavaScript的.addEventListener('clickkout')、jQuery的.on('click kout'”)、Vue.js的v-on:cclickout指令。只要前端框架内部使用addEventListener来处理事件,Clickout Event适用于它。只需在页面中的任何位置添加脚本标记,它就会像魔术一样发挥作用。
HTML属性
<div onclickout="console.log('clickout detected')">...</div>
香草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>
对于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();
}
});
我有一个应用程序,它的工作方式与Eran的示例类似,只是当我打开菜单时,我会将单击事件附加到主体。。。有点像这样:
$('#menucontainer').click(function(event) {
$('html').one('click',function() {
// Hide the menus
});
event.stopPropagation();
});
有关jQuery的one()函数的更多信息
$("html").click(function(){
if($('#info').css("opacity")>0.9) {
$('#info').fadeOut('fast');
}
});
您可以监听文档上的单击事件,然后使用.clost()确保#menucontainer不是被单击元素的祖先或目标。
如果不是,则单击的元素位于#menucontainer之外,您可以安全地隐藏它。
$(document).click(function(event) {
var $target = $(event.target);
if(!$target.closest('#menucontainer').length &&
$('#menucontainer').is(":visible")) {
$('#menucontainer').hide();
}
});
编辑–2017-06-23
如果您计划关闭菜单并希望停止侦听事件,也可以在事件侦听器之后进行清理。此函数将只清理新创建的侦听器,保留文档上的任何其他单击侦听器。使用ES2015语法:
export function hideOnClickOutside(selector) {
const outsideClickListener = (event) => {
const $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的人。这是上面的纯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的评论,仅供使用!元素。包含(event.target)而不是jQuery部分。
但是element.clost()现在也可以在所有主要浏览器中使用(W3C版本与jQuery版本稍有不同)。Polyfills可以在以下位置找到:Element.clost()
编辑–2020-05-21
如果您希望用户能够在元素内部单击并拖动,则在元素外部释放鼠标,而不关闭元素:
...
let lastMouseDownX = 0;
let lastMouseDownY = 0;
let lastMouseDownWasOutside = false;
const mouseDownListener = (event: MouseEvent) => {
lastMouseDownX = event.offsetX;
lastMouseDownY = event.offsetY;
lastMouseDownWasOutside = !$(event.target).closest(element).length;
}
document.addEventListener('mousedown', mouseDownListener);
在外部ClickListener中:
const outsideClickListener = event => {
const deltaX = event.offsetX - lastMouseDownX;
const deltaY = event.offsetY - lastMouseDownY;
const distSq = (deltaX * deltaX) + (deltaY * deltaY);
const isDrag = distSq > 3;
const isDragException = isDrag && !lastMouseDownWasOutside;
if (!element.contains(event.target) && isVisible(element) && !isDragException) { // or use: event.target.closest(selector) === null
element.style.display = 'none';
removeClickListener();
document.removeEventListener('mousedown', mouseDownListener); // Or add this line to removeClickListener()
}
}