¿Accesibilidad y javascript?
acc_calendar: Calendario accesible en javascript (innecesario pero útil)
Actualizado el 1 de Junio de 2008, por Rumoroso
En los campos de formulario en los que se tiene que introducir una fecha, de cara a mejorar la experiencia de usuario, y a la par que se aumenta el control en el formato de los datos, se puede incluir un calendario mediante javascript. Lo se, palabra maldita, aunque si se hace con cuidado y control, no tiene por qué tener implicaciones negativas en cuanto a estándares y accesibilidad.
Objetivos
En principio he establecido dos objetivos principales, que más que objetivos han sido pautas de trabajo a la hora de construirlo:
- Que sea accesible y no obstrusivo. Evidentemente, en ausencia de soporte para javascript no se ofrece la opción de desplegar el calendario, pero, si hay soporte… ¿por qué no hacer que el contenido generado sea accesible y utilizable?
- Que sea fácil de implementar y utilizar. He buscado una forma tal los programadores que deseen implementarlo en sus páginas web no requieran de introducir código adicional. Al igual que en CSS se utilizan diversos tipos de selectores (de elementos, id, clases,…) para asociar estilos a las diferentes partes de nuestros documentos, ¿por qué no utilizar lo mismo para asociar comportamientos?
Además, como objetivos secundarios están: optimizar, generalizar, internacionalizar,… (siendo realista, tuve que eliminar los objetivos de ligar y el de ganar dinero.)
Incluyéndolo en nuestros documentos
Antes de nada indicar que el script se puede obtener directamente descargando el ejemplo completo.
La inclusión del calendario en nuestro documento es tan sencillo como incluir el elemento script correspondiente en el head:
<script type="text/javascript" src="acc_calendar/acc_calendar.js"> </script>
El calendario se cargará para cualquier campo de texto que lleve incluida la clase “fecha“ (si el idioma del documento es el español). El formato de la fecha se introduce en la primera línea del script. Así, si por ejemplo se desea que la fecha siga el orden día/mes/año, no incluyendo un 0 delante del día cuando esté formada por un dígito, e incluyéndolo en el mes cuando sea necesario, y que el formato para el año sean 4 dígitos:
var formato = 'd/mm/yyyy';
Como ya se mencionó, para conseguir mostrar el calendario junto a un campo de texto, este deberá llevar la clase “fecha” si el idioma declarado para el documento es el español (“date” si es el inglés, etc). Estos nombres de clase se pueden modificar, añadir nuevos para otros idiomas, etc., directamente en el script. Además, todos los posibles parámetros se introducen como clases. La lista completa es la siguiente:
- Cargar calendario (requerido):
fecha - Fechas previas a hoy:
prev - Fechas posteriores a hoy:
post - Rango de años:
rangX(siendo X el número de años) - No se incluye el día actual:
todnact - Aplciar filtro para fechas disponibles:
disp
¿Y si cargo dinamicamente los input con AJAX?
El script tiene la propiedad de que si en cualquier momento se introducen nuevos campos de texto de forma asíncrona con AJAX, bastará con que tras dicha carga se llame a la función cargaLinks() para que a los inputs se les asocien los enlaces para la apertura del calendario
Primer ejemplo
<input class="fecha post" type="text"
id="fecha1" name="fecha1" value="" />
<input class="fecha post todnact" type="text"
id="fecha2" name="fecha2" value="" />
<input class="fecha prev rang100" type="text"
id="fecha3" name="fecha3" value="" />
<input class="fecha post rang20 todnact" type="text"
id="fecha4" name="fecha4" value="" />
<input class="fecha prev rang15" type="text"
id="fecha5" name="fecha5" value="" />
<input class="fecha rang10" type="text"
id="fecha6" name="fecha6" value="" />
Nueva Mejora (abril 2007)
En ocasiones podríamos desear que la fecha se introduzca en tres campos de texto, uno para cada dato que la compone. Se ha añadido la posibilidad de hacerlo. Para ello seguiremos controlándolo todo mediante el uso de clases asignadas a los input.
Para que constituyan un grupo, los tres campos de texto deberán añadir un código que los identifique como tal. Esto, que parece algo raro, no lo es tanto. En realidad, lo que hay que hacer es añadir a la palabra fecha que empleamos como clase en los tres, una letra o un número. Así, por ejemplo, les podríamos aplicar a los tres la clase “fechaA” e inmediatamente, además de asociarse el enlace para la apertura del calendario, se pasarían a comportar como un grupo. Más adelante se incluyen dos ejemplos que lo muestran claramente.
Cada uno de los campos deberá llevar una clase en función del dato que se le asocie:
- Para el campo día la clase “
day“ - Para el campo mes la clase “
month“ - Para el campo año la clase “
year“
Existe total libertad para el orden en el que se pongan, colocando las clases para la configuración del calendario (número de años, previos, posteriores, etc.) en el primero de los campos que se utilice. En el ejemplo siguiente se podrá apreciar la forma de hacerlo:
Segundo ejemplo
Fecha de los próximos 10 años en formato día, mes, año: / /
<input class="fechaA day post rang10"
maxlength="2" type="text" id="dia" name="dia" value="" />
<input class="fechaA month"
maxlength="2" type="text" id="mes" name="mes" value="" />
<input class="fechaA year"
maxlength="4" type="text" id="year" name="year" value="" />
Consideración importante es informar siempre al usuario de cuál es el campo para cada cosa. En el ejemplo se informa en el texto previo y además, las etiquetas de los input lo incluyen.
Fecha de los últimos 15 años en formato año, mes, día: / /
<input class="fechaB year prev rang15"
maxlength="4" type="text" id="otroyear" name="otroyear" value="" />
<input class="fechaB month"
maxlength="2" type="text" id="otromes" name="otromes" value="" />
<input class="fechaB day"
maxlength="2" type="text" id="otrodia" name="otrodia" value="" />
Consideración importante es informar siempre al usuario de cuál es el campo para cada cosa. En el ejemplo se informa en el texto previo y además, las etiquetas de los input lo incluyen.
Actualización (abril de 2007)
Se ha retocado el script para reducir los estilos que se aplican desde este. Ahora, el enlace generado tiene la imagen por contenido (antes esta se cargaba desde la hoja de estilos). El enlace se genera inmediatamente después del input (fuera del label si está incluido en él) y posee el siguiente marcado:
<a title="Desplegar para seleccionar la fecha para fecha"
href="#" class="enl_cal">
<img src="acc_calendar/acc_calendar.png" alt="Calendario">
</a>
En el caso de que sea el enlace para la carga de la fecha en tres campos de texto, la clase del enlace pasa a ser “enl_cal_group, y este se situa antes del primero de ellos.
Actualización (7 de julio de 2007)
De forma opcional y mediante una consulta ajax se puede aplicar un filtro para que únicamente determinados días del mes esten disponibles como enlaces. Para ello, el script envía mediante el método POST las variables month (mes en forma de número) y year, y este ha de devolver (mediante el lenguaje de servidor que queramos) la secuencia de días disponibles separados por comas. Al inicio del código del script se encuentra una variable (fichero_consulta) donde pondremos la dirección sobre la que resolver la consulta. Aquellos campos en los que queramos aplicar el filtro deberán incluir la clase disp (además de las restantes que ya se han mencionado).
Y como con ejemplos se puede entender mejor:
Fecha de este año (el calendario permitirá la elección exclusiva de días disponibles): / /
<input class="fechaN day disp"
maxlength="2" type="text" id="dian" name="dian" value="" />
<input class="fechaN month"
maxlength="2" type="text" id="mesn" name="mesn" value="" />
<input class="fechaN year"
maxlength="4" type="text" id="yearn" name="yearn" value="" />
* Actualización (21 de octubre de 2007)
Se acaban de incluir dos pequeñas variaciones en el script:
- La posibilidad de que el formato del año sea de dos o cuatro dígitos.
- La posibilidad de que se muestre el día de la semana cuando se ha seleccionado la fecha. Esto es posible si en el documento se incluye un elemento cuya “id” sea “nombre_dia_†más la “id†del campo donde se va a incluir la fecha, en el caso de utilizar un único campo de texto para esta, o la “id” del campo donde se incluirá el día si se emplean tres campos para ello.
Esta última modificación no implica la necesidad de incluir dicho elemento. El script reconoce su presencia si lo hay y en este caso, lo utiliza. No se ha considerado la opción de hacer que el script carge el nombre del día dentro del campo de texto, dado que esto tendría implicaciones en el formato a emplear en el caso de que el usuario tuviese que escribirlo directamente. A continuación se incluye un ejemplo de aplicación.
<span id="nombre_dia_fechaj"></span>
<input class="fecha post" type="text"
id="fechaj" name="fechaj" value="" />
* Actualización (1 de junio de 2008)
Gracias a Gerard y a su aportación, ahora el script para el calendario presenta dos nuevas mejoras.
- El script reconoce si el campo de texto al que se le asocia el calendario es readonly, evitando enviarle el foco al cerrarlo. Previo a esta modificación, en el caso de tener esta característica el mencionado campo de texto, el script podría devolver un error.
- Añadido soporte para el catalán.
Nuevamente le agradezco a Gerard su aportación e invito a todos a continuar mejorando el acc_calendar.
* Estilos enviados por los lectores
Cesar Caballero nos envió un nuevo estilo para el calendario. Si lo queréis utilizar, únicamente lo tenéis que descargar y remplazar por el archívo homónimo.
Gracias por vuestras aportaciones. Podéis enviar los estilos que queráis y aquí los enlazaremos.
Ventajas
Entre las ventajas que se le pueden atribuir tenemos:
- Fácil de usar e implementar.
- No es intrusivo.
- El código y el contenido que se genera es accesible (marcado, organización, contenido,…) y es utilizable mediante el uso de ayudas técnicas (lector de pantalla,…). En este punto se ha tenido en cuenta en qué lugar recae el foco tanto al mostrarse como durante el funcionamiento y al desaparecer. Así, cuando se muestra, el foco recae directamente sobre el selector de años, siguiendo un orden lógico al tabular desde él, y cuando se cierra el calendario (mediante el enlace de cierre o tras haber seleccionado una fecha) el foco recae sobre el campo de texto al que se le había asociado.
- Se facilita la navegación por el mismo independientemente del dispositivo. Se puede navegar utilizando cualquiera de los dispositivos con los que podamos navegar por la web.
- Sus parámetros son fácilmente configurables y su llamada muy simple (mediante el uso de nombres de clase).
- El idioma lo toma directamente del documento padre, pudiendo añadir traducciones nuevas al código. En el caso de no estar declarado el idimoa en el documento (cosa que no debe ocurrir), el español será el que se utilice por defecto. Actualmente, además del español incluye el inglés. Adicionalmente se ha hecho que reconozca si es inglés americano, no porque vaya a cambiar el contenido, sino para cambiar la disposición de los días de la semana (el domingo se coloca primero).
- Los estilos aplicados al calendario se incluyen mediante una CSS enlazada por medio del script, con lo que en ausencia de soporte para este, se optimiza la descarga del documento al no llamarse a dicha hoja de estilos.
- Se han incluido clases de tal manera que se puedan aplicar estilos sobre cualquiera de las celdas de la tabla (días activos, días no activos, día actual), así como estilos específicos para los sábados o domingos.
Conclusión
A modo de cierre… ¿qué se podría decir de este calendario?… pues que “es innecesario… pero útil” y que “no tiene implicaciones negativas en términos de accesibilidad“.
…por cierto ¿qué día es hoy?

Buenas,
he estado mirando tu codigo y veo q hay un BUG, si te fijas hoy es 31 de mayo del 2010 lunes y mañana sera 1 de junio martes no?, pues bien en el calendario me aparece q es jueves
espero que no tardes en solucionarlo, no es por fastidiar solo que a coincidido las fechas y mejor que te avise ahora a quedarme callado
Saludos y espero que sea facil de solucionar
oye tengo un pequeño problema, tnego mi formulario dentro de una tabla y así el calendario no funciona;es decir, no aparece la imagen para abrirlo ni nada.Al eliminar toda la tabla y dejar sólo el cuadro de la fecha funciona a la perfección; alguna recomendacion? he tratado de todas las formas y no hallo solucion; y trabajar mi formulario sin la tabala es muy tedioso y anti-estético, por tanto preferiria una solucion k incluya tanto el formulario como la tabla, de antemano agradezco sus respuestas
Hola, estoy realizando un proyecto final de carrera y no consigo que me funcione este calendario. No me aparece la clase “fecha post”, bueno esta ni ninguna. Me descarge el “ejemplo completo” ,adjunte el script en el head , modificando las rutas del acc_calendar.js, añadí el input a mi código,pero no consigo que me salga la imagen para mostrar el calendario, y por supuesto, no me aparece el calendario. Un saludo
Siento haber tardado en responderos.
Andrés, seguramente el problema está en que tienes la etiqueta label y el input correspondiente separados en celdas de la tabla diferentes. Te recomiendo que no utilices la tabla para maquetar el formulario, pues aunque parezca más sencillo, no resulta correcto (las tablas son para datos, no para maquetar). Reconozco que puede ser más laborioso trabajar con otros elementos y CSS, pero te garantizo que se puede llegar a tener el mismo resultado visual y con un código más correcto.
Merk, no tengo muy claro a qué te refieres cuando dices que “no te aparece la clase…”. Esa clase la has de poner tu para que el script reconozca sobre qué campos ha de trabajar.
Un saludo
Ok, muchas gracias.
Hola Rumoroso! Antes que nada felicitarte por tu excelente calendario.
Te cuento que tardé varias horas tratando de hacer funcionar el calendario, hasta que me di cuenta de que no funcionaba porque en la etiquete body tenia algo así como:
...dado que mis conocimientos de javascript son muuy limitados, y después de mucho pensar, probar varias cosas y analizar tu código, di con una solución que aqui te expongo:
En el head de mi pagina coloco el siguiente script:
function focalizar()
{
var cosa=document.getElementById("campo");
cosa.focus();
}
addLoadEvent(focalizar);
Por lo pronto esto funcionó, pero dada mi casi nula experiencia y conocimientos en javascript te pregunto ¿Es esto correcto?, ¿existe una mejor forma de hacerlo?
por lo pronto espero que esta solución sea útil para alguien mas
Salu2
Hola Ulises. La verdad es que no me ha quedado muy claro el motivo por el que no te funcionaba y la forma en que lo solucionaste. Si quieres que lo mire un poco, enlaza un ejemplo o envíamelo para que le eche un vistazo.
Un saludo
Hola Rumoroso, muchas gracias por tu atención!! Leí detenidamente mi comentario anterior y me doy cuenta de que no fui muy explicito, y peor, no escribí bien el primer código, por lo cual te suplico una disculpa.
Te cuento un poco mas detallado
Resulta que deseo que al abrir el documento html, (el cual contiene un formulario) se ubique el foco en un text input en particular, para lograrlo, utilizaba el evento onload en la etiqueta body del documento. Es decir mi codigo en el html era algo asi como:
.....Descubrí que al utilizar el evento onload en la etiqueta body, el calendario ya no funciona. Después de analizar tu código, me di cuenta que creaste un mecanismo para agregar funciones que se ejecutan al cargar el documento, y lo único que tuve que hacer fue definir una función que ubicara el foco (e inicializar otros campos) donde deseo, y agregarla con la función
addLoadEventDespués de este par de días de pensarlo, creo que esta es la única y mejor forma de hacer que se ejecuten funciones al cargar la pagina al utilizar tu excelente calendario
Por otra parte, como te comentaba anteriormente, apenas estoy aprendiendo sobre html, y javascript, y también tardé algún tiempo en darme cuenta que es imprescindible colocar una etiqueta “label” asociada con el text input. de lo contrario el calendario no se mostrará.
Disculpa la molestia, al final creo que yo mismo me contesté, pero también quise compartir mi experiencia con todos aquellos, que como yo, que apenas estamos aprendiendo, y a quienes cosas que son evidentes para algunos para otros todavía no lo son! jejeje!
El código completo ahora mismo no lo tengo a la mano, en realidad es para una tarea de la escuela, pero si deseas con gusto te lo envío para que puedas ver claramente mi error.
Salu2 y gracias
Sigo sin lograr colocar el codigo del body….
intento con otros caracteres…
{body onload="document.getElementById('campo').focus()"}.....El hecho es que hacer que cualquier funcion se ejecute al cargar la pagina, provoca que el calendario ya no funcione
Hola Ulises. Perdona que no te haya respondido antes. La cuestión es que el calendario se carga gracias al evento asociado a la carga del documento. Por eso, cuando le añades el onload al body, es como si sobreescribieses el evento que yo declare para cargar el calendario.
En el caso de que quieras añadir funcionalidades al evento onload, lo que tendrías que hacer es utilizar la función que puse en el script y que resulta fácil de llamar. Mira al final del script y verás la función “addLoadEvent”. Esta permite ejecutar todas las funciones que quieras al cargar. Así, por ejemplo, yo tengo addLoadEvent(carga_estilos) y addLoadEvent(cargaLinks), que llaman respectivamente a las funciones para cargar los estilos y ejecutar la carga de los calendarios.
Lo que tendrías que hacer es incluir en una función lo que quieres ejecutar. Por ejemplo:
function focaliza() {document.getElementById(‘campo’).focus();}
y luego añades al final:
addLoadEvent(focaliza);
Esto te debería funcionar…
Suerte y un saludo
Hola como estan saludos antes que nada e intentado implementar este calendario pero no me deja ver ni el icono no c si sea porque e utilizado ajax no veo la forma de como, (index.php –> Configuración )tengo 1 link k me manda a cargar un formulario (configuracion.php)con ajax en una area de index tiene un campo de texto fecha6 lo deje con lo mismo del class del ejemplo descargable a esa pagina le agrege el include de script y el css, deje tal cual las carpetas descargadas en mi localhost y no me jala el calendario XD si pudieran ayudarme mucho mejor
He probado el calendario y funciona muy bien en IE 7 y 8. El problema es que con el nuevo Firefox 4.0, al abrirlo se posiciona siempre en la esquina superior izquierda del explorador, quedando incluso un trozo fuera, de modo que no es posible seleccionar algunos días (aparte de no verse completo). Esto se produce independientemente de dónde se coloquen los inputs asociados.
¿Alguna idea sobre cómo solucionarlo?
Vale, no he dicho nada. Culpa mía, por usar tablas. Si saco el input asociado de la tabla, funciona correctamente. Así que tendré que sustituir celdas por divs, y organizarlo de otra manera.
De todas formas, es curioso que con la tabla en el IE funciona correctamente, pero en el Firefox, no.
Hola Pepin. La diferencia está en la interpretación que hace cada navegador de determinadas propiedades de CSS, o quizás más bien la ausencia que tienen para soportarlas. Es posible que aplicando específicamente algún valor para la propiedad display se solucionase (por ejemplo table-cell).
Un saludo
Buenas,
Yo quisiera saber, si la incidencia de Julio del 31 de Marzo de 2009, esta resuelta, porque no consigo que los meses abril, julio, etc… cuadren bien los días del mes con los de la semana.
Se ha encontrado una solución al respecto??
Un saludo,
Adolfo
Buenas,
tengo una página con frames y entonces al aparecer el calendario no cabe y se ve parcialmente, no sé si hay posibilidad de que se abra en una ventana independiente en lugar de la misma página o ¿cómo puedo solucionarlo?
Gracias
Hola a tod@s,
He solucionado el problema que había con las fechas en los días 31 de todos los meses!!! un infierno… ya que se descuadraban todos los meses del año!
La solución es:
Aprox. en la línea 97 donde hay esto:
…
var Hoy_real = new Date();
…
añadir justo debajo la declaración de esta nueva variable.
var Hoy = new Date();
luego dentro de la función calendario()
comentar esa misma linea: (aprox. línea 312)
…
destino = id;
//var Hoy = new Date(); <————– Comentar esta línea!!
if(document.getElementById(id).className.indexOf('post') != -1) {
….
Con esto se soluciona el famoso tema de los días 31!
Espero que haya sido de ayuda para lo que aún no tenían respuesta sobre este error……
Saludos,
Excelente Calendario , fácil de implementar.
Una Observación: Para IE9 presenta un error en los Años muestra 101 hasta 111, en vez de 2001 hasta 2011.
Solución parchar en el archivo JS (acc_calendar.js) , getYear() por getFullYear().
Muchas Gracias.
Hola. Perdonarme que no os haya respondido antes. He estado algo liado y no me pude poner a ello.
En cuanto a la consulta de Nuria, la idea del calendario es que forme parte del DOM del documento que lo porta, con lo que se abrirá en el marco correspondiente. No está pensado para que abra ventana nueva, con lo que si esto es lo que necesitas, tendrás que buscar otra alternativa.
A Adolfo y a Janux, agradeceros que os hayáis pegado con el código y que hayáis planteado soluciones a los problemas que mencionáis, por un lado lo que venía arrastrando desde hace tiempo respecto a los 31 días de algunos meses, y por otro lo que está pasando con IE9 (seré sincero si te digo que hace tiempo que no tocaba nada en el código y no lo probé aun en esa versión).
En general, gracias a todos por vuestros comentarios y aportaciones.
Un saludo
Hola.
Antes de nada darte la enhorabuena por el calendario
En Internet Explorer 9 (y supongo que de ahí en adelante), la función getYear tiene el mismo comportamiento que en Firefox, Chrome, etc. por lo que en el calendario los años aparecen como 112, 113, etc.
En mi caso he solucionado el problema filtrando por versiones de IE anteriores a 9. Incluyo el código por si quieres actualizar el script.
var re = new RegExp(“msie ([0-9]{1,}[\.0-9]{0,})”);
var rv=-1;
if (re.exec(nav) != null) {
rv = parseFloat(RegExp.$1);
}
if((nav.indexOf(“msie”) != -1) && rv<9) {
comp = 0;
}
Saludos.
Jorge, gracias, tanto por avisar del problema como de aportar una solución. Me he tomado la libertad de incluirla en el script…
Un saludo
Pingback: Días disponibles con acc_calendar | Niquelao
Hola,
Antes que nada, no se mucho de javascript y en cuanto al calendario, éste es el calendario que estaba buscando, ya que los demás que he encontrado traen funciones para guardar citas, notas, etc, cosas que no me interesan y este esta sencillo y se adapata a lo que quiero.
Ahora bien, sería factible que el calendario se abriera en una nueva ventana a parte tipo ventana emergente para que ahí se mostrara el calendario y por consiguiente que el calendario se abriera automaticamente y no mediante el uso del link que pusiste llamado “calendario”? y pues obvio que regrese el valor de la fecha seleccionada a la ventana inmediata anterior.
Saludos y excelente codigo.
Saludos.
Hola Juan y gracias por tu comentario,
En principio, la idea con la que hice el calendario era la de hacerlo accesible, frente a otras alternativas que se pueden encontrar por internet. Entre las recomendaciones de accesibilidad que se deben seguir está el no provocar la apertura de ventanas nuevas. De ahí que no recomiende ese comportamiento.
Un saludo y gracias por los comentarios.