Saltar al contenido principal
Codigo Heroe
Tarea anterior
Introducción a los eventos20/21
A la lista de tareas
  1. 1. Eventos del usuario
  2. 2. Añadir un manejador de eventos
  3. 3. Sintaxis de los manejadores
  4. 4. Acciones predeterminadas
  5. 5. Funciones como argumentos
  6. 6. Eliminar clases con classList.remove()
  7. 7. Eventos de teclado
  8. 8. Identificar una tecla
  9. 9. Cerrar una ventana con ESC
  10. 10. Seleccionar los elementos de una galería
  11. 11. Añadir manejadores en un ciclo
  12. 12. Cambiar el src de una imagen
  13. 13. Depurar un manejador
  14. 14. Ámbito local
  15. 15. Ámbito global
  16. 16. Cambiar variables externas
  17. 17. Funciones dentro de funciones
  18. 18. Cierres
  19. 19. Un cierre en cada llamada
  20. 20. Usar cierres en los manejadores
  21. 21. Completar la galería
Siguiente tarea
  • Matriz de skills
  • Cursos
  • Registro
  • Iniciar sesión

Loading…
En unos segundos, estará listo.

  • Teoría
  • Teoría

Usar cierres en los manejadores

Ahora que conocemos los ámbitos y los cierres, volvamos a la galería. ¿Qué ocurrió en nuestro código? ¿Por qué no funciona como esperamos?

for (var i = 0; i < thumbnails.length; i++) {
  thumbnails[i].addEventListener('click', function () {
    fullPhoto.src = photos[i];
  });
}

Los manejadores utilizan el contador i, pero no se ejecutan al crearlos: esperan al clic. Cuando hacemos clic por primera vez, el ciclo ya terminó y i vale 5. El ciclo no crea un ámbito de función para la variable declarada con var. En este código, i está en el ámbito global y todos los manejadores acceden a esa misma variable. Por eso todos utilizan 5. No tenemos una miniatura ni un elemento de photos con ese índice, así que la imagen no aparece.

¿Cómo lo resolvemos? ¡Con cierres!

Crearemos una función que reciba una miniatura y el elemento correspondiente de photos. Dentro añadiremos el manejador. Así, cada manejador tendrá acceso a los parámetros de la llamada en la que fue creado.

Cada llamada tendrá sus propias variables thumbnail y photo. Los manejadores dejarán de depender del mismo contador global.

Mejoremos el programa paso a paso para que funcione correctamente.

  • index.html
  • style.css
  • script.js
HTML
<!DOCTYPE html> <html lang="es"> <head> <meta charset="utf-8"> <title>Galería de Cupcake</title> <link href="gallery/setting.css" rel="stylesheet"> <link href="style.css" rel="stylesheet"> </head> <body class="pattern"> <section class="gallery"> <h1>Galería de Cupcake</h1> <p class="gallery__photo-full"> <img class="full-photo" src="gallery/laptop-large.jpg" width="550" height="367" alt="Fotografía ampliada de Cupcake"> </p> <p class="gallery__photo-previews"> <button class="gallery__photo-preview" type="button"> <img src="gallery/laptop.jpg" alt="Miniatura de Cupcake con una computadora portátil"> </button> <button class="gallery__photo-preview" type="button"> <img src="gallery/microphone.jpg" alt="Miniatura de Cupcake con un micrófono"> </button> <button class="gallery__photo-preview" type="button"> <img src="gallery/keyboard.jpg" alt="Miniatura de Cupcake con un teclado"> </button> <button class="gallery__photo-preview" type="button"> <img src="gallery/signboard.jpg" alt="Miniatura de Cupcake con un letrero"> </button> <button class="gallery__photo-preview" type="button"> <img src="gallery/tree.jpg" alt="Miniatura de Cupcake junto a un árbol"> </button> </p> </section> <script src="script.js"></script> </body> </html>
CSS
.gallery { display: flex; flex-direction: column; align-items: center; } .gallery__photo-full { margin-bottom: 12px; } .gallery__photo-full img { display: block; } .gallery__photo-previews { display: flex; list-style-type: none; margin: 0; width: 550px; padding: 0; justify-content: space-between; } .gallery__photo-preview { padding: 0; border: 0; border-radius: 0; background: none; } .gallery__photo-preview:hover, .gallery__photo-preview:focus { opacity: 0.7; } .gallery__photo-preview img { display: block; object-fit: cover; width: 100px; height: 100px; } .gallery__photo-preview--active img { outline: 5px solid red; outline-offset: -5px; } .pattern { background: url("gallery/leaves-pattern.png") 0 0 repeat; }
JavaScript
var photos = [ 'gallery/laptop-large.jpg', 'gallery/microphone-large.jpg', 'gallery/keyboard-large.jpg', 'gallery/signboard-large.jpg', 'gallery/tree-large.jpg' ]; var thumbnails = document.querySelectorAll('.gallery__photo-preview'); var fullPhoto = document.querySelector('.full-photo'); for (var i = 0; i < thumbnails.length; i++) { thumbnails[i].addEventListener('click', function () { fullPhoto.src = photos[i]; }); }

El código ha cambiado, haz clic en "Actualizar" o activa la ejecución automática.

Ha ido a otra página

Haga clic dentro del mininavegador para poner el foco en esta ventana.

100%
Consola
ObjetivosRealizado
0
    1. Antes del ciclo, declara la función addThumbnailClickHandler con dos parámetros: thumbnail y photo.
    2. Dentro de la función, añade un manejador de clic a thumbnail.
    3. Dentro de ese manejador, muestra thumbnail en la consola y, en la línea siguiente, muestra photo.
    4. Sustituye todo el código del cuerpo del ciclo por una llamada a addThumbnailClickHandler con los argumentos thumbnails[i] y photos[i].
    5. Haz clic en dos miniaturas distintas.
    Codigo Heroe

    © 2023-2026, codigoheroe.com