soy Kseso y esto EsCSS

Creación de tablas con movimiento de contenido entre celdas.
Caso de estudio: Tablero de Ajedrez

Nueva colaboración de Furoya en torno a javascript. En esta ocasión parte de la creación de una tabla convertida en tablero de ajedrez y va añadiendo funcionalidades, desde las fichas, a cambiar su posición y efectos asociados al movimiento.

Creación de tablas con movimiento de contenido entre celdas.
Caso de estudio: Tablero de Ajedrez

✎ 0
COLABORACIÓN AUTOR INVITADO
Creación de tablas con movimiento de contenido entre celdas. Caso de estudio: Tablero de Ajedrez

Como habrán visto en el título, vamos a hacer un tablero de ajedrez. Solamente el tablero interactivo. No hace jugadas, no las valida; lo más será eliminar las piezas muertas.

Es una excusa para probar métodos que crean tablas con bucles anidados y al mismo tiempo ir llenando selectivamente sus celdas con contenido. Y después encontrar dificultades al inventar un modo de arrastre para mover trebejos, que vamos a resolver de a una.

Ya conocemos varias formas de escribir elementos al vuelo en un documento HTML, hoy las repasamos y le agregamos alguna más.

En principio, podemos crear toda la tabla en algún lugar del body, pero vamos a repetir una chanchada previa, que es meter una etiqueta table vacía para tener un punto de referencia en el código fuente, y después la rellenamos.

Veamos antes seguir, el resultado final.

See the Pen Chessboard. With Javascript. by solipsistaCP (@solipsistacp) on CodePen.

Un detalle importante a mencionar antes de ver el escript es que las piezas están hechas con caracteres unicode. Si carecen de una fuente que las contenga, seguramente no las van a ver. Así que es buen momento para que se instalen alguna más completa (en la hoja de estilos pueden ver una buena lista de fuentes). Solamente estamos aprovechando las diseñadas como "blancas", y nuestro color se lo damos con estilos. Si prefieren, usan las que van del 265A al 265F; eso va en gustos.

Y no es que no se puedan hacer con CSS puro (Íconos CSS. Parte 2.) pero aquí estamos viendo el JS y no nos vamos a complicar con estos formatos.

<script type="text/javascript"> var escaques; //VARIABLE A USAR LUEGO var trebejos0 = ["♖","♘","♗","♕","♔","♗","♘","♖"] // ARRAY CON CARACTERES DE PIEZAS DE AJEDREZ var trebejos1 = "♙"; // CARACTER "PEÓN" DE AJEDREZ /* CREAMOS EL TABLERO */ function tablero() { /* REFERIMOS LA TABLA VACÍA EN UNA VARIABLE */ escaques = document.getElementById("tablero"); /* CREAMOS DENTRO DE LA TABLA LAS 8 FILAS */ for(f=0; f<8; f++) { /* REFERIMOS CADA FILA NUEVA INSERTADA, EN UNA VARIABLE */ var fila = escaques.insertRow(); /* CREAMOS EN CADA FILA 8 CELDAS */ for(c=0; c<8; c++){ /* REFERIMOS CADA CELDA INSERTADA, EN UNA VARIABLE */ var celda = fila.insertCell(); /* APROVECHAMOS LA VUELTA PARA LLENAR LAS 4 FILAS DE PIEZAS CON LOS CARACTERES*/ if(f==0) celda.innerHTML = "<span class=negras>"+trebejos0[c]+"</span>"; else if(f==1) celda.innerHTML = "<span class=negras>"+trebejos1+"</span>"; else if(f==6) celda.innerHTML = "<span class=blancas>"+trebejos1+"</span>"; else if(f==7) celda.innerHTML = "<span class=blancas>"+trebejos0[c]+"</span>"; } } } onload = tablero; </script>
  • Empezamos con una de las variables globales que contiene un array de caracteres. Son las piezas principales en su orden natural, y las vamos a usar luego para rellenar la primera y última filas (0 y 7) del tablero. La siguiente variable es solamente un caracter, el peón, y como la segunda y penúltima filas (1 y 6) llevan ocho iguales, no precisamos de ningún array : llegado el caso repetimos el mismo.
  • Dentro de la función, ya apuntamos a la tabla vacía para meterla en una variable.
  • Y empezamos a hacer bucles for() anidados para crear las ocho filas y en cada una las ocho celdas que forman los escaques que dan sentido al tablero.
  • Usamos el método insertRow() que sirve justamente para insertar filas. La referimos en una variable local para cada vuelta de bucle (es decir, que se pierde y reescribe en cada vuelta, no es global) y aprovechamos la referencia en esa misma vuelta de fila para llenarla con las ocho celdas usando insertCell() que —obviamente— es una función propia de javascript para insertar celdas. Cuando se terminan las ocho vueltas de ese bucle de celdas, entonces pasa a la segunda vuelta de su "bucle padre" para filas, y va haciendo el mismo trabajo hasta llegar a su octava.
  • En las vueltas para celdas vemos una serie de condicionales "if; else if; else". Usan la variable f dentro del for anterior para "saber" en qué fila están, y si es la primera (0) llama al ítem de array que tiene las piezas para esa fila (var c) y se corresponda con con su mismo orden (a celda cero, caracter cero que es una torre, a celda uno, caracter uno que es un caballo, ...), entonces lo escribe junto con su span usando el viejo método innerHTML. Una vez terminada esa fila, pasa a la segunda, donde repite la operación, pero esta vez la primera condición no se cumple, porque —repito— estamos en la segunda, y f ya es 1, entonces el condicional ignora la primera instrucción y pasa a la segunda, donde escribe en cada celda el mismo caracter peón con su correspondiente span. A partir de aquí, hay cuatro filas que no cumplen con ninguna condición, así que escribe sólo celdas sin caracteres. En la séptima ya vuelve a escribir peones; y en la fila 7 (la octava y última) repite la serie de caracteres igual que hizo con la primera. La diferencia en estas dos últimas, es que el span ya tiene otra clase, porque las primeras son color negro, y las últimas color blanco.
  • Seguimos aprovechando el evento onload, como en ejemplos anteriores, para ejecutar la función cuando el código fuente ya está cargado. (Más abajo vamos a empezar a trabajar con addEventListener().)

Cuando usamos

if();
else if();
else;

estamos poniendo condicionales exclusivos. Si escribimos

if();
if();
else;

se va a comprobar la primera condición; se cumpla o no va a probar con la segunda, y si no se cumple la última recién aplica el else.

Pero un else if() no sigue probando si ya se cumplió la anterior, así que cualquier condición que devuelva true excluye a las otras. Solamente puede aplicarse una.

Recordemos que las condiciones son simples operadores booleanos, si se cumple la que tenga entre paréntesis, javascript le devuelve true y se aplica lo que tenga en la misma línea (o entre las llaves, si tiene más de una línea).

Con la condición de los bucles for(una variable; una condición; una operación) ocurre lo mismo; cuando el segundo valor es false, el loop se detiene.

Hay muchos casos en que javascript devuelve un booleano false; si una variable está declarada, pero no se le asigna contenido o valor, es falso; si pedimos un elemento de array que no existe, es falso; si llamamos a un número y es cero, es falso.

Saber esto nos va a facilitar las cosas al momento de poner límites o rechazar operaciones.

Ahora vamos un poco más lejos.
Vamos a inventar un modo de mover las piezas.
ajedrez con js

Intercambiando contenidos

El mecanismo más extendido es el de arrastre, pero si lo pensamos un poco nos damos cuenta de que tiene sus desventajas. Se puede justificar cuando debemos mover contenido arbitrariamente a cualquier parte de un texto o un campo en el documento. Pero en un tablero de ajedrez no hay muchas opciones : va en un escaque sí o sí, y siempre en la misma posición, no en cualquier punto que elijamos de la celda. Así que un método más práctico es clickear en la pieza a mover y luego clickear la celda de destino, de esa forma el escript ya sabe qué espan debe cortar para insertarlo después en la segunda celda, y eventualmente eliminar el contenido que tuviere, como ocurre cuando se captura una pieza.

A esto le podemos agregar unos adornos, como para hacer más simpático el movimiento. Como que al elegir una pieza y mientras vamos al escaque destino el trebejo se vea semitransparente; o que al pasar sobre las piezas el puntero se transforme en una mano abierta, y una vez elegido, que se vea una mano cerrada...

Este último efecto parece el más sencillo, y no lo es. Tiene complicaciones operativas que casi no lo justifican. Como que la mano solamente debe aparecer sobre las piezas y no sobre celdas vacías, hasta que se elija una y entonces la mano cerrada debe mostrarse sobre cualquier celda y span; y hasta entre el cellspacing que tiene la tabla, para evitar ese molesto parpadeo del cursor cuando se pasa de una a otra.

Pero como somos una comunidad que no se asusta tan fácil, vamos a resolver esto de la mejor manera que podamos.

Aquí el pen.

See the Pen Chessboard. With Javascript movement. by solipsistaCP (@solipsistacp) on CodePen.

Nota: en Codepen no funcionan los cursores drag&drop, para ver el efecto es mejor probarlo en local.
Ya encontré una manera de "hackearlo" y ahora se ven

Y el detalle del escript comentado.

<script type="text/javascript"> var escaques, padre, hijo, moviendo; //VARIABLES A USAR LUEGO var trebejos0 = ["♖","♘","♗","♕","♔","♗","♘","♖"]; // ARRAY CON CARACTERES DE PIEZAS DE AJEDREZ var trebejos1 = "♙"; // CARACTER "PEÓN" DE AJEDREZ /* CREAMOS EL TABLERO Y SUS EVENTOS */ function tablero() { /* REFERIMOS LA TABLA VACÍA EN UNA VARIABLE */ escaques = document.getElementById("tablero"); /* CREAMOS DENTRO DE LA TABLA LAS 8 FILAS */ for(e=0; e<8; e++) { /* REFERIMOS CADA FILA NUEVA INSERTADA, EN UNA VARIABLE */ var fila = escaques.insertRow(); /* CREAMOS EN CADA FILA 8 CELDAS */ for(c=0; c<8; c++){ /* REFERIMOS CADA CELDA INSERTADA, EN UNA VARIABLE */ var celda = fila.insertCell(); /* APROVECHAMOS LA VUELTA PARA LLENAR LAS 4 FILAS DE PIEZAS CON LOS CARACTERES*/ if(e==0) celda.innerHTML = "<span class=negras>"+trebejos0[c]+"</span>"; else if(e==1) celda.innerHTML = "<span class=negras>"+trebejos1+"</span>"; else if(e==6) celda.innerHTML = "<span class=blancas>"+trebejos1+"</span>"; else if(e==7) celda.innerHTML = "<span class=blancas>"+trebejos0[c]+"</span>"; } } /* REFERIMOS LA LISTA DE CELDAS YA CREADAS */ var movible = document.querySelectorAll("td"); /* LA RECORREMOS COMPLETAMENTE */ for(m=0; m<movible.length; m++) { /* AGREGAMOS EL ATRIBUTO DEL EVENTO PARA DISPARAR UNA FUNCIÓN, CON SU VALOR */ movible[m].setAttribute("onclick", "juega(this)", false); } } /* FUNCION PARA MOVER LAS PIEZAS */ function juega(T) { /* PONEMOS LA LISTA DE ELEMENTOS table Y table span EN VARIABLE */ elementos = document.querySelectorAll("table, table span"); /* SI moviendo ES false Y EL CLICK SE HIZO EN UNA CELDA CON CONTENIDO ... */ if(!moviendo && T.firstElementChild){ padre = T; // REFERIMOS LA CELDA CLICKADA EN VARIABLE GLOBAL hijo = T.innerHTML; // REFERIMOS SU CONTENIDO (span Y caracter) /* AGREGAMOS UNA CLASE DE NUEVO PUNTERO A LA TABLA Y SUS span */ for(i=0; elementos[i]; i++) elementos[i].classList.add("mano"); /* SEMITRANSPARENTAMOS EL CONTENIDO DE CELDA CLICKADA */ T.querySelector("span").style.opacity = ".4"; /* HACEMOS true LA VARIABLE GLOBAL PARA CONFIRMAR QUE HAY UNA PIEZA ELEGIDA EN MOVIMIENTO */ moviendo = true; } /* ... SI moviendo NO ES false */ else if(moviendo){ /* VACIAMOS LA ANTERIOR CELDA CLICKADA */ padre.innerHTML = ""; /* LLENAMOS LA ACTUAL CELDA CLICKADA CON EL CONTENIDO GUARDADO DE LA ANTERIOR */ T.innerHTML = hijo; /* REMOVEMOS LA CLASE PARA LOS PUNTEROS DE TODAS LAS CELDAS Y LA TABLA */ for(i=0; elementos[i]; i++) elementos[i].classList.remove("mano"); /* VOLVEMOS LA VARIABLE A false PORQUE YA NO HAY UNA PIEZA EN MOVIMIENTO */ moviendo = false; } } onload = tablero; //EJECUTA LA FUNCIÓN DE INICIO AL CARGARSE EL DOCUMENTO </script>

Vamos con la explicación, que tiene cierta dificultad y debemos estudiarla un poco para entenderla.

  • A la lista de variables globales agregamos una para "recordar" la celda padre del span elegido, otra para mantener copia del HTML del hijo y otra para saber si hicimos el primer click, o vamos por el segundo (con una pieza ya en movimiento).
  • El tablero se crea de la misma forma, porque para agregar el código que le falta vamos a modificar la tabla ya hecha en vez de meternos en los loops.
  • Para eso creamos una variable movible que hace referencia a todas las celdas de la tabla que pueden tener o tendrán contenido movible, y les agrega el atributo onclick con una llamada a la función que hace los movimientos llevando como argumento a la misma celda.
  • Esta nueva función juega(T) recibe el argumento en la variable T que escribimos entre los paréntesis, y que a partir de su ejecución se "convierte" en la celda clickeada.
  • Ya dentro de la función, creamos una variable para meter la tabla y todos sus span. Más abajo vemos para qué sirve.
  • El condicional nos va a ejecutar líneas dependiendo de si estamos haciendo el primer click para elegir la pieza a mover, o si ya estamos moviendo una y elegimos la celda de destino. Resulta que la variable moviendo no tiene valor, así que por omisión es "false". En la primera condición preguntamos si "no hay 'moviendo' ", y como javascript para moviendo le devuelve "false", la condición se cumple [Nota: el signo de admiración al comienzo es una negación]. En la segunda se pregunta por T.firstElementChild, es decir, por "un primer elemento hijo" en la celda clickada, y también se cumple, porque se supone que picamos en una celda que tiene un span con la pieza a mover. Si se cumplen la primera y la segunda condición, se ejecuta la instrucción que hay dentro de ese if; si, por ejemplo, picamos en una celda vacía por error, la segunda condición no se cumple, y se pasa al siguiente else if().
  • Pero quedémonos en el primero. Allí metemos en la variable global padre a la celda clickada para futura referencia. Y en la variable hijo al código de su contenido (el span y su caracter).
  • Después recorremos todas las tablas (que hay solamente una) y todos sus span. Esto puede parecer extraño, pero tiene que ver con el efecto del cursor. Una vez elegida la pieza, el puntero tiene que cambiar a una mano cerrada en todas la tabla (celdas y espacio entre ellas) además de cada span que tenían una clase para la mano abierta. Lo que hace el bucle es agregar a todos una clase nueva al final (que tendrá prioridad sobre la anterior en las reglas repetidas) y que asigna el nuevo cursor. En la tabla quedará como class="mano" y en los span con —por ejemplo— piezas blancas class="blancas mano".
  • En la siguiente línea ya semitransparenta el span dentro de la celda clickada.
  • Y, lo más importante, asigna el valor "true" a la variable moviendo, porque ahora sí tenemos una pieza en movimiento.
  • Ya estamos para elegir la casilla de destino para la pieza. Así que hacemos el segundo click, y disparamos nuevamente la función juega(T).
  • Tomamos otra vez la colección de tablas y contenidos para meterlos en una variable (mmmm... ahora pienso que podría haberla hecho también global, :-P ) y pasamos al condicional. Al pedido sobre la variable moviendo la respuesta será "true", porque así la tenemos asignada del click anterior. Ya esa condición no se cumple porque dejó de ser "false", entonces pasamos al siguiente if else, que en el caso anterior había sido descartado.
  • Su única condición es (por una cuestión de seguridad, podría ser simplemente un else, pero vamos a confirmar que hay una pieza en movimiento) que moviendo sea "true". Y lo es, la cambiamos en el click anterior, así que lo primero que hace es borrar el contenido de la celda donde hicimos aquél primer click (porque le sacamos la pieza) y en la nueva celda clickada ponemos la copia de ese contenido que teníamos guardada en la variable hijo (si ya había otra pieza en la celda, será reemplazada).
  • Luego recorremos de nuevo todos los elementos de la tabla, pero esta vez para remover esa clase con "la mano cerrada" (ya pusimos la pieza en su lugar de destino, no se necesita más) y entonces queda como estaba todo al principio, solamente las piezas con "la mano abierta".
  • Por supuesto, volvemos moviendo a "false", porque ya se terminó esa jugada y debe quedar lista para la siguiente. Como ya se le asignó un valor, no podemos aprovechar que por omisión era "false", y le tenemos que asignar el nuevo explicitamente.
Como de costumbre, las explicaciones son más largas que el código.
Y esto no es todo. Aún le vamos a dar otra vuelta de tuerca al asunto.

Arrastrando cuerpos astrales

Arrastrando figuras ajedrez con js

Ya tenemos no sólo el cambio de casilla, sino un efecto de puntero y marca semitransparente de la pieza elegida. La cereza del postre será que al mover el puntero hacia la nueva casilla se vea un "fantasmita" de la pieza debajo del cursor con la mano cerrada, que desaparecerá al depositarse en la celda de destino.

El contenido que muestra al trebejo en cuestión ya lo tenemos en una variable, lo único que hay que hacer es meterlo en un div suelto por ahí que siga las coordenadas del puntero en tiempo real.

Algo así

See the Pen Chessboard. With Javascript movement and phantom. by solipsistaCP (@solipsistacp) on CodePen.

El código sigue siendo el mismo, con los agregados pertinentes.

En el detalle nos vamos a ocupar principalmente de las líneas nuevas, pero en el comentado repito todo, porque es una ayuda.

<script type="text/javascript"> var escaques, padre, hijo, moviendo, copia; //VARIABLES A USAR LUEGO var trebejos0 = ["♖","♘","♗","♕","♔","♗","♘","♖"]; // ARRAY CON CARACTERES DE PIEZAS DE AJEDREZ var trebejos1 = "♙"; // CARACTER "PEÓN" DE AJEDREZ /* CREAMOS EL TABLERO Y SUS EVENTOS */ function tablero() { /* PONEMOS EN UNA VARIABLE UN NUEVO div PARA EL DOCUMENTO */ var nuevoDiv = document.createElement("div"); /* LE AGREGAMOS UN id Y SU VALOR */ nuevoDiv.setAttribute("id","fantasma"); /* LO AGREGAMOS EN EL BODY AL FINAL DEL DOM */ document.body.appendChild(nuevoDiv); /* AGREGAMOS UN "ESCUCHADOR DE EVENTOS" AL body PARA SEGUIR AL PUNTERO Y EJECUTAR UNA FUNCIÓN QUE LEA LAS COORDENADAS*/ document.body.addEventListener('mousemove', function(event){ sigue(event); false }); /* PONEMOS EN LA VARIABLE copia EL NUEVO div CREADO EN EL body */ copia = document.getElementById("fantasma"); /* REFERIMOS LA TABLA VACÍA EN UNA VARIABLE */ escaques = document.getElementById("tablero"); /* CREAMOS DENTRO DE LA TABLA LAS 8 FILAS */ for(f=0; f<8; f++) { /* REFERIMOS CADA FILA NUEVA INSERTADA, EN UNA VARIABLE */ var fila = escaques.insertRow(); /* CREAMOS EN CADA FILA 8 CELDAS */ for(c=0; c<8; c++){ /* REFERIMOS CADA CELDA INSERTADA, EN UNA VARIABLE */ var celda = fila.insertCell(); /* APROVECHAMOS LA VUELTA PARA LLENAR LAS 4 FILAS DE PIEZAS CON LOS CARACTERES*/ if(f==0) celda.innerHTML = "<span class=negras>"+trebejos0[c]+"</span>"; else if(f==1) celda.innerHTML = "<span class=negras>"+trebejos1+"</span>"; else if(f==6) celda.innerHTML = "<span class=blancas>"+trebejos1+"</span>"; else if(f==7) celda.innerHTML = "<span class=blancas>"+trebejos0[c]+"</span>"; } } /* REFERIMOS LA LISTA DE CELDAS YA CREADAS */ var movible = document.querySelectorAll("td"); /* LA RECORREMOS COMPLETAMENTE */ for(m=0; m<movible.length; m++) { /* AGREGAMOS EL ATRIBUTO DEL EVENTO PARA DISPARAR LA FUNCIÓN, CON SU VALOR */ movible[m].setAttribute("onclick", "juega(this)", false); } } /* FUNCION PARA MOVER LAS PIEZAS */ function juega(T) { /* PONEMOS LA LISTA DE ELEMENTOS table Y table span EN VARIABLE */ elementos = document.querySelectorAll("table, table span"); /* SI moviendo ES false Y EL CLICK SE HIZO EN UNA CELDA CON CONTENIDO ... */ if(!moviendo && T.firstElementChild){ padre = T; // REFERIMOS LA CELDA CLICKADA EN VARIABLE GLOBAL hijo = T.innerHTML; // REFERIMOS SU CONTENIDO (span Y caracter) /* AGREGAMOS UNA CLASE DE NUEVO PUNTERO A LA TABLA Y SUS span */ for(i=0; elementos[i]; i++) elementos[i].classList.add("mano"); /* SEMITRANSPARENTAMOS EL CONTENIDO DE CELDA CLICKADA */ T.querySelector("span").style.opacity = ".4"; /* LLENAMOS EL div AGREGADO CON EL MISMO CONTENIDO DE LA CELDA CLICKADA */ copia.innerHTML = T.innerHTML; /* HACEMOS VISIBLE EL div */ copia.style.display = "block"; /* SEMITRANSPARENTAMOS EL CONTENIDO DE CELDA CLICKADA */ T.querySelector("span").style.opacity = ".4"; /* HACEMOS true LA VARIABLE GLOBAL PARA CONFIRMAR QUE HAY UNA PIEZA ELEGIDA EN MOVIMIENTO */ moviendo = true; } /* ... SI moviendo ES true */ else if(moviendo){ /* VACIAMOS LA ANTERIOR CELDA CLICKADA */ padre.innerHTML = ""; /* LLENAMOS LA ACTUAL CELDA CLICKADA CON EL CONTENIDO GUARDADO DE LA ANTERIOR */ T.innerHTML = hijo; /* REMOVEMOS LA CLASE PARA LOS PUNTEROS DE TODAS LAS CELDAS Y LA TABLA */ for(i=0; elementos[i]; i++) elementos[i].classList.remove("mano"); /* OCULTAMOS EL div "FANTASMA" QUE SIGUE AL PUNTERO */ copia.style.display = "none"; /* VOLVEMOS LA VARIABLE A false PORQUE YA NO HAY UNA PIEZA EN MOVIMIENTO */ moviendo = false; } } /* FUNCIÓN QUE MUESTRA EL TREBEJO "FANTASMA" QUE SIGUE AL PUNTERO */ function sigue(e) { /* CAPTURA COORDENADAS HORIZONTAL Y VERTICAL DEL PUNTERO */ var horiz= (e.x) ? e.x : e.clientX; var vert= (e.y) ? e.y : e.clientY; //document.title = (horiz - 16)+" "+(vert - 16); /* PASA LAS COORDENADAS (CON UNA CORRECCIÓN) A LA POSICIÓN DEL div */ copia.style.top = (vert - 16)+"px"; copia.style.left = (horiz - 16)+"px"; } onload = tablero; //EJECUTA LA FUNCIÓN DE INICIO AL CARGARSE EL DOCUMENTO </script>
  • Ya estamos usando una variable global más. En copia vamos a apuntar a un div que seguirá al puntero conteniendo una copia del span con la pieza elegida.
  • Ese nuevo div ya no va a estar en el código fuente (como la tabla vacía) sino que lo vamos a insertar al vuelo con document.createElement("div"). Allí usamos otra variable previa y local para la función tablero() que solamente hace referencia a este objeto que se crea "en el limbo" porque aún no existe en el DOM. De esta forma podemos agregarle atributos, antes de colgarlo en el body con appendChild().
  • Otra cosa que agregamos es un evento "mousemove", esta vez usando el ya mencionado addEventListener() que ante un movimiento del ratón captura el evento y se lo pasa a una nueva función sigue(e)que veremos más abajo. Poner "escuchadores de eventos" es hoy lo más recomendado, yo trato de no usarlos en los ejemplos porque, como ven, son más complejos e incompatibles en algunos casos; pero es bueno que los conozcan y estudien para usarlos por su cuenta.
  • Ahora, sí, ya hay un nuevo div al final del documento, y lo referimos para futuros usos en la var global copia.
  • Ya en la función juega(T) al hacer el primer click llenamos el fantasma de la pieza elegida con el mismo contenido de la celda, y lo hacemos visible.
  • En el segundo click, lo ocultamos, porque ya el "verdadero" estará visible y ubicado dentro de su nueva celda.
  • La nueva función para leer x:y del puntero trabaja así : el argumento que quedó entre paréntesis es el evento de "mover el ratón". Para saber sus coordenadas hay por ahora dos métodos. Hasta que se estandarice de una vez en la vida real, vamos a usar una condición que discrimine cuál reconoce el navegador con el que vemos la página; y metemos las coordenadas horizontal y vertical en sendas variables. Una vez que sabemos cuántos pixeles arriba y a la izquierda está el puntero, solamente tenemos que pasarle al div esos valores como top y left con alguna corrección para que se vea más cerca del medio del cursor (en le ejemplo lo desplacé 16 pixeles).

Los formatos del CSS asociado son muy importantes para el funcionamiento del tablero, pero no los detallo porque supongo que se entienden. Quedará para más adelante un cajoncito que guarde las piezas comidas y algún modo práctico de coronar peones.

Autoría

Furoya: Autor del artículo

Artículo original de Furoya.
La intención del autor con sus colaboraciones no es que los artículos sirvan para hacer un copy&paste de códigos sino que comprendas y aprendas la lógica y el cómo trabaja javaScript.
Y a partir de lo expuesto experimentes tú.
El autor del post y el editor del blog te animamos a que plantees tus dudas o reflexiones y que compartas tus realizaciones en base a lo expuesto en los comentarios. Recuerda que puedes incluir pens (ejemplos en Codepen.io) en ellos.