working not div chrome bootstrap javascript html tabindex modal-popup

javascript - not - Restringir tabindex enfocando a una sección de la página



tabindex not working in chrome (5)

¿Qué hay de atrapar la tab-key ? En el último elemento y luego ponga el foco en el primero y viceversa con shift-tab

Esto lo estoy usando en un entorno multi-modless-diaolog, para mantener el foco en un diálogo, cambiando los diálogos con el mouse u otra tecla

inputs=".editing, input, textarea, button, a, select" no_tab="[type=''hidden''], :disabled" $focusable=dlg.$form.find(inputs).not(no_tab) $fa_first=$focusable.first() $fa_last=$focusable.last() $fa_last.on("keydown", (evt) => if evt.keyCode==9 && ! evt.shiftKey $fa_first.focus() evt.preventDefault() false ) $fa_first.on("keydown", (evt) => if evt.keyCode==9 && evt.shiftKey $fa_last.focus() evt.preventDefault() false )

edición pequeña: sustituí mi función "unibind ()" (= .off (x) .on (x)) mediante jQuery "on ()"

Situación:

Tengo una página web que abre ventanas modales (cajas de luz) que contienen formularios donde el usuario puede ingresar datos. Los usuarios generalmente navegan usando el teclado, tabulando de un campo al siguiente.

Problema:

Cuando se abre una ventana modal, solo la ventana está activa, no se puede acceder al resto de la página con el mouse, pero se puede acceder a los elementos haciendo tabulaciones fuera de la ventana modal.

Pregunta:

¿Cómo puedo restringir el movimiento usando el botón de pestaña solo para los elementos dentro de la ventana del formulario?

Lo único que se me ocurre es usar Javascript para establecer tabindex=-1 en todos los elementos del formulario (y otros elementos enfocables) cuando se abre la ventana modal y luego volver a establecer los valores de tabindex en sus valores anteriores cuando se cierra la ventana modal. ¿Hay una manera más simple / mejor?


A pesar de que es una publicación antigua, estaba buscando una solución a este problema e hice lo siguiente para resolverlo.

Al usar JQuery, deshabilité todos los campos de entrada en diferentes formas y divs tan pronto como se abriera la ventana modal (excepto las del formulario modal en sí).

$(''#formId :input'').prop(''disabled'',true);

cuando se cierra el formulario modal, puede habilitar los elementos de entrada nuevamente.

Los campos deshabilitados no se consideran al "tabular" alrededor de su página.



No, es la única manera.

  1. Encuentra todos los elementos que tienen un tabIndex mayor que -1 y no pertenecen a tu modal.
  2. Cree una matriz y rellénela con referencias a cada elemento junto con su tabIndex original.
  3. Establezca el tabIndex cada elemento en -1 para que ya no pueda recibir el enfoque del teclado.
  4. Cuando se cierre el cuadro de diálogo modal, itere sobre su matriz y restaure el tabIndex original.

Aquí hay una demostración rápida:

function isDescendant(ancestor, descendant) { do { if (descendant === ancestor) return true; } while (descendant = descendant.parentNode); return false; } var tabIndexRestoreFunctions; var lastFocused; document.getElementById("btn-show-modal").addEventListener("click", function(e) { lastFocused = document.activeElement; var modal = document.querySelector(".modal"); tabIndexRestoreFunctions = Array.prototype // get tabable items which aren''t children of our modal .filter.call(document.all, o => o.tabIndex > -1 && !isDescendant(modal, o)) // iterate over those items, set the tabIndex to -1, and // return a function to restore tabIndex .map(o => { var oldTabIndex = o.tabIndex; o.tabIndex = -1; return () => o.tabIndex = oldTabIndex; }); // show modal modal.classList.add("shown"); // focus modal autofocus modal.querySelector("[autofocus]").focus(); }); document.getElementById("btn-close-modal").addEventListener("click", function(e) { // restore tabs tabIndexRestoreFunctions && tabIndexRestoreFunctions.forEach(f => f()); tabIndexRestoreFunctions = null; // hide modal document.querySelector(".modal").classList.remove("shown"); // restore focus lastFocused && lastFocused.focus(); });

.modal { display: none; position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(128, 128, 128, .75); } .modal.shown { display: flex; } .modal-content { margin: auto; width: 500px; padding: 30px; border: 1px solid #333; background-color: #fdfdfd; }

<label>test <input autofocus /> </label> <button>dummy button</button> <hr/> <button id="btn-show-modal">open modal</button> <div class="modal"> <div class="modal-content"> <label>test <input autofocus /> </label> <button id="btn-close-modal">close modal</button> </div> </div>

Buscamos tabIndex > -1 para que podamos enfocarnos específicamente en elementos tabulables. Puedes restringir aún más ese filtro para ignorar los elementos ocultos, pero te lo dejo a ti. En cualquier caso, la lista no debería ser muy grande.
Alternativamente, como en la demostración, puede llenar la matriz con una serie de funciones cuyo único propósito es restablecer tabIndex . También puede renunciar a la matriz por completo y simplemente agregar un atributo data-original-tab-index a los elementos afectados ... usando document.querySelectorAll("[data-original-tab-index]") para recuperarlos después del hecho.

Aquí hay una demostración que usa atributos de datos para almacenar el tabIndex original para que no tenga que mantener su propia matriz:

function isDescendant(ancestor, descendant) { do { if (descendant === ancestor) return true; } while (descendant = descendant.parentNode); return false; } var lastFocused; document.getElementById("btn-show-modal").addEventListener("click", function(e) { lastFocused = document.activeElement; var modal = document.querySelector(".modal"); Array.prototype.forEach.call(document.all, o => { if (o.tabIndex > -1 && !isDescendant(modal, o)) { o.dataset.originalTabIndex = o.tabIndex; o.tabIndex = -1; } }); // show modal modal.classList.add("shown"); // focus modal autofocus modal.querySelector("[autofocus]").focus(); }); document.getElementById("btn-close-modal").addEventListener("click", function(e) { // restore tabs Array.prototype.forEach.call(document.querySelectorAll("[data-original-tab-index]"), o => { o.tabIndex = o.dataset.originalTabIndex; delete o.dataset.originalTabIndex; }); // hide modal document.querySelector(".modal").classList.remove("shown"); // restore focus lastFocused && lastFocused.focus(); });

.modal { display: none; position: fixed; top: 0; right: 0; bottom: 0; left: 0; background-color: rgba(128, 128, 128, .75); } .modal.shown { display: flex; } .modal-content { margin: auto; width: 500px; padding: 30px; border: 1px solid #333; background-color: #fdfdfd; }

<label>test <input autofocus /> </label> <button>dummy button</button> <hr/> <button id="btn-show-modal">open modal</button> <div class="modal"> <div class="modal-content"> <label>test <input autofocus /> </label> <button id="btn-close-modal">close modal</button> </div> </div>

Ver HTMLElement. dataset HTMLElement. dataset


en caso de que quiera restringir el enfoque dentro de dom "padre"

parent.addEventListener(''focusout'', function(event) { event.stopPropagation(); if (node.contains(event.relatedTarget)) { // if focus moved to another parent descend return; } parent.focus(); // otherwise focus on parent or change to another dom })

soportado por todos los navegadores mordern