Cuando generas botones de forma dinámica en el DOM, agregarles eventos de clic requiere una estrategia diferente a la habitual. Aquí se aborda cómo iterar sobre elementos compartidos por una misma clase CSS, capturar el evento de clic para identificar qué botón fue presionado y construir una secuencia de ataques almacenada en un arreglo, sentando las bases para una mecánica de juego por rondas.
¿Cómo seleccionar múltiples elementos con querySelectorAll?
Para trabajar con varios botones que comparten características, se utiliza el método document.querySelectorAll [01:15]. A diferencia de getElementById, que busca un elemento único, querySelectorAll devuelve un NodeList —una lista de nodos— con todos los elementos que coincidan con el selector indicado.
- Se agrega una clase CSS común a cada botón generado, por ejemplo
b-ataque [00:52].
- Se declara una variable
botones como arreglo vacío y luego se le asigna el resultado de document.querySelectorAll('.b-ataque') [01:08].
- El resultado es un NodeList que puede iterarse como un arreglo.
Un detalle importante: los IDs no deben repetirse en distintos elementos HTML porque es mala práctica [01:38]. Si necesitas agrupar elementos que se repiten, lo correcto es usar clases.
¿Por qué es necesario llamar la función después de declararla?
Se crea una función llamada secuenciaAtaque que recorre el arreglo de botones con forEach [04:25]. Por cada botón, se agrega un addEventListener de tipo click. Sin embargo, un error frecuente es declarar la función pero nunca invocarla [05:48].
- La función debe llamarse en el momento adecuado del flujo, en este caso, después de que se selecciona la mascota del enemigo y los botones ya existen en el DOM [06:10].
- Sin esa invocación, el código simplemente no se ejecuta.
¿Qué información contiene el evento de clic?
Al capturar el evento con el parámetro e, se accede al objeto del evento [05:08]. Dentro de él, la propiedad e.target apunta al elemento exacto que recibió el clic [06:48]. A su vez, e.target.textContent devuelve el contenido de texto de ese botón, por ejemplo el emoji de fuego, agua o tierra [07:20].
Esta cadena de acceso —evento → target → textContent— es fundamental para identificar qué ataque seleccionó el jugador sin necesidad de IDs individuales.
¿Cómo construir la secuencia de ataques del jugador?
Se declara una variable ataqueJugador como arreglo vacío [08:22]. Cada vez que el jugador hace clic en un botón, se ejecuta una validación con if / else if / else:
- Si
e.target.textContent es igual al emoji de fuego, se hace ataqueJugador.push('fuego') [09:00].
- Si es agua, se hace push de
'agua' [10:08].
- En cualquier otro caso, se agrega
'tierra' [10:38].
Además del push, se imprime el arreglo con console.log para visualizar la secuencia en tiempo real y se cambia el color de fondo del botón con boton.style.background para indicar visualmente que ya fue seleccionado [09:30].
¿Qué errores comunes aparecen al refactorizar el código?
Durante la implementación surgen dos errores representativos que vale la pena entender:
- Variable ya declarada: si
ataqueJugador se declara con let en dos lugares distintos, JavaScript lanza un error de redeclaración [11:28]. La solución es conservar una sola declaración en el scope correcto.
- Push is not a function: ocurre cuando otra parte del código sobreescribe el arreglo con un valor que no es un arreglo [12:02]. En este caso, funciones antiguas reasignaban
ataqueJugador a un string, eliminando el método push. Al remover esas funciones obsoletas y las líneas que agregaban eventos de clic duplicados, el problema desaparece [12:30].
Estos errores refuerzan la importancia de limpiar código legacy cada vez que se cambia la lógica de una aplicación.
Con la secuencia del jugador almacenada correctamente, el siguiente paso es generar la secuencia de ataques del enemigo y comparar ambas en un loop de cinco rondas para determinar al ganador. ¿Ya te animaste a probar variaciones en la cantidad de ataques o en las reglas de victoria? Comparte tu enfoque en los comentarios.