2

I have a transparent div that covers the entirety of my page that ISN'T my pop-up sidebar. I want a click anywhere on the page that's not the sidebar to close the sidebar but I also want it to do whatever it would have done if the sidebar isn't on (so, if I click on a button I want that to register).

I realize I can do this if the rest of the page are children of the transparent div, then clicking will trigger the listeners of both the parent and the children, but I can't use that layout because it causes issues with the positioning of my sticky nav bar. The transparent "cancel" div is a standalone div with no children, but I still want the click to propagate through it somehow.

Rough outline of my code element hierarchy:

<body>
   <sidebar/>
   <cancelDiv/>
   <otherContent/>
</body>

So, to reiterate, I want a click on cancelDiv to trigger the event listener that will close sidebar but also pass through to otherContent and do whatever the listeners there want to do.

Supperhero
  • 911
  • 1
  • 7
  • 24
  • why use that layer in first place? https://stackoverflow.com/questions/18893144/javascript-detect-click-event-outside-of-div – epascarello Jul 30 '19 at 16:02
  • Well, as something that can hold an on click event listener that will close the sidebar if the user clicks outside of it. Basically, when the sidebar is opened, the cancelDiv expands to cover everything that isn't the sidebar and catches the clicks that happen there. If there's a better solution for implementing that, feel free to share. – Supperhero Jul 30 '19 at 16:13
  • Like the code in the link? :) – epascarello Jul 30 '19 at 16:13
  • Hmm, that might work, I did try doing something with checking the event target but didn't get the results I expected, might be due to z-index. I'll have to check it out some more. – Supperhero Jul 30 '19 at 16:15
  • Yeah, this will work. Not directly because my sidebar has children of it's own so they will be the event target not the sidebar, but i can add a dummy class to everything inside the sidebar and check if my target has that class. Thanks. – Supperhero Jul 30 '19 at 16:24
  • `if(!event.target.closet(".YourWrapperClass")) hideYourElement()` – epascarello Jul 30 '19 at 16:25
  • That's useful, thanks. I'm still new to JS/coding, lots to learn. – Supperhero Jul 31 '19 at 06:25

1 Answers1

1

The easiest way to do this is to use the onblur event or add an event listener for blur on your sidebar container. Give your sidebar container a tabindex="-1" so that it can receive focus on click, but not when a user hits tab. As long as you click on anything inside the sidebar it will continue to have focus. As soon as you click outside of that container it will no longer have focus. This is when you will call your function to close the sidebar.

Edit for clarification: You don't need your cancel div. You could have a close button in your sidebar that on click will close the sidebar. Clicking on other content will cause the blur event to fire and close the sidebar.

<body>
   <sidebar id="sidebar" tabindex="-1"/>
   <otherContent/>
</body>

<script>
document.getElementById('sidebar').onblur = function(){
   //call your function to close sidebar         
}

//or

document.getElementById('sidebar').addEventListener('blur', (event) => {
  //call your function to close sidebar     
});
</script>

Update I came back to reference this and wanted to add that if your sidebar element has an child element like a button or something else that receives focus. You may want to add a check that for the event.relatedTarget so that it does not close your sidebar when you click a button. I came across this when creating a custom modal.

document.getElementById('sidebar').addEventListener('blur', (event) => {
    if (event.relatedTarget === null) {
         //call your function to close sidebar 
    }
}
justalittleheat
  • 387
  • 2
  • 13