A煤n no tienes acceso a esta clase

Crea una cuenta y contin煤a viendo este curso

Comparte el resultado

24/28
Recursos

Aportes 56

Preguntas 7

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesi贸n.

Vale, para agregar el fondo gris lo que hice fue crear un wrapper que encerrara a la imagen y que se adaptara al tama帽o de la misma con un m铆nimo de 100px, y este wrapper tiene el fondo gris, as铆 cuando se inserta sale con fondo gris:

...

imagen.width = "320";
imagen.dataset.src = `https://randomfox.ca/images/${random()}.jpg`

const imageWrapper = document.createElement("div");
imageWrapper.className = "bg-gray-300";
imageWrapper.style.minHeight = "100px";
imageWrapper.style.display = "inline-block";

imageWrapper.appendChild(imagen);
container.appendChild(imageWrapper);
...

Para eliminar las imagenes, le puse id a los botones:

<button class="p-3" id="add">Agregar Imagen</button>
<button class="p-3" id="clean">Limpiar</button>

En JavaScript los selecciono y les pongo sus eventos, para eliminarlos simplemente recorro todos los nodos hijos de mountNode, los recorro y los elimino:

const cleanImages = () => {

    console.log(mountNode.childNodes);

    [...mountNode.childNodes].forEach(child => {
        child.remove();
    }) 

}

addButton.addEventListener("click", addImage)
cleanButton.addEventListener("click", cleanImages)

Y para imprimir los logs, en el HTML agregue variables y una funci贸n super globales para tener acceso desde index.js y desde lazy.js:

<script>
    let appendedImages = 0;
    let loadedImages = 0;

    const printLog = () => {
    console.log(`鈿 Se han agregado ${appendedImages} im谩genes`);
    console.log(`馃煟 Se han cargado ${loadedImages} im谩genes`);
    console.log("---------------------------------------");
    }
</script>
<script type="module" src="%PUBLIC_URL%/_dist_/index.js"></script>

Entonces, en la funci贸n createImageNode antes de retornar el container, aumento uno a las imagenes que se han agregado y llamo a la funci贸n:

...
imageWrapper.appendChild(imagen);
container.appendChild(imageWrapper);

appendedImages++;
printLog();

return container;
...

Y dentro de lazy.js en loadImage antes de dejar de observar hago lo mismo, pero aqu铆 incremento las im谩genes cargadas:

const loadImage = entry => {

    const container = entry.target;
    const imagen = container.firstChild;
    const imagen = container.querySelector("img");
    const url = imagen.dataset.src;
    imagen.src = url;

    loadedImages++;
    printLog();

    observer.unobserve(container)

}

Y listo 馃槃
.
El c贸digo completo est谩 aqu铆 por si quieren darle un vistazo:
.
Resoluci贸n del reto

espero lograr un efecto parecido para mi lista de pokemons.
https://codepen.io/rogergcc/full/NeEYeN
queria lograr un loading a cada pokemon porque el texto carga rapido pero la imagen demora en cargar mas.
Vi que lo hacen con imagenes estaticas pero quiero lograrlo en un api json.

Les comparto mi proyecto 馃榿 El curso ha estado genial!!! sitio: https://findafox.netlify.app/
repo: https://github.com/jmilo13/findFox/

Como adicional al primer reto, seria esencial agregar un icono de cargando al recuadro gris, esto le dar谩 una mejor percepci贸n al usuario de lo que esta sucediendo con la imagen. En la siguiente url podr谩n encontrar un ejemplo de c贸mo crear este icono con solo html y css https://devcode.la/tutoriales/crear-un-preloader-con-css3/


Les dejo el enlace: Lazy loading

Si se pudo!! En mi caso, us茅 webpack como builder 馃槃 Si le quieren dar un ojo se los dejo aqu铆

Index.js

lazy

El uso de clases para el pintado de los estatus de las im谩genes me ha funcionado, aqu铆 les comparto:

  • Creamos la clase, la inicializamos y la exportamos (lazy.js).

  • La clase cuenta con m茅todos p煤blicos y privados para su encapsulamiento y los m茅todos 鈥済etAppended o getLoaded鈥 pueden o no ser p煤blicos dependiendo de la necesidad.

  • El m茅todo 鈥渃lear鈥 en mi caso aplique una limpieza en consola.

class ImageLoaded {
    #appendImages = 0;
    #loadedImages = 0;

    #getAppended(){
        return this.#appendImages;
    }

    #getLoaded(){
        return this.#loadedImages;
    }

    addAppend(){
        this.#appendImages += 1;
    }
    addLoad(){
        this.#loadedImages += 1;
    }

    clear(){
        console.clear();
        this.#appendImages = 0;
        this.#loadedImages = 0;
    }

    printLog() {
        console.log(`
        鈿 Se han agregado ${this.#getAppended()} im谩genes
        馃煟 Se han cargado ${this.#getLoaded()} im谩genes
        ---------------------------------------`);
    }
}

export const imageStatus = new ImageLoaded();

  • Su implementaci贸n en el archivo lazy.js, seria la siguiente:
//imageStatus
const accion = ({ target }) => {
    const imagen = (target.firstChild).firstChild;
    imagen.src = imagen.dataset.src;
    imageStatus.addLoad();
    imageStatus.printLog();
    observer.unobserve(target)
}
  • Su implementaci贸n en el archivo index.js (requiere importar):
import { registerImage, imageStatus } from './lazy';

//...

const addButton = document.querySelector('.btn-add');
const cleanButton = document.querySelector('.btn-clean');

const addImage = () => {
    const newImage = createImageNode();
    container.appendChild(newImage)
    registerImage(newImage)
    imageStatus.addAppend();
    imageStatus.printLog()
};
const cleanImage = () =>{
    const allImages = [...container.querySelectorAll('div')];
    allImages.forEach(img => img.remove())
    imageStatus.clear();
}

addButton.addEventListener('click', addImage);
cleanButton.addEventListener('click', cleanImage);

Fondo gris a las im谩genes s贸lo se lo agregu茅 con una clase de tailwind:

img.className = "mx-auto my-16 bg-gray-200";

Para el bot贸n de borrar lo agregu茅 desde js:

const cleanImages = () => {
	const gallery = document.getElementById("gallery");
	const nodes = gallery.childNodes;
	if (!nodes.length > 0) return;

	[...nodes].forEach((node) => {
		gallery.removeChild(node);
	});

	resetImages();
};

const clean = document.createElement("button");
clean.className =
	"mx-auto my-4 block bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded transition duration-300 ease-in-out";
clean.textContent = "Borrar im谩genes";
clean.type = "reset";
clean.addEventListener("click", cleanImages);
const gallery = document.createElement("div");
gallery.id = "gallery";
container.append(button, clean, gallery);

Y para el conteo de im谩genes:

let totalImages = 0;
let loadedImages = 0;

const isIntersecting = (entry) => entry.isIntersecting;

const observer = new IntersectionObserver((entries) => {
	entries.filter(isIntersecting).forEach((entry) => {
		const imgNode = entry.target;
		imgNode.src = imgNode.dataset.src;
		imgNode.onload = () => {
			loadedImages++;
			logState();
		}
		observer.unobserve(entry.target);
	});
});

export const registerImage = (image) => {
	observer.observe(image);
	totalImages++;
	logState();
};

export const resetImages = () => {
	totalImages = 0;
	loadedImages = 0;
	logState();
};

function logState() {
	console.group("Lazy loading");
  console.log(`鈿笍 Total Im谩genes: ${totalImages}`);
  console.log(`馃煟 Im谩genes cargadas: ${loadedImages}`);
	console.log(`馃煛 Im谩genes por cargar: ${totalImages - loadedImages}`);
	console.groupEnd();
}

html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta
      name="description"
      content="Web site created using create-snowpack-app"
    />
    <!--
      Snowpack will replace %PUBLIC_URL% with the value you have for `baseUrl` in `snowpack.config.js`.
      Make sure to update it with your GitHub Page URL. https://<your-username>.github.io/<your-repo-name>

      More about config options:
      - https://www.snowpack.dev/reference/configuration#buildoptions.baseurl
    -->
    <link
      rel="stylesheet"
      type="text/css"
      href="%PUBLIC_URL%/_dist_/index.css"
    />
    <title>Random fox</title>
  </head>
  <body>
    <!--
      This HTML file is a template.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.

      Start modyfing from here.
    -->
    <div class="py-10 max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
      <div class="text-center">
        <p
          class="text-base leading-6 text-indigo-600 font-semibold tracking-wide uppercase"
        >
          Manipulando el Dom
        </p>
        <h3
          class="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10"
        >
          Random Fox
        </h3>
        <p class="m-4 max-w-2xl text-xl leading-7 text-gray-500 mx-auto">
          Manipulacion del DOM con API de <span> <a href="https://randomfox.ca/" target="_blank">RandomFox</a></span>
        </p>

        <button id="addButton" class="p-3">Agregar Imagen</button>
        <button id="removeButton" class="p-3">Remover Imagenes</button>
       
        <div id="images">
          
        </div>

        

      </div>
    </div>

    <!-- Add more scripts here -->
    <script type="module" src="%PUBLIC_URL%/_dist_/index.js"></script>
  </body>
</html>

index.js

/**
 * This file is just a silly example to show everything working in the browser.
 * When you're ready to start on your site, clear the file. Happy hacking!
 **/

import { registerImage } from "./lazy";

const URL = "https://randomfox.ca/images";

const maximum=122;
const minimum= 1;

//crea un numero aleatorio para traer las imagenes
const random = () => Math.floor(Math.random() * (maximum - minimum)) + minimum

// reporte en consola de cuantos argumentos han traido y estan cargados
const reportImgs = {
    imgLoaded: 0,
    totalImg: 0
}

const stopContentLoader = (event) => {
    const img = event.target;
    // img.parentElement.lastChild.remove();
    img.style.width = '320px';
    img.style.height= '320px';
    
    reportImgs.imgLoaded++;
    
    // debugger;
    showReportImg();
}

const showReportImg = () => {
    console.log('----------------------------------------')
    console.log(`%c鈿猅otal Imgs: ${reportImgs.totalImg}`, 'color: white; font-size: 0.8rem');
    console.log(`%c馃煟Total Cargadas: ${reportImgs.imgLoaded}`, 'color: hotpink; font-size: 0.8rem');
    console.log('----------------------------------------')
}

const allElementsDeleted = () => {
    console.log(`鈿 Todas las imagenes fueron eliminadas`);
}

const createImageNode = () => {
    const container = document.createElement('div');
    container.className = 'flex flex-col items-center p-4 mx-auto';

    const img = document.createElement('img');
    img.className = 'mx-auto rounded bg-gray-300';
    img.width = "320";
    img.style.minHeight = '300'
    img.dataset.src = `${URL}/${random()}.jpg`; // TODO

    img.onload = stopContentLoader; //onload llama una funcion

    container.appendChild(img);

    return container;
};

const nuevaImagen = createImageNode();

const addImage = () => {
    const newImage = createImageNode();
    mountNode.append(newImage);
    registerImage(newImage);
    
    reportImgs.totalImg++;
    showReportImg();
}

const removeAllImg = () =>{
    mountNode.innerHTML = "";
    reportImgs.imgLoaded = 0;
    reportImgs.totalImg = 0;
    allElementsDeleted()
}


//captura la etiqueta img del html
const mountNode = document.getElementById('images')

//captura el button del html
const addButton = document.querySelector('#addButton');
addButton.className = 'text-white px-3 py-2 rounded-lg bg-indigo-600 focus:outline-none';

const removeButton = document.querySelector('#removeButton')
removeButton.className ='rounded-lg mt-5 px-3 py-2 text-indigo-600 border border-indigo-600 focus:outline-none';

addButton.addEventListener('click', addImage);
removeButton.addEventListener('click', removeAllImg);


lazy.js

const isIntersecting = (entry) => entry.isIntersecting; //true (dentro de la pantalla)

const loadImage = (entry) => {
    const container = entry.target; //regresa un container (DIV)
    const imagen = container.firstChild;
    const url = imagen.dataset.src
    //cargar la imagen.
    imagen.src=url

    // console.log(entry);

    //desregistrar el evento
    observer.unobserve(container);
};

const observer = new IntersectionObserver((entries)=>{
    entries.filter(isIntersecting).forEach(loadImage);
});

export const registerImage = (imagen) => {
    //intersectationObservador -> observer(imagen)
    observer.observe(imagen)
}

Bien, esto fue lo que yo hice 馃槃
index.html :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta
      name="description"
      content="Web site created using create-snowpack-app"
    />
    <!--
      Snowpack will replace %PUBLIC_URL% with the value you have for `baseUrl` in `snowpack.config.js`.
      Make sure to update it with your GitHub Page URL. https://<your-username>.github.io/<your-repo-name>

      More about config options:
      - https://www.snowpack.dev/reference/configuration#buildoptions.baseurl
    -->
    <link
      rel="stylesheet"
      type="text/css"
      href="%PUBLIC_URL%/_dist_/index.css"
    />
    <title>Snowpack & Tailwind App</title>
  </head>
  <body>
    <!--
      This HTML file is a template.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.

      Start modyfing from here.
    -->
    <div class="py-10 max-w-screen-xl mx-auto px-4 sm:px-6 lg:px-8">
      <div class="text-center">
        <p
          class="text-base leading-6 text-indigo-600 font-semibold tracking-wide uppercase"
        >
          Platzi
        </p>
        <h3
          class="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10"
        >
          Fox API
        </h3>
        <p class="mt-4 max-w-2xl text-xl leading-7 text-gray-500 mx-auto">
          Coleccionando im谩genes de Zorros
        </p>

        <button class="button" id="buttonFox">Click me to see a new fox!</button>
        <button id="deleteFoxes" class="buttonClear">Clean images</button>
        <div id="app"></div>

      </div>
    </div>

    <!-- Add more scripts here -->
    <script type="module" src="%PUBLIC_URL%/_dist_/index.js"></script>
  </body>
</html>

index.css :

@import 'tailwindcss/dist/base.css';
@import 'tailwindcss/dist/components.css';
@import 'tailwindcss/dist/utilities.css';

.button,
.buttonClear{
  color: white;
  padding: 5px;
  border-radius: 5px;
}

.button{
  background-color: orange;
}

.buttonClear{
  background-color: rgb(255, 81, 0);
}

index.js :

import {registerImage} from './lazy';

const maximum = 122;
const minimum = 0;
const random = () => Math.floor(Math.random() * (maximum - minimum) + minimum);

const createImageNode = () => {
  const container = document.createElement('div');
  container.className = "p-4 bg-gray-200 mt-5";

  const image = document.createElement('img');
  image.className = 'mx-auto';
  image.width = '320';
  image.dataset.src = `https://randomfox.ca/images/${random()}.jpg`;
  container.append(image);

  return container;
}

const mountNode = document.getElementById('app');
const buttonFox = document.getElementById('buttonFox');
const buttonClear = document.getElementById('deleteFoxes');

var imagenesCargadas = 0;

const addImage = () => {
  const newImage = createImageNode();
  mountNode.append(newImage);
  registerImage(newImage);
  imagenesCargadas += 1
  console.log(`Se han cargado ${imagenesCargadas} fotos`)
}

buttonFox.addEventListener('click' , addImage);

buttonClear.addEventListener('click' , () => {
  let containerWithImage = document.querySelectorAll('#app .p-4'); //!Obtiene nodeList
  containerWithImage = Array.from(containerWithImage); //!Convierte a Array
  containerWithImage.forEach(element => {
    element.remove();
  });
})

//*Las l铆neas de abajo ya muestran 1 imagen por defecto
//const nuevaImagen = createImageNode();
//mountNode.append(nuevaImagen);

lazy.js :

const isIntersecting = entry => {
  return entry.isIntersecting //* true si est谩 dentro de la pantalla del navegador
}

var imagenesMostradas = 0;

const loadImage = (entry) => {
  const container = entry.target; //* div
  const image  = container.firstChild;
  const url = image.dataset.src;
  //*carga imagen
  image.src = url;
  observer.unobserve(container);
  imagenesMostradas += 1;
  console.log(`Se han mostrado ${imagenesMostradas} fotos a la vista del navegador`)
}

const observer = new IntersectionObserver((allEntries) => {
  allEntries
    .filter(isIntersecting)
    .forEach(loadImage)
})

export const registerImage = image => {
  observer.observe(image)
}

Aqu铆 les dejo mi taller: https://christbm.github.io/workshop2/

Ah铆 va mi Lazy Loading. Tuve que ver el repositorio del profesor para el tema de la imagen gris, pero entend铆 el funcionamiento.

https://marinrmarco.github.io/lazyloading/

Mi soluci贸n, para eliminar las imagenes hice lo siguiente:

const cleanImages = () => {
    
    const nodeElementsImages = mountNode.children
    const listaElements = [...nodeElementsImages]
    listaElements.forEach((element) => element.remove())
    
}

//Agregamos el evento
cleanButton.addEventListener('click', cleanImages)

Para agregar el fondo gris :

const imagen = h('img.mx-auto', {
        width: 320,
        height : 300,
        style: {
            background:'grey'
        },
        "data-src" : `https://randomfox.ca/images/${random()}.jpg`,
        
    })

Les comparto mi soluci贸n al Reto 馃帀 Aqu铆 el repo y aqu铆 el resultado 馃榿

Asi pueden eliminar todos los elementos 馃槃

// removeImageButton
const removeButton = document.getElementById('btn-clean');

const clearImage = () => {
    mountNode.replaceChildren();
};

removeButton.addEventListener("click", clearImage);

Encontr茅 este c贸digo para eliminar todos los child nodes, me pareci贸 sencillo y eficaz. 馃榿
https://www.javascripttutorial.net/dom/manipulating/remove-all-child-nodes/

const deleteImgs = () => {
  console.log(mountNode.childNodes);
  while(mountNode.firstChild) {
    mountNode.removeChild(mountNode.firstChild);
  }
}

Adoro estas clases pr谩cticas que te dejan algo en Github.
https://nosoyeseoscar.github.io/workshop-2-lazy/

Mi implementaci贸n

Genial este curso 馃槂 se aprende mucho

Mi resultado 馃槃 todo ha sido genial mil gracias
Repositorio
Sitio

Mont茅 mi proyecto en CodePen:

https://codepen.io/Londrack/full/jOaqwvJ

Este fue mi resultado:

P谩gina
Repositorio

Este es mi resultado:
He agregado contadores y textos random cuando genero una nueva targetita de zorro (锟o付锟*))

P谩gina aqu铆 馃憟
Repo aqui 馃憟


Les dejo el link del repositorio.
En este enlace pueden ver la p谩gina.

Esta es mi githubpage:
https://jsegundo.github.io/JS-intersection-observer/
Y este es el repo, todo el JS tiene comentarios que explican detalladamente(a mi parecer) todas las funciones, espero que a alguien le sirva.
https://github.com/JSegundo/JS-intersection-observer

Vamos por ese reto

Acepto toda critica. REPOSITORIO

Tambi茅n dejo por aqu铆 SITIO EN VIVO

Mas los screenshots :

Este es mi proyecto, me ayude bastante de @retaxmaster, Fox Lazy Loading, repo en GitHub

Para los que miraron el repo del profe buscando como hacer lo del recuadro gris y se encontraron una ruta bastante extra帽a como: data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIwIiBoZWlnaHQ9IjMyMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiLz4=, les dejo un recurso que explica en que consiste esto, espero le sirva a alguien 馃槉:
recurso

No es mucho, pero es trabajo honesto 馃槃
https://lazy-lodn.netlify.app/
C贸digo del proyecto

馃槃 aqui mi genrador de imagenes de los zorros.

https://brayangc1.github.io/kuramaGenerator/

MAIN.JS

import { lazyLoading, imgCargadas } from "./lazyLoad.js";

const section = document.getElementById('seccion');
const boton = document.querySelector('#agregar');
const removeButton = document.getElementById('quitar');
const max = 122;
const min = 1;
export let imgCreadas = 0;

export const consoleImages = (creadas,cargadas) => {
    console.log(`馃 Total imagenes: ${creadas}`)
    console.log(`馃憖 Imagenes cargadas: ${cargadas}`)
}

const random = () => Math.floor(Math.random() * (max - min)) + min;

const crearImagen = () =>{
    const figure = document.createElement('figure');
    const imagen = document.createElement('img');
    // imagen.src = `https://randomfox.ca/images/${random()}.jpg`;
    imagen.dataset.src = `https://randomfox.ca/images/${random()}.jpg`;
    imgCreadas++;

    figure.appendChild(imagen);
    return figure;
}

const borrarFigure = () =>{
    const selectDelete = document.querySelectorAll('figure');
    
    const arrayDelete = [...selectDelete];
    return arrayDelete;
} 

const borrarImagen = () =>{
    const selectDelete = document.querySelectorAll('img');
    
    const arrayDelete = [...selectDelete];
    return arrayDelete;
} 

const agregarImagen = () => {
    const newImage = crearImagen();
    section.appendChild(newImage);
    lazyLoading(newImage);

    consoleImages(imgCreadas,imgCargadas);
}

const quitarImagen = () =>{
    const deleteImage = borrarImagen();
    const deleteFigure = borrarFigure();

    deleteImage.forEach(hijo=> hijo.remove());
    deleteFigure.forEach(hijo => hijo.remove());    
}

boton.addEventListener('click', agregarImagen);

removeButton.addEventListener('click', quitarImagen);


LAZYLOAD.JS

import { imgCreadas, consoleImages } from "./main.js";

const isIntersecting = entry => entry.isIntersecting;
export let imgCargadas = 0;

const tarea = (entry) =>{    
    const container = entry.target;
    const imagen = container.firstChild;
    const url = imagen.dataset.src;
    imagen.src= url;

    imgCargadas++;
    consoleImages(imgCreadas,imgCargadas);
    observer.unobserve(container);

    imagen.onload = () =>{
        container.parentElement.replaceChild(imagen,container);
        imagen.classList.add('margin');
    }
}

const observer = new IntersectionObserver((entries)=>{
    entries.filter(isIntersecting).forEach(tarea);
})

export const lazyLoading = (figure) =>{
    observer.observe(figure);
}

tambi茅n el codigo se encuentra aqui: https://github.com/brayangc1/kuramaGenerator

Termin茅 el proyecto y utilic茅 un closure para resolver el tema del informe y aprovech茅 para agregar una funci贸n que elimine los datos de la consola cuando se limpien los lobos del DOM.
En vivo aqu铆

function contarImg() {
    let imgAdd = 0
    let imgPaint = 0
    
    return {
        imgAgreg: function(){
            imgAdd++
            console.log(`鈿 Se han agregado ${imgAdd} im谩genes`);
            console.log(`馃煟 Se han cargado ${imgPaint} im谩genes`);
            console.log("---------------------------------------");
        },
        imgLoad: function(){
            imgPaint++
            console.log(`鈿 Se han agregado ${imgAdd} im谩genes`);
            console.log(`馃煟 Se han cargado ${imgPaint} im谩genes`);
            console.log("---------------------------------------");
        },
        imgDelete: function(){
            imgPaint = 0
            imgAdd = 0
            console.clear()
        }
    }
}

export const contar = contarImg()

Estoy disfrutando este curso demasiado. Eres uno de los mejores profesores en la plataforma.
Les dejo mi resultado con algunos ajustes como deshabilitar el bot贸n de Limpiar cuando no hay im谩genes en la lista. Tambi茅n, si las imagenes son eliminadas, el reporte vuelve a 0.

El despliegue lo hice en Netlify porque ah铆 manejo todos mis proyectos actualmente.

Para publicarlo ah铆 solo es necesario conectar la cuenta de github y en el deploy colocar 鈥渘pm run build鈥 y elegir la carpeta 鈥渂uild/鈥 como la carpeta de donde se levantar谩 la web una vez hecho el build.

https://youthful-jang-e738c2.netlify.app/

Con un poco de complicaciones pero pude terminarlo!. 馃榿
Muchas gracias a todos los compa帽eros que compartieron sus aportes y al profesor sin duda alguna 馃槉
Reto completado
Repo

Wenas [email protected];

Por aqu铆 dejo mi soluci贸n del segundo proyecto. Wen domingo.

Entonces tenemos 3 retos:

  • Dar la percepci贸n de carga con el recuadro gris.
  • Eliminar todo el contenido y limpiar la pantalla por medio de un bot贸n
  • Por medio de la consola indicar cuantas han cargado y cuantas faltan por cargar

隆Vamo a darle! 馃槂

Les comparto mi resultado me demore un poco con este reto me toco apoyarme en comentarios de los compa帽eros y repo del profe pero gracias a Dios lo pude terminar les comparto el deploy Aqui y el repo

D铆as despu茅s se me ocurri贸 solucionar el tema del log de la cuenta con clousures, es un poco m谩s organizada a mi parecer. Les comparto mi soluci贸n 馃榾

Ya luego solo importamos he invocamos como

count.imageRendered();
count.imageLoaded();

Hola, les dejo mi resultado.
repo: https://github.com/sebaser99/lazy
github pages: https://sebaser99.github.io/lazy/

Agradezco el feedback

Para el lazy-loader solo agregu茅 estilos al div

// index.js
  ...
  div.style.width = "200px"
  div.style.minHeight = "100px"
  div.style.height = "auto"
  ...
};

Para eliminar toda la lista de imgs use un add event y un foreach

// index.js
const cleanImgButton = document.getElementById("cleanButton");

cleanImgButton.addEventListener("click", () => {
  [...imgContainer.childNodes].forEach((item) =>
    imgContainer.removeChild(item)
  );
});

Para el console fueee un poquito mas complicado para mi

//index.js
import { registerImage, changesRegister } from "./lazy";
changesRegister(imgContainer);
  • Use el Mutation Observer para leer las mutaciones en el container, y una sola funcion que leyera la data y la muestre en consola
//lazy.js
/** Esto es lo que hara el mutation observer */
const mutationObserver = new MutationObserver(() => updateConsole());

/** Convierte el objeto obtenido en un mutation observer  */
export const changesRegister = (container) => {
  mutationObserver.observe(container, {
    attributes: false,
    childList: true,
    subtree: false,
  });
};

/** Funcion que lee el numero de imagenes y el numero de imagenes sin src, y luego lo imprime */
const updateConsole = () => {
  const creadas = imgContainer.childElementCount;
  const cargadas = [...imgContainer.children].filter((item) =>
    item.children[0].hasAttribute("src")
  ).length;
  console.log(`------------------------------`);
  console.log(`馃 Total imagenes: ${creadas}`);
  console.log(`馃憖 Imagenes cargadas: ${cargadas}`);
};

agrego el updateConsole tambien en cada vez que sea cargada la imagen en el intersectionObserver

// lazy.js
const loadImage = (entry) => {
  ...
  updateConsole();
  ...
}

MI soluci贸n.

// lazy.js
import { registerImage } from "./lazy";
// random images
const min=1, max=122;
const random=()=> Math.floor(Math.random()*(max-min))+min;
// images HTML -> JS
const createImageNode=()=>{
    const container = document.createElement('div');
    container.className='p-4';
    const image= document.createElement('img');
    image.className='mx-auto rounded-md bg-gray-300';
    image.width='320';
        image.dataset.src=`https://randomfox.ca/images/${random()}.jpg`
    container.appendChild(image);
    return container;
};

const mountnode=document.getElementById('images');
//eventListerner DOM -> addImages
const addButton=document.getElementById('btnaddimg');
const addImage=()=>{
    const newImage=createImageNode();
    mountnode.append(newImage);
    registerImage(newImage);
};
addButton.addEventListener('click',addImage);

//clean Images
const clean=document.getElementById('btnclnimg');
clean.addEventListener('click',()=>{
    mountnode.innerHTML="";
});
 
// lazy.js
let totalImage=0, loadedImage=0;

const isIntersecting=(entry)=>{
    return entry.isIntersecting; // true (dentro de la pantalla)    
};

const loadImage=(entry)=>{
    const container=entry.target; //container DIV
    const image=container.firstChild;
    image.src=image.dataset.src;
    image.onload=()=>{
        loadedImage++;
        logstate();
    }
    //desregister la imagen (unlisten)
    observer.unobserve(container);
};

const observer= new IntersectionObserver((entries)=>{
    entries.filter(isIntersecting).forEach(loadImage);
});

export const registerImage=(image)=>{
    observer.observe(image);
    totalImage++;
    logstate();
};

function logstate(){
    console.log(`Total Images: ${totalImage}`);
    console.log(`Loaded Images: ${loadedImage}`);
} 

Aqui esta mi solucion,para el fondo gris lo unico que hago es darle un background color grey a la imagen y un min height asi

const createImageNode = () => {
  const container = document.createElement('div')
  container.className = 'p-4'

  const img = document.createElement('img')
  const imageUrl = `https://randomfox.ca/images/${randomNumber()}.jpg`
  img.dataset.src = imageUrl
  img.className = 'mx-auto bg-gray-300'
  img.style.minHeight = "300px"
  img.width = '320'
  container.appendChild(img)

  return container
}

Para borrar las imagenes lo unico que se tiene que hacer es un :

innerHTML = ''

cuando le das click a un boton al nodo de las imagenes, asi

const imagesNode = document.querySelector('#images')
const clearBtn = document.querySelector('#clearImages')

const clearImages = () =>{
  imagesNode.innerHTML = ""
}
clearBtn.addEventListener('click',clearImages)

y para hacer los logs, en el observer agrege un log cada que llamara al cb y obtengo todas las imagenes de la pagina y las loggeo como agregadas y loggeo las cargadas con un contador que avanza cada que se carga una imagen


const isIntersecting = (entry) => {
  return entry.isIntersecting
}
let loadedImagesCounter = 0
const action = (entry) => {
  const container = entry.target
  const img = container.firstChild
  const url = img.dataset.src
  img.src = url
  loadedImagesCounter++
  observer.unobserve(container)
}

const observer = new IntersectionObserver((entries) => {
  const unloadedImagesCounter = document.querySelectorAll('img').length
  entries.filter(isIntersecting).forEach(action)
  console.log(`鈿 Se han agregado ${unloadedImagesCounter} im谩genes`);
  console.log(`馃煟 Se han cargado ${loadedImagesCounter} im谩genes`);
  console.log("---------------------------------------");
})

export const registerImage = (image) => {
  observer.observe(image)
}

Terminado 馃槃

Repo
Live Demo

Mi solucion para el tracker de imagenes cargadas:

Lo primero crear dos variables en el lazy.js, para ir incrementandolas en las funciones correspondientes:

let totalImages = 0
let totalImagesLoaded = 0

export const registerImage = (imagen) => {
    totalImages += 1;
    console.log(`Total imagenes : ${totalImages} \nTotal Imagenes Cargadas : ${totalImagesLoaded}`)
    //intersectactionObserver
    observer.observe(imagen);
}
const loadImage = (entry) =>{
    totalImagesLoaded += 1;
    console.log(`Total imagenes : ${totalImages} \nTotal Imagenes Cargadas : ${totalImagesLoaded}`)
    const container = entry.target
    const imagen = container.querySelector('img')
    const url = imagen.dataset.src;
    // imagen.backgroun = 'grey';
    imagen.src = url
    
    //desregistra la imagen
    observer.unobserve(container)
}

Realice el proyecto como un generador de covers de libros aleatorio empleando la API Open Library.
Emplee un archivo js adicional llamado contador para mantener el reporte de los cambios en las im谩genes.
De esta forma el resultado final de mi soluci贸n es:

index.js

import {registrarImagen} from './lazy'

const URL = 'https://covers.openlibrary.org/b/id/'
const TAMANO_Y_FORMATO = '-L.jpg'

const MAXIMO = 10610627
const MINIMO = 1
const random = () => Math.floor(Math.random() * (MAXIMO - MINIMO)) + MINIMO

const convertirAStringLen8 = () => {
    let stringNumero = random().toString()
    switch (stringNumero.length) {
        case 1: return `0000000${stringNumero}`
        case 2: return `000000${stringNumero}`
        case 3: return `00000${stringNumero}`
        case 4: return `0000${stringNumero}`
        case 5: return `000${stringNumero}`
        case 6: return `00${stringNumero}`
        case 7: return `0${stringNumero}`
        case 8: return `${stringNumero}`
    }
}

const crearNodoImagen = () => {
    const imagen = document.createElement('img')
    imagen.className = 'mx-auto shadow-xl'
    imagen.dataset.src = `${URL}00${convertirAStringLen8()}${TAMANO_Y_FORMATO}`

    const contenedorImagen = document.createElement('div')
    contenedorImagen.className = 'flex align-items mx-auto w-80 h-96 p-4 border-4 border-blue-600 bg-blue-50 rounded-lg hover:border-blue-300'
    contenedorImagen.appendChild(imagen)

    imagenesAgregadas += 1
    logEstadoImagenes()

    return contenedorImagen
}

const nodoMontaje = document.getElementById('images')
nodoMontaje.className = 'flex flex-wrap'
const botonAgregar = document.getElementById('agregar')
const botonClear = document.getElementById('clear')

const agregarImagen = () => {
    const nuevaImagen = crearNodoImagen()
    nodoMontaje.append(nuevaImagen)
    registrarImagen(nuevaImagen)
}

const limpiarImagenes = () => {
    [...nodoMontaje.childNodes].forEach(childNode => {
        childNode.remove()
    })
    imagenesAgregadas = 0
    imagenesCargadas = 0
    logEstadoImagenes()
}

botonAgregar.addEventListener('click', agregarImagen)
botonClear.addEventListener('click', limpiarImagenes)

lazy.js

const estaIntersectando = entrada => {
    return entrada.isIntersecting
}

const cargarImagen = entrada => {
    const contenedorImagen = entrada.target
    const imagen = contenedorImagen.firstChild
    const URL = imagen.dataset.src
    imagen.src = URL
    imagenesCargadas += 1
    logEstadoImagenes()
    observador.unobserve(contenedorImagen)
}

const observador = new IntersectionObserver(entradas => {
    entradas.filter(estaIntersectando).forEach(cargarImagen)
})

export const registrarImagen = imagen => {
    observador.observe(imagen)
}

contador.js

let imagenesAgregadas = 0
let imagenesCargadas = 0

const logEstadoImagenes = () => {
    console.log(`Imagenes agregadas = ${imagenesAgregadas}`)
    console.log(`Imagenes cargadas = ${imagenesCargadas}`)
}

Hola:

Comparto mi proyecto con los puntos del reto:

https://robmvsk.github.io/workshop-2-lazy-loading/index.html

Saludos 馃槂

Hola todos!!

Esta muy bueno el curso!

Les comparto mi solucion en codepen.
Cualquier feedback es bienvenido.

codepen

Para el reporte en mi index tengo esta funcion que exporto:

export function imprimirReporte (total, loaded) {
    console.log(`馃憤Total de imagenes: ${total}`);
    console.log(`鉁匢m谩genes cargadas: ${loaded}`);
}```

y al registrar la imagen aumento totalImages++ y antes de termina de desobservar el container aumento loadedImages++

El curso ha resultado genial, cada d铆a aprendo mas en Platzi.

Mi soluci贸n
Index.js

import { getLoadedImg, registerImage } from "./lazy"

let totalImg = 0

const mini = 1
const maxi = 122
const randomImg = () => Math.floor(Math.random() * (maxi - mini)) + mini

export const report = () => {
    console.log(`馃憤Total images: ${totalImg}`);
    console.log(`鉁匢mages loaded: ${getLoadedImg()}`);
}

const createImg = () => {
    const container = document.createElement('div');
    container.className = "p-4"
    const img = document.createElement('img');
    img.className = "mx-auto grayBackground"
    img.width = "320"
    img.dataset.src = `https://randomfox.ca/images/${randomImg()}.jpg`
    container.appendChild(img)
    return container
}

const main = document.getElementById("images")
const addBtn = document.getElementById('add')
const delBtn = document.getElementById('del')

const addImage = () => {
    const newImg = createImg()
    main.append(newImg)
    registerImage(newImg)
    totalImg++;
    report()
}

const delImage = () => {
    let count = main.childElementCount;
    for (let i = 0; i < count; i++) {
        main.lastChild.remove()
    }
}

addBtn.addEventListener("click", addImage)
delBtn.addEventListener("click", delImage)

lazy.js

import { report } from "./index"

let loadedImg = 0;

const isIntersecting = (entry) => {
    return entry.isIntersecting
}

const loadImg = (entry) => {
    const container = entry.target
    const img = container.firstChild
    const url = img.dataset.src
    img.src = url
    img.onload = () => {
        img.classList.remove("grayBackground")
        loadedImg++;
        report()
    }
    observer.unobserve(container)
}

const observer = new IntersectionObserver((entries) => {
    entries
    .filter(isIntersecting)
    .forEach(loadImg)
});


export const registerImage = (image) => {
    observer.observe(image);
}

export const getLoadedImg = () => {
    return loadedImg;
}

Para los botones

<button id="add" class="p-3">Agregar Imagen</button>
<button id="del" class="p-3">Limpiar</button>

Me gustar铆a poder conocer su feedback, en especial en la funci贸n delImage
炉_(銉)_/炉