Home > front end >  Tab doesn't trigger focusout event [JS,HTML]
Tab doesn't trigger focusout event [JS,HTML]

Time:12-09

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"  name="tags" required="required" autocomplete="off">
<div  style="display: block; pointer-events: all;">
  <div >
    <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:

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";
    }
});

CodePudding user response:

i dont have much time so imma leave you with this, try using this variable for the tab navigation

// check for focus
var isFocused = (document.activeElement === popup2);
alert(isFocused); // will come out false if not focused

CodePudding user response:

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"  name="tags" required="required" autocomplete="off">
<div  style="display: none; pointer-events: all;">
  <div >
    <li tabindex="0">#THING 1</li>
    <li tabindex="0">#THING 2</li>
  </div>
</div>
  
<div>
  <input/>
</div>

CodePudding user response:

One alternative is to wrap the <input> element and the "popup" <div> elements and set the listeners on those.

Run the example, click on any white space in the result window, then hit "tab" several times.

EDIT: if you use the body element, that will have the effect of for every element on the page. Just so you know.

const container = document.getElementById('container');
var popup2 = document.querySelector(".suggest-pop-up.s2");

container.addEventListener('focusout', e => {
  if (!popup2.contains(e.relatedTarget)) {
    popup2.style.display = "none";
    popup2.style.pointerEvents = "none";
  }
});
container.addEventListener('focusin', e => {
  if (!popup2.contains(e.relatedTarget)) {
    popup2.style.display = "block";
    popup2.style.pointerEvents = "all";
  }
});
<div autofocus tabindex="1">before focus in: </div>
<div id="container">
  <input id="tags" type="text"  name="tags" required="required" autocomplete="off" tabindex="2">
  <div  style="display: none; pointer-events: all;">
    <div >
      <li tabindex="0">#THING 1</li>
      <li tabindex="0">#THING 2</li>
    </div>
  </div>
</div>
after focus out: <input>

CodePudding user response:

Something is wrong with:

if (!popup2.contains(e.relatedTarget)) {
  • Related