Ir directamente al contenido de esta página
Aunque no es estrictamente necesario, recomiendo leer antes «Cómo mejorar la usabilidad de una tabla de datos por medio de JavaScript no obstrusivo», dado que algunos de los problemas a la hora de tratar con los elementos de una tabla son comunes.
La inspiración viene de la mano de las cosas cotidianas, y si no pensemos en la magdalena de Proust. Hace poco, en el autobús, me encontré con que un hombre a mi lado comprobaba los datos de una tabla compuesta por decenas de celdas, con encabezados tanto para las filas como para las columnas, algo como esto:
Al | Ca | Sc | Ti | V | Cr | Mn | Fe | Co | Ni | Cu | … | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
001 | 0,25 | 1,22 | 1,05 | 0,72 | 1,23 | 0,09 | 0,34 | 1,23 | 1,03 | 1,12 | 0,01 | … |
002 | 1,02 | 1,99 | 0,26 | 1,14 | 1,02 | 1,91 | 0,96 | 0,72 | 1,17 | 0,96 | 0,12 | … |
003 | 1,71 | 0,61 | 1,12 | 1,09 | 1,17 | 0,99 | 0,54 | 1,61 | 0,36 | 0,22 | 1,59 | … |
004 | 0,09 | 0,03 | 1,98 | 0,25 | 1,10 | 0,17 | 1,50 | 1,78 | 1,02 | 0,77 | 0,90 | … |
005 | 1,11 | 1,09 | 1,11 | 0,64 | 0,26 | 1,58 | 1,26 | 0,32 | 1,70 | 1,33 | 0,71 | … |
… | … | … | … | … | … | … | … | … | … | … | … | … |
Leerla, por supuesto, era un dolor de cabeza asegurado, por el esfuerzo necesario para cerciorarse de que se está leyendo la celda que corresponde a los dos encabezados que están relacionados. Como podría ocurrir que alguna vez me encontrase con una tabla semejante en una página, me puse a pensar en cómo facilitar su lectura.
El siguiente script modifica el estilo de las celdas de una tabla para identificar los encabezados relacionados con un td
concreto, e identificar visualmente su relación:
01 var posicion_celda = 0;
02 var celda;
03 var fila;
04 var tabla;
05 var celdas_fila;
06 var filas_totales;
07 function escuchar(){
08 var celdas = document.getElementsByTagName('td');
09 for (var i=1;i<celdas.length;i++){
10 celdas[i].addEventListener('mouseover', resaltar_celdas, false);
11 celdas[i].addEventListener('mouseout', restaurar_celdas, false);
12 }
13 }
14 function resaltar_celdas(){
15 celda = this;
16 celda.className += ' celda_destacada';
17 fila = this.parentNode;
18 if (fila.parentNode=='[object HTMLTableElement]'){
19 tabla = fila.parentNode;
20 } else {
21 tabla = fila.parentNode.parentNode;
22 }
23 celdas_fila = fila.getElementsByTagName('td');
24 for (var i=0;i<celdas_fila.length;i++){
25 if(celdas_fila[i]==celda){
26 break;
27 } else {
28 posicion_celda++;
29 celdas_fila[i].className += ' fila_resaltada';
30 }
31 }
32 filas_totales = tabla.getElementsByTagName('tr');
33 for (var k=1;k<filas_totales.length;k++){
34 if(filas_totales[k]==fila){
35 break;
36 } else {
37 filas_totales[k].getElementsByTagName('td')[posicion_celda].className += ' columna_resaltada';
38 }
39 }
40 fila.getElementsByTagName('th')[0].className += ' encabezado_horizontal';
41 tabla.getElementsByTagName('th')[posicion_celda].className += ' encabezado_vertical';
42 }
43 function restaurar_celdas(){
44 celda.className -= ' fila_resaltada';
45 fila.getElementsByTagName('th')[0].className -= ' encabezado_horizontal';
46 tabla.getElementsByTagName('th')[posicion_celda].className -= ' encabezado_vertical';
47 var celdas_totales = tabla.getElementsByTagName('td');
48 for (var m=0;m<celdas_totales.length;m++){
49 celdas_totales[m].className -= ' fila_resaltada columna_resaltada';
50 }
51 posicion_celda = 0;
52 }
53 if (document.addEventListener){ window.addEventListener('load',escuchar,false); }
Tras declarar las variable que voy a necesitar, asigno escuchas a cada una de las celdas presentes en el documento para controlar los dos eventos de ratón que necesito controlar (líneas 10 y 11)1.
Cuando el usuario sitúa el puntero sobre una celda, se lanza la función resaltar_celdas
. En ella primero asigno a esa misma celda el estilo que voy a emplear para resaltarla, por medio de la sintaxis celda.className +=
, asegurándome así de que no elimino otras posibles declaraciones que puedan estar aplicándosele.
En las líneas 7 a 22 asigno a dos variables una referencia a la fila a la que pertenece la celda, y otra a la tabla —detectando antes si se ha empleado o no tbody
—, que necesitaré un poco más tarde para saber la posición de la fila en cuestión. También incremento el valor de posicion_celda, una variable que luego me va a permitir elegir la celda que corresponde a la misma columna para las filas anteriores.
Entre la línea 23 y la 31, compruebo en el bucle cuál de las celdas de la lista de nodos que es fila es la celda actual; cuando la localizo, rompo el bucle, pero hasta entonces asigno a esas celdas un estilo diferente.
Seguidamente hago algo similar en las líneas 32 a 39: un bucle recorre las filas de la tabla hasta dar con la que tengo asignada a fila, y para cada fila anterior cambio el estilo de la celda que se encuentra en la misma posición que la resaltada.
Por último, en las líneas 40 y 41 asigno estilos también a los encabezados correspondientes, tanto horizontal como vertical.
La función restaurar_celdas
es mucho más sencilla. Simplemente elimina los estilos adicionales, primero para la celda consultada (línea 44), después para los encabezados (líneas 45 y 46), y después para cualquier celda (líneas 47 a 50). Para terminar, restaura el valor de la variable posicion_celda, y el ciclo puede volver a empezar.
Ver un ejemplo de su funcionamiento.
Una vez que se ha vinculado el script a la página que se desee, el aspecto de las celdas se puede especificar añadiendo unas pocas reglas a la hoja de estilo, como los siguientes selectores:
.celda_destacada
: El estilo de la celda que se está consultando..encabezado_vertical
: El estilo para el encabezado de la columna correspondiente..encabezado_horizontal
: El estilo para el encabezado de la fila correspondiente..columna_resaltada
: El estilo para las celdas de la columna correspondiente..fila_resaltada
: El estilo para las celdas de la fila correspondiente.He comprobado que este script funciona correctamente —sobre Windows— en:
focus
y blur
, no se pueden aplicar a td
, según la especificación sólo acepta los eventos comunes (inglés). Es este caso, lo único que puedo hacer en favor de la accesibilidad es hacer que el script no sea obstrusivo.