문제

Im trying to create an overlay on click of a button and then removing it when the user clicks outside the overlay. In my example the target returns a length of "0" when the overlay is clicked and I can't figure out why when this method works with other examples I've used it with. Any idea?

Here's the js

$(document).ready(function() {
    $(document).on("click",".pop", function() {
       if ($('#search-overlay').length === 0) {
           $('body').append('<div id="search-overlay"></div>');
        }
    });
    $(document).on("mouseup", function(e) {
      var container = $("#search-overlay");
      if (container.has(e.target).length === 0) {
        alert(container.has(e.target).length);
        container.remove();
      }
    });
});

And the link where you see it in action http://jsfiddle.net/CwrAh/

도움이 되었습니까?

해결책

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)) {

Fiddle

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) {

Fiddle #1.1


You can further simplify it with .closest() as well:

if (!$(e.target).closest(container).length) {

Fiddle #2

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();
   }
}));

Fiddle #3

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top