That's because .has()
looks for descendants, it doesn't match the element(s) inside of the jQuery object. One extra check to fix your logic:
if (!container.has(e.target).length && !container.is(e.target)) {
When performance is concerned, you can replace the is()
function with a simple comparison between the e.target
element and the first element contained inside the container
jQuery object:
if (!container.has(e.target).length && container[0] !== e.target) {
You can further simplify it with .closest()
as well:
if (!$(e.target).closest(container).length) {
Same logic, but reversed. closest
starts trying to match at the element contained inside the jQuery object and traverses up the DOM tree looking for an ancestor overlay that matches. Same result as the first version.
And a third variation, that discards the need of logical tests. Attach a mouseup handler that stops the event propagation to the overlay, so it doesn't reach the document
:
$('body').append($('<div>', {
id: 'search-overlay',
mouseup: function(e) {
e.stopPropagation();
}
}));