I have a container (in a form) that has a Table layout with a set of Edit fields (texts, Checkboxes, etc).
I need to capture when the user clicks outside the container (on a menu item for example). There are no event handlers on the container currently.
I have a container (in a form) that has a Table layout with a set of Edit fields (texts, Checkboxes, etc).
I need to capture when the user clicks outside the container (on a menu item for example). There are no event handlers on the container currently.
Share asked Mar 14, 2013 at 19:22 srini.venigallasrini.venigalla 5,1451 gold badge20 silver badges29 bronze badges 2-
$(document).not("#container").click(function() {
.... – Rodrigo Siqueira Commented Mar 14, 2013 at 19:23 - @RodrigoAssis That doesn't work if it needs to be triggered when tabbed out too. – James Coyle Commented Mar 14, 2013 at 19:24
3 Answers
Reset to default 5I know this is an old question, but I recently ran into the same problem so I thought I would try to help any fellow sufferers.
I got stuck for hours creating various incarnations of blur and click event listeners which all seemed to almost work. Blur would fail because it fires even if the focus is on a child element. Click worked but didn't handle keyboard navigation.
My final solution was to capture the focus event at the window level and pare the focus target with my container and it's children. This will only work for browsers that support addEventListener. In my app, I had a captive audience and didn't need to worry about IE < 9.
First create a function to check if the focus target is your container or any of it's child elements.
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;
};
Note that this will pare all nodes in the container through recursion.
Next, create a listener function.
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 );
}
};
Note that the LocalTarget and Listener functions as well as [YOUR CONTAINER] are closures.
Finally, add the event listener.
window.addEventListener( 'focus', Listener, window, true );
While it seems like a lot of work to go through and the overhead is insane, this is the only concoction I could make work. Hope it helps someone.
Here is a solution using the focusout event, Node.contains method, and the relatedTarget property. This listens for the focusout event on a containing element. When the related target is no longer a descendent of that containing element you know that the focus has gone outside of that element.
let element = document.querySelector('.some-selector');
element.addEventListener('focusout', e => {
if (! element.contains(e.relatedTarget)) {
// Focus has left the element
}
});
This might not work in IE11 since IE11 has only partial support for the Node.contains method.
In jquery you can use $('#container').blur(function() { //some code here });