ValidationSummary accesible en MVC 5

¡Hola!

Hoy os vengo con un truquillo que, en caso de estar desarrollando webs accesibles en MVC, os puede venir bien.

Una de las cosas que considero muy importantes a la hora de mostrar una lista de errores de cumplimentación de formularios, es encabezar la misma con una cabecera, de modo que el usuario de lector de pantallas, al navegar por la lista de encabezados, dé con el resumen de los errores de formulario de forma fácil. Si obviamos esta cabecera, es posible que esa lista pase desapercibida, o al menos es lo que me dice la experiencia 🙂

En MVC 4, hasta donde recuerdo, no existía la sobrecarga de ValidationSummaryFor que os muestro a continuación, y que sí está disponible en MVC 5:

@Html.ValidationSummary("Revisa los siguientes errores", new { @class = "text-danger" }, "h3")

Esta extensión de HtmlHelper pinta una lista de errores, añadiéndole la clase text-danger (estoy usando bootstrap), y encabezando la lista con una etiqueta “h3” que encerrará el mensaje pasado en el primer parámetro.

¿La única pega de todo esto? Que el encabezado con el mensaje se ve siempre aunque no haya errores 🙁 .
Sin embargo, este método pinta una clase por defecto cuando el formulario es válido: “validation-summary-valid”; así que con un poco de magia CSS, podemos añadir lo siguiente a nuestra hoja de estilos:

/* para ocultar los encabezados de los validation summary si son válidos */
.validation-summary-valid {
	display: none;
}

¿Más fácil? ¡Imposible!

Y ahora ya, como truquillo de nota, podríamos hacer una pequeña mejora a la experiencia del usuario, añadiendo, mediante jquery, una función que ponga el foco en la lista de errores cuando esta esté visible. Así, un usuario de lector de pantallas, escuchará el encabezado con el mensaje que hayamos puesto, y será consciente al instante de que algo pasa con ese formulario.
Añadamos este script a nuestro sitio (recordad que necesitaréis jquery):

$(function () {
	var encabezado = $(".validation-summary-errors:last :header");
	if (encabezado.length) {
		encabezado.attr("tabindex", "-1");
		encabezado.focus();
	}
});

¡

Et Voilà!

¿Qué estamos haciendo aquí?

  1. Adjuntándonos al evento onDocumentReady, para que esto se ejecute cuando la página esté cargada.
  2. Buscando el último elemento con la clase validation-summary-error, y dentro de él, cualquier encabezado, sea del nivel que sea.
  3. Si lo encuentra, le pone tabIndex a -1 para poder focalizar en él de forma programática.
  4. Y por último, fuerza el foco a ese encabezado.

A mí personalmente me gusta crear un bundle de scripts de accesibilidad, y meter en él pequeños ficheros, cada uno de los cuales realiza una acción concreta. Así tengo la sensación de que mi código es más fácil de mantener.

¡Espero que os sirva!

¡A disfrutar picando! 😉

Entrada visitada 722 veces

Evitar interacciones no deseadas al ocultar elementos con animación en jQuery

¡Hola!

Esta mini entrada surge por un problema que estaba teniendo con unas animaciones en jQuery.

Resulta que estoy mostrando y ocultando una lista de enlaces usando fadeIn, fadeOut, slideDown y slideUp, dándole un tiempo de animación tanto en mostrar como en ocultar. ¡Estas cosas que a los que veis os molan tanto, que eso de que aparezcan y desaparezcan elementos de la pantalla así de golpe como que no os mola! 😉
Pues resulta que me di cuenta de algo obvio pero que no se me había ocurrido: Durante una animación de desaparición (por deslizamiento o por transparencia), el usuario de lector de pantallas puede seguir interactuando con los elementos, sin darse cuenta de que esos elementos están desapareciendo.
Y como a mí me la traen al fresco las animaciones y las desapariciones progresivas, se me ocurrió usar, durante las desapariciones, un atributo que oculta elementos para lectores de pantalla. Este atributo, dentro de las recomendaciones ARIA de la w3c, es “aria-hidden“, que ajustado a true, oculta la etiqueta en la que se aplique a lectores de pantalla.

Así que, podríamos usar el siguiente código para ocultar un ul durante 400 milisegundos, pero que desde el primer momento ya no se muestre a lectores de pantalla aunque tarde un rato en desaparecer:

lista.attr("aria-hidden", "true").slideUp(200, function () { $(this).removeAttr("aria-hidden"); });

¿Qué estamos haciendo?

  1. Ocultamos el elemento a lectores de pantalla.
  2. Lanzamos la animación de desaparición.
  3. Cuando se completa la animación, volvemos a mostrar el elemento a lectores de pantalla, pues como ya está oculto con display:none, no será visible para nadie. Vuelvo a quitar el aria-hidden, ya que si luego queremos volver a mostrar el elemento, los lectores no lo verán si esa propiedad se ha quedado a true :).

¡Mucho cuidado con aria-hidden y display:none! Si un elemento tiene display:none pero aria-hidden está a false explícitamente (no que no esté el atributo, sino puesto a false), el elemento será mostrado a lectores de pantalla pese al display:none. ¡Flipante!

¡Espero que este truquillo os pueda servir!

¡Buena semana!

Entrada visitada 520 veces