Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

152
Visualizações
When landing on last element of focus trap, it immediately goes back to the first element

I am running into an issue with focus trapping, I have a popup with a command bar that has 3 span elements that use icons, and when I tab through them it works fine, up until I tab over to the last element and as soon I land on it, it brings me right back to the first element, and what I was expecting to happen is when I tab away from the last element then it should go back to the first element.. Click on the Save Icon and use the tab key

const element = document.getElementById("PromptsDialog");
const focusableElements = element.querySelectorAll("span:not([disabled])");

const firstFocusableElement = focusableElements[0];
const lastFocusableElement = focusableElements[focusableElements.length - 1];
element.addEventListener("keyup", function(e) {
  if (e.key === "Tab") {
    if (document.activeElement === lastFocusableElement) {
      firstFocusableElement.focus();
      e.preventDefault();
    }
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="PromptsDialog" style="display: block;">
  <div class="prompt-title-bar">
    <h4 style="margin-top:-4px;">Options Prompt</h4>
    <div id="PromptsCommand" class="">
      <div style="height:inherit">
        <span type="" tabindex="1" data-toggle="tooltip" data-placement="top" title="" data-original-title="Save" class="" id="btnSaveWindow"><i class="fa fa-save"></i></span>
        <span type="" tabindex="2" data-toggle="tooltip" data-placement="top" title="" data-original-title="Remove Item" class="" id="btnRemoveFromItemsGrid"><i class="fa fa-trash"></i></span>
        <span type="" tabindex="3" data-toggle="tooltip" data-placement="top" title="" data-original-title="Close" class="" id="btnClosePromptDialog"><i class="fa fa-remove"></i></span>
      </div>
    </div>
  </div>
</div>

Any idea on why it happens when I land on the last element?

Thanks!

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

It immediately goes back to the first element more or less because of the timing of events. In your code you are using the 'keyup' event, which triggers as soon as the 'Tab' key is released. However, the last element is focused when the 'Tab' key is pressed (down), and so pressing tab will first focus the last element, then execute your code when tab is released, immediately moving back to the first element.

An easy fix is to use the 'keydown' event instead.

const element = document.getElementById("PromptsDialog");
const focusableElements = element.querySelectorAll("span:not([disabled])");

const firstFocusableElement = focusableElements[0];
const lastFocusableElement = focusableElements[focusableElements.length - 1];
element.addEventListener("keydown", function(e) {
  if (e.key === "Tab") {
    if (document.activeElement === lastFocusableElement) {
      firstFocusableElement.focus();
      e.preventDefault();
    }
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="PromptsDialog" style="display: block;">
  <div class="prompt-title-bar">
    <h4 style="margin-top:-4px;">Options Prompt</h4>
    <div id="PromptsCommand" class="">
      <div style="height:inherit">
        <span type="" tabindex="1" data-toggle="tooltip" data-placement="top" title="" data-original-title="Save" class="" id="btnSaveWindow"><i class="fa fa-save"></i></span>
        <span type="" tabindex="2" data-toggle="tooltip" data-placement="top" title="" data-original-title="Remove Item" class="" id="btnRemoveFromItemsGrid"><i class="fa fa-trash"></i></span>
        <span type="" tabindex="3" data-toggle="tooltip" data-placement="top" title="" data-original-title="Close" class="" id="btnClosePromptDialog"><i class="fa fa-remove"></i></span>
      </div>
    </div>
  </div>
</div>

about 4 years ago · Juan Pablo Isaza Relatório

0

Keydown is a better event and this works with shift-tab too

const element = document.getElementById("PromptsDialog");
const focusableElements = element.querySelectorAll("span:not([disabled])");
const lastIdx = focusableElements.length-1;
focusableElements.forEach((elem, i) => {
  elem.dataset.next = i < lastIdx ? i+1 : 0;
  elem.dataset.prev = i >= 1 ? i-1 : lastIdx;
})

element.addEventListener("keydown", function(e) { 
  if (e.key === "Tab") {
    e.preventDefault();
    const idx = +e.target.dataset[e.shiftKey ? "prev" : "next"];
    focusableElements[idx].focus();
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="PromptsDialog" style="display: block;">
  <div class="prompt-title-bar">
    <h4 style="margin-top:-4px;">Options Prompt</h4>
    <div id="PromptsCommand" class="">
      <div style="height:inherit">
        <span type="" tabindex="1" data-toggle="tooltip" data-placement="top" title="" data-original-title="Save" class="" id="btnSaveWindow"><i class="fa fa-save"></i></span>
        <span type="" tabindex="2" data-toggle="tooltip" data-placement="top" title="" data-original-title="Remove Item" class="" id="btnRemoveFromItemsGrid"><i class="fa fa-trash"></i></span>
        <span type="" tabindex="3" data-toggle="tooltip" data-placement="top" title="" data-original-title="Close" class="" id="btnClosePromptDialog"><i class="fa fa-remove"></i></span>
      </div>
    </div>
  </div>
</div>

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda