Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Tab doesn't trigger focusout event [JS,HTML]

I have a pop up list that suggest search results kinda like when searching on google.
I have 2 event listeners that are supposed to show and hide the popup if you click out of the area. It works with clicks but if you try to navigate with tabs it just keeps it open forever.

How would I make the focusout event happen when navigating with tabs?

var popup2 = document.querySelector(".suggest-pop-up.s2");

document.getElementById('tags').addEventListener('focusout', e => {
  if (!popup2.contains(e.relatedTarget)) {
    popup2.style.display = "none";
    popup2.style.pointerEvents = "none";
  }
});
document.getElementById('tags').addEventListener('focusin', e => {
  if (!popup2.contains(e.relatedTarget)) {
    popup2.style.display = "block";
    popup2.style.pointerEvents = "all";
  }
});
<input id="tags" type="text" class="suggest s2" name="tags" required="required" autocomplete="off">
<div class="suggest-pop-up s2" style="display: block; pointer-events: all;">
  <div class="suggest-box s2">
    <li tabindex="0">#THING 1</li>
    <li tabindex="0">#THING 2</li>
  </div>
</div>

<br><div>I want #THING 1 and #THING 2 to appear on 1. tab press, then to be selectable while on any of the <li> and then to go away when tabing to the next element outside suggest-box s2.</div>

Edit:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The issue was that I was only listening for focusout on the #tags input element. Making it listen on the whole body does the job.
This is how I have it now:

document.body.addEventListener('focusout', e => { 
    if (!popup2.contains(e.relatedTarget)) {
        popup2.style.display = "none"; 
        popup2.style.pointerEvents = "none";
    }
});
document.getElementById('tags').addEventListener('focusin', e => { 
    if (!popup2.contains(e.relatedTarget)) {
        popup2.style.display = "block"; 
        popup2.style.pointerEvents = "all";
    }
});

>Solution :

Your only ever going to get focusOut once when it leaves, so a better way to approach this might be with a delegated event on the body.

Below is an example using a delegated event on the body tag, it then uses closest to see if it’s any of the items, if so it will not collapse.

const popup2 = document.querySelector(".suggest-pop-up.s2");

document.body.addEventListener('focusout', e => {
  if (e.relatedTarget && e.relatedTarget.closest('.suggest-pop-up')) return;
  popup2.style.display = "none";
  popup2.style.pointerEvents = "none";
}); 

document.getElementById('tags').addEventListener('focusin', e => {
  popup2.style.display = "block";
  popup2.style.pointerEvents = "all";
});
<input id="tags" type="text" class="suggest s2" name="tags" required="required" autocomplete="off">
<div class="suggest-pop-up s2" style="display: none; pointer-events: all;">
  <div class="suggest-box s2">
    <li tabindex="0">#THING 1</li>
    <li tabindex="0">#THING 2</li>
  </div>
</div>
  
<div>
  <input/>
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading