25

Im using a very simple and clean code to render a modal in my page:

<div class="modal">I'm the Modal Window!</div>

.modal {
    /* some styles to position the modal at the center of the page */
    position: fixed;
    top: 50%;
    left: 50%;
    width: 300px;
    line-height: 200px;
    height: 200px;
    margin-left: -150px;
    margin-top: -100px;
    background-color: #f1c40f;
    text-align: center;

    /* needed styles for the overlay */
    z-index: 10; /* keep on top of other elements on the page */
    outline: 9999px solid rgba(0,0,0,0.5);
}

http://jsfiddle.net/c89Ls0av/

Is there a clean and reliable way to detect when somebody clicks outside of the modal?

DomingoSL
  • 14,920
  • 24
  • 99
  • 173

4 Answers4

12

Probably the simplest way is to bind click event to body and see if it comes from the element (e.target) which has parent (walk up the tree with closest method) .modal:

$(document).click(function(e) {
    if (!$(e.target).closest('.modal').length) {
        alert('click outside!');
    }
});

Demo: http://jsfiddle.net/c89Ls0av/4/

By the way, overlay made with outline is an interesting idea, but it's not real overlay, as it still allows to interact with underlying page elements. Here is an example of the overlay made with div container covering entire page: http://jsfiddle.net/c89Ls0av/5/. This one will prevent page interaction when modal is visible.

And here is an example of how open/close functionality can be use together: http://jsfiddle.net/c89Ls0av/7/.

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • That works if there's content behind the modal. Replace `'body'` with `document`, and it seems to work well regardless. – Rick Hitchcock Nov 15 '14 at 21:52
  • This answer has introduced a load of paragraphs which weren't in his fiddle. How would you address the problem as is in the OP's fiddle? – Ben Smith Nov 15 '14 at 21:53
  • 1
    @RickHitchcock Very true I forgot that body will only take as much height as need for content. Thank you! – dfsq Nov 15 '14 at 21:53
  • @BenSmith http://jsfiddle.net/c89Ls0av/2/ like this? I added some text to test how overlay works. But you are making good point either, since there will be a problem if binding event to `body`. I fixed to `document` now. – dfsq Nov 15 '14 at 21:54
  • @dfsq "overlay made with outline is an interesting idea, but it's not real overlay, as it still allows to interact with underlying page elements" Do you know a better solution? – DomingoSL Nov 15 '14 at 21:54
  • @dfsq Ah, it still works without the extra p elements. Nice :) – Ben Smith Nov 15 '14 at 21:55
  • 1
    @BenSmith It actually would not work with `body` click event. See comment above. Now I fixed it to `document`. Thank you for comment! – dfsq Nov 15 '14 at 21:57
  • @DomingoSL Usually along with actual modal container there is one more overlay container covering entire page. Then click event is bound to this overlay. When modal is closed overlay is removed or hidden. – dfsq Nov 15 '14 at 21:58
  • 1
    @DomingoSL By the way, here is an example of real overlay: http://jsfiddle.net/c89Ls0av/5/ – dfsq Nov 15 '14 at 22:14
1

WithOut jQuery

document.addEventListener('click', function (e) {
  if(e.target.className === 'modal'){
     alert('clicked in');
  }else {
    alert('clicked out');
  }
}, false);

check it out:
http://jsbin.com/totonopili/1/edit?html,css,js,output

ariel_556
  • 368
  • 1
  • 9
  • 2
    It's a little bit more complecated. If you have nested HTML elements in modal (`p`, links, buttons, etc.) `e.target` will no longer be `modal`. So you need to implement `closest` functionality. Usually `while` loop is used, walking up the tree and checking `parentNode`. – dfsq Nov 15 '14 at 22:00
0

With the help of a javascript framework this is quite easy.

Follow these steps:

  1. Attach a click event to the document which closes or hides the modal.
  2. Attach a separate click event to the window which stops click propagation.

Example:

$('html').click(function(){
    $('.modal').hide();
});
$('.modal').click(function(e){
    e.stopPropagation();
});

http://jsfiddle.net/c89Ls0av/3/

Warning! Stopping propagation can introduce strange behaviour

0

Dfsq answer will work fine.. but if you want something to do with dialog boxes you may have a look at jQuery ui dialog boxes. It gives you many options with dialog boxes which you can configure as per your needs.

http://jqueryui.com/dialog/

Vatsal
  • 2,068
  • 4
  • 21
  • 24