it-swarm.dev

¿Cómo puede restringir la presión de la tecla tabulador solo dentro de la ventana emergente modal cuando está abierta?

Tengo una ventana emergente modal abierta. Tengo un requisito de accesibilidad. Entonces se agregaron etiquetas relacionadas con ARIA. Pero cuando hago clic en la tecla de tabulación continuamente me enfoco yendo a la página detrás de la página real.

Función agregada = "diálogo" en el archivo html

Pero cuando se abre modal solo quiero que el foco navegue dentro de la ventana emergente modal.

Trabajando en Angular4, HTML5 proyecto. Mejor si encontramos una solución dentro del archivo HTML. Quiero decir, sin agregar ningún elemento relacionado con javascript/jQuery para evitar esto

5
Prince

Está preguntando acerca de foco trampa , está bien demostrado en esta demostración: http://davidtheclark.github.io/focus-trap/ demo /

Añadiendo role="dialog" no proporcionará automáticamente la captura del foco dentro de ese elemento. De hecho, no hay ninguna trampa de enfoque nativa proporcionada por los navegadores.

Debe ir con una de las siguientes opciones:

5
Limon Monte

tenga cuidado con cualquier método que se base solo en eventos javascript, ya que no manejará correctamente los lectores de pantalla

Sin embargo, esto no se puede lograr sin javascript, como ya se indicó en varias preguntas como ¿Cómo mantener el enfoque dentro del diálogo modal?

Tienes tres pasos para hacer:

1. deshabilite la interacción del lector de pantalla con cualquier otro nodo estableciendo aria-hidden=true en ellos

Por ejemplo:

<main aria-hidden="true"><!-- main content here--></main>
<dialog>Your dialog here</dialog>

2. deshabilitar cualquier interacción del teclado con ellos

Esto tiene que hacerse en Javascript/o jQuery.

Esta es una instrucción de una línea en jQuery, usando jquery-ui

$("main :focusable").addClass("disabled").attr("tabindex", -1);

Lo contrario se puede lograr usando:

$(".disabled").removeClass("disabled").attr("tabindex", 0);

3. eliminar cualquier evento de puntero para esos elementos para deshabilitar la interacción del mouse

muestra css:

main[aria-hidden='true'] { pointer-events: none;}
3
Adam

Aquí está mi solución. Atrapa Tab o Shift + Tab según sea necesario en el primer/último elemento del diálogo modal (en mi caso encontrado con role="dialog"). Los elementos elegibles que se verifican son todos los controles de entrada visibles cuyo HTML puede ser input,select,textarea,button.

$(document).on('keydown', function(e) {
    var target = e.target;
    var shiftPressed = e.shiftKey;
    // If TAB key pressed
    if (e.keyCode == 9) {
        // If inside a Modal dialog (determined by attribute role="dialog")
        if ($(target).parents('[role=dialog]').length) {                            
            // Find first or last input element in the dialog parent (depending on whether Shift was pressed). 
            // Input elements must be visible, and can be Input/Select/Button/Textarea.
            var borderElem = shiftPressed ?
                                $(target).closest('[role=dialog]').find('input:visible,select:visible,button:visible,textarea:visible').first() 
                             :
                                $(target).closest('[role=dialog]').find('input:visible,select:visible,button:visible,textarea:visible').last();
            if ($(borderElem).length) {
                if ($(target).is($(borderElem))) {
                    return false;
                } else {
                    return true;
                }
            }
        }
    }
    return true;
});
1
gene b.

En este momento también Angular CDK proporciona la directiva para agregar una trampa de enfoque a la ventana emergente modal https://material.angular.io/cdk/a11y/api#CdkTrapFocus

0
Stefan

el elemento de diálogo primario debe tener role="dialog" para indicar que esto es un diálogo. En tu caso, también te falta el aria-modal="true" que debería decirle al navegador y a los lectores de pantalla que el enfoque debe permanecer solo dentro del modal.

Utilizando aria-modal="true" reemplaza la necesidad de agregar aria-hidden="true" para elementos que deben ocultarse de los lectores de pantalla y no recibir el foco del teclado fuera del modal mientras este esté abierto.

Si el método anterior no funciona, es posible que aún desee utilizar aria-hidden="true" para el elemento padre fuera del modal para evitar que el teclado abandone el modal.

Si por alguna razón aún no funciona y necesita control manual sobre el enfoque del teclado, puede verificar qué elementos reciben el enfoque del teclado fuera del modal y luego establecer su atributo tabindex en tabindex="-1", lo que significa que aún pueden recibir foco pero no desde el teclado. En este enfoque, debe tener cuidado, porque cuando se cierre el modal, querrá restaurar la funcionalidad eliminando el tabindex="-1" de esos elementos o volviéndolo a poner a tabindex="0"

Fuente: prácticas de wai aria del W3C - diálogo modal con ejemplo

0
Shahar

Una solución que no es jQuery que pasa solo por los elementos de entrada del modal


// place this line in the dialog show function - to only add the listener when the dialog is shown
window.addEventListener('keydown', handleKey);

// uncomment and place this in the dialog close/hide function to remove the listener when dialog is closed/hidden
// window.removeEventListener('keydown', handleKey);

function handleKey(e) {
    if (e.keyCode === 9) {
        let focusable = document.querySelector('#modal').querySelectorAll('input,button,select,textarea');
        if (focusable.length) {
            let first = focusable[0];
            let last = focusable[focusable.length - 1];
            let shift = e.shiftKey;
            if (shift) {
                if (e.target === first) { // shift-tab pressed on first input in dialog
                    last.focus();
                    e.preventDefault();
                }
            } else {
                if (e.target === last) { // tab pressed on last input in dialog
                    first.focus();
                    e.preventDefault();
                }
            }
        }
    }
}
0
lilotop