0

I have a dropdown menu within a div element. Calling the javascript function HideDropdown() hides the menu when any other main link on the page is clicked (not including links in the dropdown menu itself):

<script>
function HideDropdown() {
    $("#dropdown-content-id2").hide();
    $("#dropdown-content-id").hide();}
</script>

I also want to call HideDropdown() to hide the menu (if it's open) when I click anywhere on the body except the dropdown menu itself.

In the body tag I inserted this:

<body onload="ShowPage(1)" onclick="HideDropdown()">

That successfully hides the dropdown when I click anywhere on the screen. I want to exclude clicks on the link that shows the dropdown menu and anywhere on the dropdown menu itself, so I revised the body tag:

<body onload="ShowPage(1)" onclick="HideDropdownCall(e)">

and created a new javascript function to call from the body onclick:

<script>
 function HideDropdownCall(e) {
     if(e.target.id != "dropdown-content-id" ){
         HideDropdown();
 }
 </script>

but that didn't work, so I revised it:

<script>
 function HideDropdownCall(e) {
     if(e.target.id != "dropdown-content-id" ){
         $("#dropdown-content-id2").hide();
         $("#dropdown-content-id").hide();}
 }
 </script>

but that still doesn't work.

So my question is, how can I call the HideDropdown() function from a body click, filtered so that clicks on the dropdown menu itself don't count?

Thanks very much for any help.

EDIT:

After some work, I whittled down my problem to this: I can call the HideDropdown() function from the body tag like this:

<body onload="ShowAjax(1)" onclick="HideDropdown()">

That works. But when I change it to the same function with qualifications and (not if the click event is fired by the dropdown menu), the dev console says "TypeError: e is undefined" so it has something to do with the conditional statement:

<body onload="ShowAjax(1)" onclick="HideDropdown_B()">

<script>
function HideDropdown_B(e) {
    if(e.target.id != "dropdown-content-id" ){
        $("#dropdown-content-id2").hide();
        $("#dropdown-content-id").hide();}
}
</script>

So my problem now boils down to finding out why the new function above returns a type error when the same program without the if statement works.

RTC222
  • 2,025
  • 1
  • 20
  • 53
  • 1
    Would be helpful if you provided a minimal example with html and JS code so that we could play around with it and see what behavior you're talking about – chevybow Oct 08 '18 at 14:32
  • 2
    On click of body close the dropdown, on click on dropdown call e.stopPropagation() to block the click event from propagating up to the body - I wrote a better answer here https://stackoverflow.com/questions/17965839/close-a-div-by-clicking-outside/17965941#17965941 – Jonas Grumann Oct 08 '18 at 14:32
  • Possible duplicate of [How do I prevent a parent's onclick event from firing when a child anchor is clicked?](https://stackoverflow.com/questions/1369035/how-do-i-prevent-a-parents-onclick-event-from-firing-when-a-child-anchor-is-cli) – Liam Oct 08 '18 at 14:40
  • We would have to see your markup. Your event delegation architecture should work. – zfrisch Oct 08 '18 at 14:43

3 Answers3

0

Here is an example of how it could be done:

let menu = document.getElementById('menu');
document.body.addEventListener('click', e => {
    if (!menu.contains(e.target))
      console.log('close menu');
});
<div id='menu'><a id='link'>link</a> and menu</div>
document body here

However, you may actually want to close menu depending on which link were clicked.

Another way to do so:

let menu = document.getElementById('menu');
menu.addEventListener('click', e => e.stopPropagation());
document.body.addEventListener('click', e => console.log('close menu'));
<div id='menu'><a id='link'>link</a> and menu</div>
document body here
Lain inVerse
  • 81
  • 1
  • 4
0

What you could do is add the property data-prevent='true' on the elements that you want to prevent hiding the dropdown.For example:

<a href="/some-path/to-someplace" data-prevent="true">Link</a>

and modify your function to filter out those elements like so:

function hideDropdown(evt) {

    evt.preventDefault();  // you might not need this (usefull in case of a tags & preventing redirects)

    if (!evt.target.getAttribute('data-prevent') || evt.target.getAttribute('data-prevent') === 'false') {

        $("#dropdown-content-id2").hide();
        $("#dropdown-content-id").hide();

    }

}
0x_Anakin
  • 3,229
  • 5
  • 47
  • 86
  • Thanks for the answers. I am working on this now and I will post back later with the results. Thanks again. – RTC222 Oct 08 '18 at 15:20
  • Syd, I incorporated your code and called it from the body tag like this: , then I inserted your code below the close of the body tag. But the Firefox dev console says "ReferenceError: hideDropdown is not defined." Can you show how this function should be called? Thanks very much. – RTC222 Oct 08 '18 at 15:29
  • I edited my question above with an update and clarification. – RTC222 Oct 08 '18 at 17:07
  • Well you have to declare the function in a script inside the head tag and make sure the function name is the same – 0x_Anakin Oct 09 '18 at 16:32
0

Thanks to everyone who answered. I solved this problem. Here is the solution:

In the body tag:

<body onload="ShowPage(1)" onclick="HideDropdown_B(event)">

The HideDropdown_B function:

<script>
function HideDropdown_B(event) {
    TargetID = event.target.getAttribute('id');
    TargetClass = event.target.getAttribute('class');
    if((TargetID != "dropdown-content-id") && (TargetClass != "button_01") &&   (TargetClass != "dropdown") && (TargetClass != "button_dropdown") ) {
   $("#dropdown-content-id2").hide();
       $("#dropdown-content-id").hide();}
}
</script>

That works to close the menu when clicking anywhere except the excluded elements.

RTC222
  • 2,025
  • 1
  • 20
  • 53