0

I am trying to create a simple jQuery popup menu, but cant seem to figure out the script to check if an element is in a predefined element.

Clicking on the popup trigger launches the jQuery function. The function saves the following variables: The element that was clicked (js_popup-trigger), its main parent (js_popup-container), and the actual menu with the menu items (js_popup-menu).

Once the trigger is clicked, the menu fades in/out, and an event listener is added to the document to check if the user clicked outside of the menu, in which case it should close, nothing should happen to the menu if the user clicks inside of it.

This is the part i cant figure out - how do i detect if the user has clicked inside the popup element or outside of it?

I have tried this: if(!$(e.target).parent('.js_popup-container').length){

But this does not work well when you have multiple popups on the page, because if you click anywhere else, including another popup, the current one should close, but since if you click on another popup with the same class of js_popup-container, then it will remain open because it technically is inside of an element with that class.

/*  Popup menu toggle
===========================================*/
$(document).on("click",".js_popup-trigger", function(e){
    e.preventDefault();


    //Set variables
    var element     = $(e.currentTarget),
        container   = element.parent('.js_popup-container'),
        menu        = element.next('.js_popup-menu');


    //Toggle the menu
    menu.fadeToggle(200);


    /*  Create a click listener for the document
    *   This is to close the menu if clicked outside of it */
    $(document).click(function closePopup(e){


        //If the clicked item is not in the popup, close it
        if(!$(e.target).parent(container).length){
            menu.fadeToggle(200);
            $(document).unbind('click',closePopup);
        }
    });
});

In the end, what i want to achieve is a function that can be applied to any popup menu just by adding the 3 classes. There should be the option to have multiple popup menus on the same page, and when clicking anywhere outside of the menu, it should close.

Of course i am open to suggestions on improving the code, but i don't want to use a preexisting plugins at this point.

EDIT: I know that there are already other questions and solutions very similar to this one, but the difference is that the solutions given in other questions is to check if the target that was clicked is inside of another element with a specific class name/id/selector.

I need something a little bit different, i already have the parent element (the popup container) saved in a variable. I need to know if the clicked element is inside of that saved element.

Using the solutions already found, i run in to a problem because i will have multiple popups on the page, so if i have one popup open, and i click on another, the first popup will remain open instead of closing, that's because using the other solutions, i am checking for an element with the popups container class, which they both have, which means that the first popup wont close.

K.D
  • 147
  • 1
  • 12
  • Possible duplicate of [How do I detect a click outside an element?](https://stackoverflow.com/questions/152975/how-do-i-detect-a-click-outside-an-element) – Akrion May 24 '19 at 21:04
  • Please, create a Minimal, Complete, and Verifiable example – gaetanoM May 24 '19 at 21:04
  • I saw those questions and answers, the difference between what i need and their answers is that they are giving solutions to check an element with a certain selector, i need to check an actual element that is already saved to a variable, because i want to be able to close the popup if clicked anywhere outside of the actual popup, including if the user clicks on another popup with that same class. So basically, with those solutions, if i have two popups on the same page, clicking on the second popup while the first one is open will keep the first one open, my goal is to close the first one. – K.D May 24 '19 at 21:12

2 Answers2

0

It depends on how performant you want your method to be, but here's one concise option assuming element and container are both jQuery objects.

if(element.parents().find(container).length == 1){
   // do work
}
Dinerdo
  • 560
  • 7
  • 27
  • I tried `$(e.target).parents().find(container).length` but it always returns 1 – K.D May 24 '19 at 21:53
  • I ran a few tests with dummy containers and other elements, and it doesn't seem to always return 1. I would change your question to reflect that the element you're looking for must be visible as that seems to be the real difference. – Dinerdo May 24 '19 at 22:47
0

I came up with a solution that is working for my current app at the moment.

$(document).on("click",".js_popup-trigger", function(e){
    e.preventDefault();

    //Set variables
    var element     = $(e.currentTarget).closest('.js_popup-trigger'),
        container   = element.parent('.js_popup-container'),
        menu        = element.next('.js_popup-menu');

    //Toggle the menu
    menu.fadeToggle(200);

    //Add the open classes to the container and trigger
    container.toggleClass('js_popup-container--open');
    element.toggleClass('js_popup-trigger--open');

    /*  Create a click listener for the document
    *   This is to close the menu if clicked outside of it */
    $(document).click(function closePopup(e){

        //If the clicked item is not in the popup, close it
        if(!$(e.target).closest(container[0]).length && element.is(":visible")){

            //Close the popup
            menu.fadeOut(200);

            //Remove the added classes
            container.removeClass('js_popup-container--open');
            element.removeClass('js_popup-trigger--open');

            //Unbind the closePopup function from the document
            $(document).unbind('click',closePopup);
        }
    });
});

This makes it so that you can add as many popups as you want to the same page, and they will all work independently of others - all other solutions i found used a general class to check if the popup is open instead of an actual element/object, which meant that if you had another popup open with the same class, then clicking on a new popup would not close the first one. This approach fixes that problem.

Hope this is helpful to others, if anyone has better ideas then i would love to hear them!

K.D
  • 147
  • 1
  • 12