How to Detect a Click Outside an Element

One of the most common patterns used in JavaScript is detecting a click outside an element. You can apply it for closing a non-modal user interface component like a menu or a dropdown when the user clicks outside that element.

There is a variety of solutions to this issue.

Solution 1

One of them is implementing a vanilla JavaScript solution.

The flyout in HTML will look like this:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <div class="flyout" id="flyout-example">
      <h5 class="flyout-title">This could be a flyout;</h5>
      <div class="flyout-debug" id="flyout-debug"></div>
      <div class="flyout-buttons">
        <button class="button button-outline" type="button">Cancel</button>
        <button class="button" type="button">Ok</button>
      </div>
    </div>
  </body>
</html>

So, for detecting a click outside an element, it would be best if you add a listener to the whole document element. Consequently, the main loop will go up the DOM from the clicked target element to search if the ancestor of that element belongs to the flyout container.

The fancy ES6 features offer the following JavaScript code to use:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <div class="flyout" id="flyout-example">
      <h5 class="flyout-title">This could be a flyout;</h5>
      <div class="flyout-debug" id="flyout-debug"></div>
      <div class="flyout-buttons">
        <button class="button button-outline" type="button">Cancel</button>
        <button class="button" type="button">Ok</button>
      </div>
    </div>
    <script>
      document.addEventListener("click", (evt) => {
        const flyoutEl = document.getElementById("flyout-example");
        let targetEl = evt.target; // clicked element      
        do {
          if(targetEl == flyoutEl) {
            // This is a click inside, does nothing, just return.
            document.getElementById("flyout-debug").textContent = "Clicked inside!";
            return;
          }
          // Go up the DOM
          targetEl = targetEl.parentNode;
        } while (targetEl);
        // This is a click outside.      
        document.getElementById("flyout-debug").textContent = "Clicked outside!";
      });
    </script>
  </body>
</html>

Notice that this code can run on modern browsers. For the older browsers, you need to adapt the code, which will look as follows:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the Document</title>
  </head>
  <body>
    <div class="flyout" id="flyout-example">
      <h5 class="flyout-title">This could be a flyout;</h5>
      <div class="flyout-debug" id="flyout-debug"></div>
      <div class="flyout-buttons">
        <button class="button button-outline" type="button">Cancel</button>
        <button class="button" type="button">Ok</button>
      </div>
    </div>
    <script>
      document.addEventListener("click", function(evt) {
        let flyoutEl = document.getElementById('flyout-example'),
          targetEl = evt.target; // clicked element      
        do {
          if(targetEl == flyoutEl) {
            // This is a click inside, does nothing, just return.
            document.getElementById("flyout-debug").textContent = "Clicked inside!";
            return;
          }
          // Go up the DOM
          targetEl = targetEl.parentNode;
        } while (targetEl);
        // This is a click outside.
        document.getElementById("flyout-debug").textContent = "Clicked outside!";
      });
    </script>
  </body>
</html>

Solution 2

There is another solution, as well. For that, you need to attach a click event to the document body that closes the window. Attach an independent click event to the container that stops propagation to the body of the document.

Here is an example:

$(window).click(function () { //Hide the menus if visible }); 
$('#menucontainer').click(function (event) {event.stopPropagation();});

Description of JavaScript DOM and its Elements

The Document Object Model (DOM) represents a way of describing a programming interface for the documents of HTML and XML. DOM helps to manipulate tags, classes using Document object commands. With it, you can connect programming languages to the page.

The DOM document has the essential part of your webpage, being the owner of all other objects. So, for accessing any object on your webpage, you need to start with the document.

In JavaScript DOM, you can find and/or change elements. There exist many ways of getting elements: by ID, by classname, by tag name, and more. Almost everything in DOM data structure is changeable.

The structure of DOM looks like a tree:elements are organized hierarchically in accordance with the document structure. The objects representing elements have the following properties: parentNode and childNodes that might be used for coursing through the tree.