Javascript

Handling Click Outside Techniques With Javascript

Handling Click Outside Techniques With Javascript

Manipulating click outside element is important in cases when you have some elements you need to toggle while clicking outside like navigation menus. In this post we will check some different methods to detect clicking outside element.

 

 

 

Imagine you have a multi-level navigation menu or a custom popup dialog, and you need to write logic that fires when you click outside these elements such as closing the popup or the menu. So let’s check some methods that you can use o deal with such situations.

 

  • Using contains() method:

The first common method using javascript contains() method of the Node interface. The contains() method return a boolean indicating if a node is descendant of a given node that is the node itself, one of its direct children.

To implement this typically we set up a click listener on the document using document.addEventListener():

document.addEventListener('click', function(event) {
            const targetElement = document.querySelector('nav');

            if (event.target !== targetElement && !targetElement.contains(event.target)) {

                targetElement.querySelectorAll("nav ul li[data-dropdown] ul").forEach(submenu => {
                    submenu.style.display = "none";
                });
            }
        });

In this example we assuming we have a navigation menu which have multi-level nodes. Our challenge is to close any nested menu when clicking outside nav. So the work is done inside of addEventListener() we obtained a reference to the target element using document.querySelector() passing in selector such as class of element id.

After that i check if event.target != tagetElement and not contains the clicked target using contains() function i.e targetElement.contains(event.target). Once this condition is met, then we query for all the submenu nodes with targetElement.querySelectorAll() and set the style back to none which hide the menu.

You can also achieve the same thing using jQuery syntax.

 

  • Using Event.composedPath() method:

Another method to detect if you click outside an element using the Event.composedPath() method. The composedPath() method return an array of objects on which listeners will be invoked (propagated). By using this method you can check if the target element is within the event path array, in that case you can toggle display of this element:

document.addEventListener('click', function(e) {
            const targetElement = document.querySelector('nav');

            const event_path = e.composedPath();        // return array of nodes such as [html, body, ul, ...]

            if(!event_path.includes(targetElement)) {
                 document.querySelector(`nav ul li[data-dropdown] ul`).style.display = "none";
            }
        });

Again we are using addEventListener() to register a click event on the document. in this example i retrieved the event path by calling e.composedPath(). The composedPath() is an array, so we can use the array includes() method to check if the target nav element is within the this path, and then we set the style display to be ‘none’.

Another example of using composedPath() is to obtain a list of classes of all the elements in the event path. Then check if the target element class is located inside those classes, and implement the convenient logic:

document.addEventListener('click', function(e) {
            const event_path = e.composedPath();

            let classList = [];

            const element_clases = event_path.forEach(path => {
                if(path.classList) {
                    classList = [...classList, ...Array.from(path.classList)];
                }
            });

            if(!classList.includes("child")) {               
                // Logic to hide the element
            }
        });

 

  • Using Overlay:

This method which is convenient when dealing with modals and popup’s. The idea to to add an overlay div which fills the whole screen and takes a fixed position. Once clicking on the overlay it will hide the popup.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Modal with Overlay</title>

    <style>
        .modal {
        	position:  fixed;
        	top: 20%;
        	left:  30%;
        	width: 500px;
        	height:  350px;
        	padding:  20px 40px;
        	border:  2px solid #000;
        	border-radius: 5px;
        	z-index: 100;
        	background: #fff;
        }

        .modal .close {
        	float: right;
        	font-size: 40px;
        	color:  red;
        	cursor: pointer;
        }

        .overlay {
        	position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: 50;
            background: #dadadab5;
            opacity: 0.8;
        }
    </style>
</head>
<body>

    <div class="modal">
        <div class="modal-dialog">
            <span class="close">&times;</span>

            <h2>This is popup</h2>
        </div>

    </div>
    <div class="overlay"></div>
        

    <script>
        document.querySelector(".overlay").addEventListener("click", function() {
            this.style.display = "none";
            document.querySelector(".modal").style.display = "none";
        });
        
    </script>
</body>
</html>

In this example i added a div that acts as a modal with class ‘modal‘, so i added some styling to it for demonstration purposes. Also i added an div with class ‘overlay’. Both div’s takes a fixed position. The overlay div has a 100% width and height so it spans all the document window.

Also both containers takes a z-index property, the z-index value for modal popup should be higher that the overlay div. This modal will be shown when you open the page. 

Now to close this modal when clicking outside, instead of detecting click events on the document, we simply register a click event on the overlay itself and then setting the css display to none. 

 

0 0 votes
Article Rating

What's your reaction?

Excited
0
Happy
0
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments