我有一个容器(在表单中),其表格布局包含一组编辑字段(文本,复选框等)。
我需要在用户点击容器外部时捕获(例如,在菜单项上)。目前容器上没有事件处理程序。
答案 0 :(得分:4)
我知道这是一个老问题,但我最近遇到了同样的问题,所以我想我会尽力帮助任何一个患者。
我被困了好几个小时,创造了各种模糊和点击事件监听器,这些看起来几乎都有效。模糊会失败,因为即使焦点在子元素上也会触发。点击工作但没有处理键盘导航。
我的最终解决方案是在窗口级别捕获焦点事件,并将焦点目标与我的容器及其子项进行比较。这仅适用于支持 addEventListener 的浏览器。在我的应用程序中,我有一个被俘的观众,不需要担心IE< 9。
首先创建一个函数来检查焦点目标是否是您的容器或其任何子元素。
var LocalTarget = function( el, target )
{
if ( el === target )
{
return true;
}
else if ( el.childNodes )
{
var els = el.childNodes;
for ( var i = 0, n = els.length; i < n; i++ )
{
if ( els[i] === target )
{
return true;
}
else if ( els[i].childNodes )
{
if ( LocalTarget(els[i], target) ) return true;
}
}
}
return false;
};
请注意,这将通过递归来比较容器中的所有节点。
接下来,创建一个侦听器函数。
var Listener = function( e )
{
// Check if receiving element is part of the container.
if ( !LocalTarget([YOUR CONTAINER], e.target) )
{
// Do focus lost stuff here...
// Remove the event listener. [OPTIONAL]
window.removeEventListener( 'focus', Listener, window, true );
}
};
请注意,LocalTarget和Listener函数以及[YOUR CONTAINER]都是闭包。
最后,添加事件监听器。
window.addEventListener( 'focus', Listener, window, true );
虽然看起来需要做很多工作而且开销是疯狂的,但这是我能做的唯一的混合物。希望它可以帮到某人。
答案 1 :(得分:0)
这是使用focusout事件,Node.contains方法和relatedTarget属性的解决方案。这侦听包含元素上的焦点事件。当相关目标不再是该包含元素的后代时,您就会知道焦点已超出该元素。
let element = document.querySelector('.some-selector');
element.addEventListener('focusout', e => {
if (! element.contains(e.relatedTarget)) {
// Focus has left the element
}
});
自IE11 has only partial support for the Node.contains method起,这可能无法在IE11中使用。
答案 2 :(得分:-1)
在jquery中,您可以使用$('#container').blur(function() { //some code here });