DOM Saga: Guía básica sobre el Document Object Model | Parte #2

DOM Saga: Guía básica sobre el Document Object Model | Parte #2

Última actualización:

Retomamos esta DOM Saga donde la dejamos. Si acabas de aterrizar aquí, puedes ver la parte #1 antes. 🚀

Relaciones entre padres, hijos y demás parientes

¿Recuerdas el node tree de la primera parte de esta saga? Ahí veíamos que existía un document element y un​​ root element y a partir de ahí, el resto de elementos eran sus descendientes👪 Vamos a profundar en el asunto. 

Nodes tree

​​​​Las relaciones entre los distintos nodos de un documento HTML se resumen en relaciones de padres a hijos o a la inversa. También pueden extenderse de padres a hijos, nietos, bisnietos, o la inversa. Por ejemplo, el nodo <body> tiene dos children, el nodo <a> y el nodo <h1>. A su vez, estos dos nodos son elementos hermanos (siblings), ya que están en el mismo nivel

Así que los nodos pueden tener tanto el rol de parent, como de child y de sibling. Por ejemplo, el nodo <body> es child del <html>, sibling del <head> y parent del <a> y el <h1>.  🙃


Acceso de ​parent ​a ​child​​

Sabiendo esto, podemos utilizar el DOM para acceder a elementos según su relación. Por ejemplo, a todos los children de un determinado elemento HTML. Hagamos un ejemplo para entenderlo bien: 

1. Creamos un archivo .html (index.html) y lo vinculamos a un archivo JS (javaScript) vacío al que llamamos sandbox.js. El <body> de nuestro index.html es muy sencillo:​​​​

    <article>
        <h3>The DOM</h3>
        <p>this is a text</p>
        <p>this is a text</p>
        <p>this is a text</p>
        <div>Article written by Ro</div>
    </article>
    <script src="sandbox.js"></script>

2. Vamos a seleccionar todos los children del <article>. Para ello, creamos una referencia al <article> y la guardamos en una variable. Después utilizamos la propiedad children sobre nuestra variable. Hacemos un console.log para ver el resultado en la consola. 

Aquí el bloque de código que hemos añadido:

const article = document.querySelector('article');
console.log(article.children); 

Como verás en tu consola, ahora tenemos una HTMLCollection. Sin embargo, sabemos que no podemos usar un loop ​​sobre una HTMLCollection, así que debemos encontrar la manera de convertir este tipo en un array.

3. Para ello, usamos el array object, que viene con JS por defecto. Este objeto trae un método llamado fromque acepta por parámetro un dato que queramos convertir en array. Así que le pasamos nuestra HTMLCollection. Hacemos un console.log para imprimirlo en la consola.

Aquí la línea de código que hemos añadido:

console.log(Array.from(article.children));

Y con esto, ya tenemos en la consola nuestro array recién creado:

▷ (5) [h3, p, p, p, div]

4. Con nuestro array ya creado, ya podemos iterar a lo largo de los elementos del array haciendo un forEach loop. Queremos añadirle una clase a cada elemento del array, así que podemos usar la propiedad classList y aplicarle el método add. 

Al método add debemos pasarle por parámetro una clase de CSS, así que nos inventamos una que todavía no existe: article-element. Aquí el bloque de código que hemos añadido:​​

Array.from(article.children).forEach(child => {
    child.classList.add('article-element');
});

Con estos cambios, puedes inspeccionar tu página y ver que ahora cada elemento child del <article> tiene la clase de CSS article-element. Que en realidad no supone ningún cambio visible en nuestro navegador, pero sí en nuestras dev tools. 😇

Acceso de ​child a parent

 Si ahora quisiéramos acceder al parent de un node, podemos hacerlo con la propiedad parentElement. Hagamos un ejemplo.

1. Accedemos al <h3> en nuestro archivo JS  creándonos una referencia a través del querySelector. Después, creamos otra variable y le asignamos el valor del parent del <h3>. Si vemos nuestra estructura HTML, sabemos que eso nos debería llevar al <article>.

Aquí el bloque de código que hemos añadido:

const heading = document.querySelector('h3');
const headingParent = heading.parentElement;
console.log(headingParent);

Si vas a tu consola, comprobarás que está impreso el <article>.

2. Podemos encadenar nuestra búsqueda de nodos hasta el infinito, aunque llegará un momento en el que nos de algún error. Por ejemplo, si quisiéramos buscar el parent del parent del parent del valor de la variable headingParent (me he quedado sin aire 😮), el resultado nos daría null. Porque no existe ningún parent más allá del elemento <html>. Ahí hemos tocado techo.

Aquí el bloque de código que hemos añadido que explica el párrafo de arriba:

console.log(headingParent.parentElement.parentElement.parentElement);

Acceso de sibling a sibling 👯‍♀️

Para acceder a elementos hermanos, es decir, que están al mismo nivel en el node tree y tienen un parent element en común, usamos la propiedad nextElementSibling. Por ejemplo, si quisiéramos acceder al sibling element que está inmediatamente después del <h3>, haríamos:

const heading = document.querySelector('h3');
console.log(heading.nextElementSibling);

Algo parecido haríamos si quisiéramos acceder al sibling element inmediatamente anterior, usando la propiedad previousSiblingElement. Así:

console.log(heading.previousElementSibling);

Pero esto nos daría null, ya que, si nos fijamos en la jerarquía de nodos de nuestro archivo HTML, el <h3> no tiene ningún hermano anterior, sólo posteriores:​​​​

jerarquía nodos DOM

Suponiendo que leamos nuestro nodes tree de izquierda a derecha. En cualquier caso, lo puedes comprobar directamente en tu código del index.html, donde ves que no hay ninguno elemento hermano del <h3> antes de éste.

Eventos en JavaScript

Nos adentramos ahora en el maravilloso mundo de los eventos (events) de JavaScript. Los events es la forma que tiene JS de gestionar las interacciones del usuario con una web. Por ejemplo, cuando hace click en un botón, cuando rellena un campo, etc.  Así que recuerda:

Los eventos nos permiten reaccionar a las interacciones del usuario con la página. 🖱️

Hay muchos tipos de events, que adquieren sus nombres en relación a la acción que lleva a cabo el usuario. Por ejemplo, si hace click en algo, ese gesto se llama click event, y es el primero que vamos a ver en esta sección.

Existe una lista completa de los JS events en la web de Mozilla (MDN). Yo la consulto habitualmente. 😌

Los pasos para reaccionar a acciones del usuario mediante un JS event son:

esquema javascript evento

Como ves, introducimos el término de event listener 👂. Un event listener acepta dos argumentos:

button.addEventListener('evento al que queremos reaccionar', callback function que gestiona lo que sucede al reaccionar al evento);

La callback function se disparará cuando el evento ocurra 🔫. Es decir, si el evento es un evento click, la callback function se disparará cuando el usuario haga click sobre algo.

Vamos a hacer un ejemplo para entenderlo bien. 

1. Borramos el contenido del <body> de nuestro archivo index.html y lo sustituimos por este:

    <h3>To do list</h3>
    <ul>
        <li>buy wand</li>
        <li>read Fantastic beasts and where to find them</li>
        <li>play quiddich</li>
        <li>pay rent</li>
    </ul>
    <button>click me!</button>

    <script src="sandbox.js"></script>

En tu navegador ya deberías ver lo que podríamos considerar como una lista de tareas (o to do listmuy simple📝 Lo que vamos a hacer es gestionar lo que ocurre cuando el usuario hace click en el botón que hemos creado.

2. Seguimos los pasos de nuestro esquema de arriba: creamos una referencia para nuestro botón y le añadimos un event listener. Como queremos reaccionar al click event le pasamos ese evento como primer argumento. Como segundo argumento le pasamos una callback function sin argumentos, y un console.log para ver lo que sucede en la consola.

Aquí el bloque de código que hemos añadido:​​​​

const button = document.querySelector('button');

button.addEventListener('click', () => {
    console.log('you just clicked me');
});

Si vas a tu consola y haces click en el botón, verás que se imprime el string que le hemos pasado:

you just clicked me

Y se seguirá imprimiendo cada vez que hagas click en el botón. ¡Genial 👌! Ahora lo que queremos es apuntar a los elementos de nuestra lista para que algo suceda cuando hagamos click en ellos. De hecho, queremos que queden tachados. Pero vayamos por partes.

3. Nos creamos una referencia en JS de todos nuestros <li> con querySelectorAll. Eso nos da una NodeList, y no podemos añadir event listeners a listas de elementos, sino solo a elementos individuales. Pero lo que sí podemos hacer es acceder a estos elementos individuales mediante un loop. 

A cada elemento individual le añadimos un event listener vinculado a un click event. Por ahora, no vamos a pasarle ningún argumento a la callback function. Hacemos un console.log para ver lo que sucede cuando hacemos click en un <li>.​​​​

Puedes comentar el código del punto 2 para que no nos moleste. 🙆

Aquí el bloque de código que hemos añadido:

const items = document.querySelectorAll('li');

items.forEach(item => {
    item.addEventListener('click', () => {
        console.log('item clicked!');
    });
});

4. Vamos a aprender a cómo acceder a cada <li> e informar a JS sobre qué <li> exacto estamos haciendo click. Para eso, es importante que entendamos que cuando ocurre un evento, como el click event, el navegador automáticamente genera un object eventHay muchas clases de object events, por ejemplo, en nuestro caso estamos generando un object mouse event🖱️

Usando ese event object como parámetro de la callback function del método addEventListener, podemos acceder a cierta información del evento en concreto.

En nuestro caso, accederíamos a información sobre el click event. Hacemos un console.log de este object event para ver lo que nos devuelve la consola.

Aquí el bloque de código que hemos editado:

items.forEach(item => {
    item.addEventListener('click', (e) => {
        // console.log('item clicked!');
        console.log(e);
    });
});

Como ves, hemos llamado al parámetro de la callback function "e", diminutivo de "event", pero el nombre que le des es decisión tuya 💁. Lo habitual es llamarlo "e" o "event".​​

Si ahora vas a tu navegador y haces click sobre cualquier <li>, verás que en la consola se despliega una cantidad ingente de información sobre este click event. Como ves, nos indica al principio que es un MouseEvent. A nosotros la propiedad que nos interesa es targetque es igual a li. Esto significa que esta propiedad contiene la información sobre el elemento que ha sido clicado (el <li>).

e.target explicación

5. Si ahora en nuestro código hacemos un console.log del e.targetverás que en tu consola se muestra el <li> exacto sobre el que has hecho click. Aquí el bloque de código que hemos editado:

items.forEach(item => {
    item.addEventListener('click', (e) => {
        // console.log('item clicked!');
        // console.log(e);
        console.log(e.target);
    });
});

¡Chachi! 

Es bueno que sepas que también podríamos indentificar cada <li> usando la variable local del loop, "item", pero es más conveniente usar e.target porque usar la variable local del loop tendría ciertas restricciones. Por ejemplo, hay veces que no necesitamos hacer un loop para acceder a un elemento del DOM. 

6. Utilizamos la propiedad style que hemos aprendido a usar en la parte #1 de esta serie, y le añadimos la propiedad de CSS textDecoration con un valor que haga un efecto de tachado cada vez que hagamos click sobre un <li>.​​​​​​​​

Aquí el bloque de código que hemos editado:

items.forEach(item => {
    item.addEventListener('click', (e) => {
        // console.log('item clicked!');
        // console.log(e);
        // console.log(e.target);
        e.target.style.textDecoration = 'line-through';
    });
});

¡Y voilà! 👏  Si ahora haces click en cualquier <li> de tu lista, verás como aparece una línea que lo tacha.

  • buy wand
  • read Fantastic beasts and where to find them
  • play quiddich
  • pay rent
  • Cómo crear y eliminar elementos del DOM

    En esta sección vamos a aprender a cómo crear y eliminar elementos del DOM. En concreto, vamos a seguir con nuestro ejemplo de nuestra ''to do list'' y aprender cómo eliminar totalmente los <li> de nuestra lista y de nuestra página en general. 

    Eliminar elementos del DOM  🗑️

    Para esto hacemos uso del método remove(). Por ejemplo, si queremos eliminar nuestra <ul>, no tenemos más que seleccionarla con JS y aplicarle el método remove. Así lo haríamos:​​​​

    const list = document.querySelector('ul');
    list.remove();
    

    Como ves, en tu página ha desaparecido por completo la <ul>. Si intentas inspeccionar el elemento tampoco lo encontrarás, porque ha sido borrado del DOM. 🚮

    Comenta ese bloque de código para que no nos moleste y recarga la página para que vuelva a aparecer la lista.

    Así que si quisiéramos eliminar cualquiera de nuestros <li>, sólo tendríamos que aplicar el método remove al e.target. Así nos queda el bloque de código que hemos editado:​​​​

    items.forEach(item => {
        item.addEventListener('click', (e) => {
            // console.log('item clicked!');
            // console.log(e);
            // console.log(e.target);
            // e.target.style.textDecoration = 'line-through';
            e.target.remove();
        });
    });
    

    Y ahora comprobarás que cada <li> se evapora del DOM si haces click en él. ¡Estupendo! 🤗

    Añadir elementos al DOM

     Vamos a explicar esta parte haciendo que, al hacer click en nuestro botón, un <li> nuevo se añada a lista de ''to do's''. ✍️

    1. Cambiamos el contenido en nuestro index.html del botón para ser más coherentes. Así nos queda la línea de código que hemos editado:

        <button>add new task</button>
    

    2. Existen varias maneras de agregar contenido al DOM. Aquí vamos a ver un par de ellas. La primera es sencillamente añadiendo contenido usando innerHTMLNada que no sepamos ya. En cualquier caso, para ello deberíamos:

    • seleccionar la lista y el botón con JS.
    • añadir un event listener al botón, vincularlo a un click event y agregar contenido (<li>) usando la propiedad innerHTML.

    Así nos queda el archivo sandbox.js con los cambios aplicados:​​

    const list = document.querySelector('ul');
    const button = document.querySelector('button');

    button.addEventListener('click', () => {
        list.innerHTML += '<li>a new task</li>';
    });

    const items = document.querySelectorAll('li');

    items.forEach(item => {
      item.addEventListener('click', (e) => {
        // console.log('item clicked!');
        // console.log(e);
        // console.log(e.target);
        // e.target.style.textDecoration = 'line-through';
        e.target.remove();
        });
    });

    Comprueba tu navegador y verás que ahora se añade un nuevo <li> ("a new task") cada vez que haces click en el botón. ¡Genial! 🤩 Vamos a ver una segunda manera de hacerlo.

    3. Esta vez vamos a crear un nuevo elemento usando el método createElement(). Este método acepta un argumento, que será la etiqueta HTML que queramos crear. En nuestro caso, un li.

     4. Definimos un contenido para ese li usando textContent y lo insertamos en el DOM. Existen dos maneras de insertarlo: seleccionando el parent element y añadiendo nuestro elemento dentro de él:

    • o bien al principio,
    • o bien al final.​​​​
    prepend y append

    Si queremos añadirlo al principio, haríamos lo siguiente:

    button.addEventListener('click', () => {
        const li = document.createElement('li');
        li.textContent = 'a new task';
        list.prepend(li);
    });
    

    Eso hará que una nueva <li> ''a new task'' se añada al principio de la lista. Si queremos añadirla al final, sustituimos el método ​prepend por append:

        list.append(li);
    

    Pero tenemos un problemilla 😬. Resulta que, si haces click en alguno de los <li> creados dinámicamente con JS, verás que no se eliminan. Es decir, parece que el event listener no se les aplica. ¿Pero por qué? 🤨

    Esto sucede porque JS añade el event listener al principio, a los <li> iniciales. Sólo después de eso, pasa a hacer la siguiente tarea: crear nuevos <li>. Pero esos nuevos <li> no tienen ningún evento asignado. ​​​​

    Pero que no cunda el pánico, que tenemos una solución: event delegation.

    Event bubbling e event delegation

    Cuando adjuntamos un event a una etiqueta HTML, ese elemento pasa a ser el event targetEn nuestro ejemplo, cualquier <li> sería un event target. Pero aquí no acaba todo. Porque JS, una vez localizado el event target, aplica el mismo evento a su ​​​​parent element, y al parent de ese parent, y así hasta que no haya más elementos en el HTML. 😵

    Esto se conoce como event bubbling​​​​​​

    event bubbling

    JS comprueba si existe un event listener agregado al event target y, de ser así, lo propaga hacia arriba, subiendo elemento por elemento. Si te fijas, aunque hagamos click en el <li>, también estamos haciendo click en su parent (el <ul>) y a su vez en su parent (el <body>), etc. 

    click event target and propagation

    ​​​​​Una de las complicaciones que podría traernos esta situación es si tenemos un event listener vinculado a un <li> y otro event listener distinto vinculado a su parent, un <ul>. Lo que ocurriría sería que el event vinculado al <li> se dispararía aunque hiciésemos click en el <ul>, porque se ha propagado. 

    Veámoslo en acción. 🤖

    1. Siguiendo con nuestro ejemplo, vemos que tenemos un event listener vinculado a cada <li>. Dentro del loop simplemente hacemos un console.log para ver qué se imprime cada vez que hagamos click en un <li>.​​​​​​​​

    2. Le añadimos un click event a nuestra variable list, que simplemente imprima en consola cada vez que hagamos click en el <ul>.

    Aquí el bloque de código que hemos editado/añadido:

    items.forEach(item => {
        item.addEventListener('click', e => {
            e.target.remove();
            console.log('event in LI happened');
        });
    });
    
    list.addEventListener('click', () => {
        console.log('event in UL happened');
    })
    

    Si ahora observas tu consola al hacer click en cualquier <li>, verás que también el evento asociado al <ul> se dispara. No ocurre lo mismo si haces un poco de puntería y clicas en una zona de la pantalla donde solo haya <ul> y no <li>, ya que sólo se disparará el evento asociado al <ul>. 🔫

    Es como si el event listener del <li>, al dispararse la callback function, activase todos los event listeners asociados a elementos padres del <li>. 💣

    Para evitarnos todo este lío, podemos usar un método llamado stopPropagation.

    3. Añadimos este método al event object de los <li>, porque ese es el evento que no queremos que se propague. Aquí el bloque de código que hemos editado:

    items.forEach(item => {
        item.addEventListener('click', e => {
            e.target.remove();
            console.log('event in LI happened');
            e.stopPropagation();
        });
    });
    

    Event delegation

    Vamos a ver ahora el uso del event delegation para poder, por fin, eliminar cualquier <li> de nuestra página, ya haya sido creado en el documento HTML o dinámicamente con JS. 💪

    Hasta ahora, el sistema que hemos utilizado para agregar event listeners es localizar todos los <li> y aplicarles un event listener a cada uno por medio de un loop. Esto no es precisamente una buena práctica, porque en la práctica JS está agregando un event listener a cada <li>, uno a uno. 

    Esto se puede traducir en problemas de rendimiento, por ejemplo. 🥺

    Así que la mejor manera de atajar este problema es usando event delegation. Vamos a verlo en acción.

    1. ​​​​​​​​Comentamos el bloque de código en el que vinculamos un event listener a cada <li>.​​

    2. ​Vamos al event listener del ​​<ul>. Allí vamos a averiguar sobre qué <li> dentro del <ul> se ha hecho click. Para eso, le pasamos el event object como parámetro y hacemos un console.log del e.target. 

    Aquí el bloque de código que hemos editado:​​​​

    // const items = document.querySelectorAll('li');
    
    // items.forEach(item => {
    //     item.addEventListener('click', e => {
    //         e.target.remove();
    //         console.log('event in LI happened');
    //         e.stopPropagation();
    //     });
    // });
    
    list.addEventListener('click', e => {
        // console.log('event in UL happened');
        console.log(e.target);
    })
    

    Comprueba tu navegador y verás que al hacer click en cualquier elemento de la lista, se imprime ese <li> en la consola. ¡Bien! 🥳 Esto significa que podemos reconocer dónde se ha hecho click, aunque el event listener esté vinculado al <ul>, parent de todos los <li>.

    Como decíamos antes, al hacer click en un <li> también estamos haciendo click en una parte del <ul>, y por eso se produce una propagación del evento (event bubbling). ​​​​

    3. Eliminamos cualquier <li> al hacer click sobre él. Para ello, vamos a hacer un console.log únicamente del event object. Con esto hecho, ve a tu consola y pulsa en cualquier <li>. Verás que te aparece un MouseEvent. Busca la propiedad targetque la conocemos bien. 

    Debería decir "li" ya que has hecho click en un <li>. Si la despliegas, encontrarás una propiedad llamada tagNameCon esa propiedad, lo que vamos a hacer es comprobar si el event target (el lugar donde hemos hecho clic) coincide con el espacio que ocupa un <li>. Si es el caso, eliminamos dicho <li> usando el método remove().

    Aquí el bloque de código que hemos editado:

    list.addEventListener('click', e => {
        // console.log('event in UL happened');
        console.log(e);
        if(e.target.tagName === 'LI') {
            e.target.remove();
        }
    });
    

    Y ¡¡tachán!! Ya podemos eliminar cualquier elemento <li> de nuestra web.  🤓

    Más eventos del DOM

    Hasta ahora sólo hemos visto el click event, pero existe una multitud de DOM events. Ten siempre esta lista a mano y échale un vistazo a todos ellos. Nosotros vamos a ver un par de eventos más, pero esto es sólo la punta del iceberg. 😮

    Vamos a usar el mismo archivo HTML pero sustituyendo el <body>, que nos queda así:

    <body>
        <p class="copy">this is a dummy text Lorem ipsum dolor sit amet.</p>
        <div class="box">move the mouse around this box and go nutts</div>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        <p>this is a dummy text Lorem ipsum dolor sit amet.</p>
        
        <script src="sandbox.js"></script>
    </body>

    Nuestro arhivo sandbox.js debería estar el blanco. Vinculamos también el index.html a un archivo CSS al que llamamos styles.css y que tiene el siguiente contenido:

    .box {
        width: 150px;
        height: 150px;
        margin: 10px;
        background: grey;
        text-align: center;
        padding: 10px;
    }
    

    El CSS es simplemente para crear una pequeña caja gris​​, que ya deberías ver en tu navegador.

    Los eventos que vamos a ver son el copy event, el mousemove event y el wheel event. Pero recuerda que hay decenas más. 🧐

    Copy event

    JavaScript nos permite comprobar cuándo un usuario ha copiado un texto, ya sea con ctrl+c  o con el botón derecho del ratón y la opción copiar. Vamos a verlo con un ejemplo.

    1. Seleccionamos el <p> con la clase copy en nuestro archivo JS. Recuerda que así cogeremos la referencia del primer <p> de nuestra web, porque es el único que contiene la clase copy. Guardamos la referencia en una variable.​​

    2. Le aplicamos un event listener a nuestra variable y le pasamos el evento copy. No hace falta que accedamos al event object porque sólo vamos a hacer un console.log para ver cuándo se dispara el evento. 

    Aquí el bloque de código que hemos añadido:

    const copyContent = document.querySelector('.copy');
    
    copyContent.addEventListener('copy', () => {
        console.log('you just copied me!');
    });
    

    ¡Y ahí lo tenemos! Cada vez que un usuario copie un texto que lleva asociado este copy event, lo sabremos. 🕵️‍♀️

    Mousemove event

    Para probar este evento, vamos a mover el ratón a lo largo de nuestra caja gris y utilizar el evento para mostrar la posición con respecto al eje X y al eje Y de la página. 

    1. Creamos una referencia de la caja en nuestro archivo JS. Como le hemos dado la clase box al <div> que contiene la caja, así es como vamos a seleccionarla. La guardamos en una variable.

    2. Añadimos un event listener a la variable y la vinculamos al mousemove event. Aquí sí que vamos a utilizar el event object como parámetro de la callback function. Haz también un console.log para ver qué información nos arroja este event object sobre el mousemove event. 🔍

    Aquí el bloque de código que hemos añadido:​​

    const box = document.querySelector('.box');
    
    box.addEventListener('mousemove', e => {
        console.log(e);
    });
    

    Si vas a tu navegador y mueves el ratón a lo largo de la caja, verás que se imprime un montón de información a cada mínimo movimiento. Cada vez que te mueves 1 píxel en cualquier dirección, de hecho. 

    Despliega la información de cualquiera de los MouseEvent que te ha impreso la consola y busca las propiedades offsetX offsetY. 

    offsetX --> posición en píxeles, medida de izquierda a derecha. El punto más a la izquierda sería 0 píxeles

    offsetY --> posición en píxeles, medida de abajo arriba. El punto más alto sería 0 píxeles

    Vamos, son coordenadas 🗺️. Lo que vamos a hacer es imprimir las coordenadas en las que se encuentra tu ratón en cada momento, pero en la consola y luego en la página.

    3. Hacemos un console.log de las propiedades offsetX offsetY dentro de nuestro event listener. Si ahora guardas y vas a tu consola, verás que se imprimen las coordenadas de tu ratón conforme te mueves a lo largo de la caja. ¡Pruébalo! 😊

    4. Sobreescribimos el contenido de nuestra caja usando textContent y le damos el valor de las coordenadas de nuestro ratón usando las propiedades offsetX offsetY. Las mostramos usando template strings. 

    Así nos queda el bloque de código que hemos editado:

    box.addEventListener('mousemove', e => {
        // console.log(e.offsetX, e.offsetY);
        box.textContent = `pos X: ${e.offsetX} pos Y: ${e.offsetY}`;
    });
    

    ¡Y tachááán! Ya puedes ver las coordanadas de tu ratón en tu página. 👀

    Wheel event

    Por último, vamos a ver un evento que comprueba cuándo el usuario se desplaza hacia arriba o hacia abajo de la página. Para esto, no queremos seleccionar ningún <p> en particular, porque el desplazamiento se produce en todo el documento

    1. Así que sólo necesitamos seleccionar el document object y añadirle directamente un event listener. 

    2. Vinculamos el event listener a un wheel event y le pasamos el event object como parámetro. Si hacemos un console.log del event object y guardamos, verás que en tu navegador se dispara este evento cada vez que nos desplazamos hacia arriba o hacia abajo, siempre que hagamos que la barra lateral derecha se mueva.​​​​​​​​​​

    wheel event

    Despliega cualquiera de los WheelEvents de tu consola y busca las propiedades pageX pageY. Son dos propiedades similar a offsetX offsetY, pero las primeras son relativas a toda la página. ​​​​​​​​​​

    3. Imprime si quieres estas dos propiedades por consola para verlas bien.

    Aquí el bloque de código que hemos añadido:​​

    document.addEventListener('wheel', e => {
        // console.log(e);
        console.log(e.pageX, e.pageY);
    });
    

    ¡BIEN HECHO!

    ¡Y hasta aquí la parte #2 de esta DOM saga! Espero que hayas aprendido algo nuevo. 😊 Si te quedan dudas, ¡nos vemos en los comentarios!

    Para seguir practicando con lo visto hasta ahora, aquí tienes un coding challenge sobre el asunto (disponible próximamente)Y si quieres seguir aprendiendo, aquí tienes la parte #3 (disponible próximamente)

    ¡Ah! Y si crees que este post puede serle útil a alguien, ¡compártelo!

    Otros artículos que pueden interesarte

    Días del 353 al 386
    Objetivos versus realidad Y nuevamente, llegó otro día clave. Llegó…y pasó. El pasado 4 de marzo este Reto Computer Geek[...]
    DOM Saga: Guía básica sobre el Document Object Model | Parte #3
    ¡Por fin llegamos a la última parte de esta DOM saga! 🚀  Si acabas de aterrizar aquí, puedes ver las[...]
    Días del 2 al 4
    "Si buscas resultados distintos no hagas siempre lo mismo" - Albert Einstein Estos días estoy aprendiendo a hacer loops en[...]

    Deja un comentario

    Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

    Como toda web legal que se precie, utilizamos cookies para asegurar que damos la mejor experiencia al usuario en nuestro sitio web. Si continúas utilizando este sitio asumiremos que estás de acuerdo. más información

    Los ajustes de cookies de esta web están configurados para "permitir cookies" y así ofrecerte la mejor experiencia de navegación posible. Si sigues utilizando esta web sin cambiar tus ajustes de cookies o haces clic en "Aceptar" estarás dando tu consentimiento a esto.

    Cerrar