focus-not-removed-by-script
Un script no debe quitar el foco a un elemento cuando lo recibe
Hace fallar los elementos del orden de tabulación cuyo manejador onfocus en línea solo llama a blur() sobre ellos, y pregunta por otros manejadores que llaman a blur(), o a focus() sobre otro elemento, lo que puede quitar el foco en cuanto el elemento lo recibe (fallo F55 de WCAG).
Ámbito de aplicación. Elementos que pueden recibir el foco, que la página renderiza y cuyo manejador onfocus en línea llama a blur(), o a focus() sobre otro elemento. Sin un elemento así, o en un documento en el que ninguno puede recibir el foco, nada es aplicable.
Resultado esperado. Fallo F55 de WCAG: un script que quita el foco a un elemento cuando lo recibe deja a un usuario de teclado sin poder alcanzarlo ni operarlo, y sin poder ver dónde está el foco.
FOCUS_HANDLER_BLURS_SELF:fail, en un elemento del orden de tabulación, cuando el manejador solo hace eso (this.blur(),blur(), oblur()sobreevent.targetoevent.currentTarget, por nombre o entre corchetes, posiblemente trasif (this.blur), con como mucho unreturn), como hacen los ejemplos de F55. El foco no va a ninguna parte: se pierde, no se envía a otro sitio. Fuera del orden de tabulación (tabindex="-1"), donde un usuario de teclado no llega, se pregunta por él.
Por cada uno de los demás elementos se pregunta (cantTell):
FOCUS_HANDLER_CALLS_BLURcuando llama ablur()entre otro código, o sobre otro elemento, donde que el foco se pierda depende del script;FOCUS_HANDLER_MOVES_FOCUScuando llama afocus()sobre otro elemento (document.body.focus()), lo que se lleva el foco en cuanto llega, como comprueba la prueba de F55.
Un manejador que envía el foco a otro sitio (un centinela de una trampa de foco, una redirección) es el caso de mover el foco y se pregunta por él, nunca falla: la regla lee el texto del manejador, no lo que hace la página, y una persona puede confirmarlo tabulando hasta el elemento.
Qué informa un hallazgo.
reasonCode:FOCUS_HANDLER_BLURS_SELF,FOCUS_HANDLER_CALLS_BLURoFOCUS_HANDLER_MOVES_FOCUS.handler: el valor del atributo onfocus, con los espacios colapsados, hasta 120 caracteres; uno más largo se corta y termina en….tabbable: si el elemento está en el orden de tabulación. Uno que no lo está puede seguir recibiendo el foco con un clic o desde un script.
Estos campos de data.details ayudan a leer y reproducir un hallazgo. Salvo reasonCode y los pocos campos que Esquema de salida indica como estables, no son un contrato estable: un campo puede cambiar de nombre o desaparecer en una versión menor, así que no construyas sobre ellos.
Ejemplos
<a href="/offers" onfocus="this.blur()">Offers</a>
El enlace se quita el foco a sí mismo en cuanto lo recibe, el propio ejemplo del fallo F55 de WCAG: un usuario de teclado no puede permanecer en él para seguirlo.
<button type="button" onfocus="if (locked) this.blur(); track('focus')">Send</button>
El manejador llama a blur() entre otro código, así que que el foco se pierda depende del script.
<span onfocus="this.blur()">Label</span>
El <span> no puede recibir el foco, así que su manejador nunca se ejecuta.
Cómo comprobarlo
Cuando esta regla no puede decidir, informa cantTell y deja la pregunta a una persona. Cada pregunta que puede plantear aparece aquí bajo su código de motivo, con los pasos para responderla. Un hallazgo lleva los mismos pasos en howToCheck, en el idioma del análisis. Consulta Esquema de salida.
FOCUS_HANDLER_BLURS_SELF
- Hacer clic justo antes del elemento que indica el informe y pulsar Tab hasta que el foco debiera llegar a él (si no está en el orden de tabulación, hacer clic en él).
- Observar el indicador de foco y, en la consola de las herramientas para desarrolladores, comprobar document.activeElement.
- Pulsar Tab una vez más y ver adónde va el foco.
Se cumple. El foco se queda en el elemento, su indicador de foco se muestra y el siguiente Tab pasa al control siguiente.
No se cumple. El foco desaparece del elemento en cuanto llega, así que no se puede alcanzar ni accionar con el teclado, lo que incumple WCAG 2.1.1 y 2.4.7 (F55).
FOCUS_HANDLER_CALLS_BLUR
- Leer el manejador onfocus que cita el informe y anotar cuándo llama a blur() y sobre qué elemento.
- Hacer clic justo antes del elemento y pulsar Tab hasta que el foco debiera llegar a él; repetirlo en cada estado que compruebe el manejador (por ejemplo, un campo relleno o vacío).
- Observar el indicador de foco y comprobar document.activeElement en la consola de las herramientas para desarrolladores.
- Intentar accionar el elemento con el teclado (escribir, pulsar Intro o Espacio).
Se cumple. En todos los estados, el foco se queda en el elemento, su indicador de foco se muestra y se puede accionar con el teclado.
No se cumple. En algún estado se quita el foco en cuanto el elemento lo recibe, así que no se puede accionar con el teclado o se pierde de vista el foco, lo que incumple WCAG 2.1.1 y 2.4.7 (F55).
FOCUS_HANDLER_MOVES_FOCUS
- Leer el manejador onfocus que cita el informe y anotar a qué elemento envía el foco.
- Hacer clic justo antes del elemento, pulsar Tab hasta que el foco debiera llegar a él y ver dónde queda el foco (comprobar document.activeElement en la consola).
- Si el elemento es un centinela invisible y sin nombre en el borde de un diálogo que devuelve el foco a su interior, tener en cuenta que es una trampa de foco de un modal y es lo esperado.
- Si no, intentar accionar el elemento con el teclado y pulsar Mayús+Tab para ver si puede volver atrás.
Se cumple. El foco va a un lugar lógico (el ciclo de foco de un diálogo) o se queda en el elemento, y todos los controles se pueden seguir alcanzando y accionando con el teclado.
No se cumple. Un control visible envía el foco a otra parte en cuanto llega, así que no se puede alcanzar ni accionar con el teclado, lo que incumple WCAG 2.1.1 y 2.4.7 (F55).