Aprende Javascript con MentoringJS - Step 7
Modificar el DOM es un conocimiento básico y un conocimiento muy potente para un programador frontend.
Antes de nada, voy a explicar brevemente qué es el DOM.
El DOM es lo que conecta las páginas web con scripts o lenguajes de programación, en este caso con Javascript. El DOM es una interfaz de programación para los documentos HTML y XML que facilita una representación estructurada del documento y define de qué manera los programas pueden acceder, al fin de modificar, tanto su estructura, estilo y contenido. Para más información se puede acudir aquí.
En esta entrada voy a traducir y resumir un artículo muy interesante dónde se detalla como alterar el DOM con Javascript.
¿Qué se hace con el DOM?
Cuando se trabaja con el DOM, te encuentras con la necesidad de hacer una o más de las siguientes cosas:
- Seleccionar elementos HTML
- Añadir y eliminar event listeners
- Añadir y eliminar clases
- Añadir, cambiar y eliminar atributos
- Añadir y eliminar elementos HTML
1. Seleccionando elementos HTML
Conocer como se seleccionan elementos HTML es el primer paso antes de hacer cualquier otra cosa con el DOM. Para ello, solo es necesario conocer dos métodos: querySelector y querySelectorAll.
querySelector
querySelector ayuda a seleccionar un elemento HTML.
document.querySelector(selector)
Se puede seleccionar un elemento por su id, clase o incluso por la etiqueta querySelector.
Teniendo el siguiente código:
<div id="primero">ID</div>
<div class="clase-increible">Class</div>
<p>A tag</p>
Para seleccionar el elemento por su id, se añade antes del id un #
document.querySelector('#primero').
Para seleccionar el elemento por su clase, se añade antes de la clase un .
document.querySelector('.clase-increible').
Para seleccionar el elemento por su etiqueta, simplemente se escribe la etiqueta como el selector.
document.querySelector('p')
querySelector es muy poderoso y también permite hacer selecciones complicadas encandenando ids, clases, etc., aunque no es del todo recomendable hacerlo ya que normalmente es innecesario. También se puede seleccionar elementos dentro de elementos, con lo que se reduce el tiempo necesario para buscar un elemento profundo. Para hacer eso, tienes que añadir un espacio entre las clases, ids o etiquetas. Tenemos el código siguiente:
<div class="container">
<div class="item-profundo">Inner item!</div>
</div>
Y seleccionamos el elemento dentro del elemento con:
let innerItem = document.querySelector('.container .item-profundo')
De manera alternativa, si ya has seleccionado un elemento con querySelector también puedes usar ese elemento para utilizar otra llamada con querySelector:
let container = document.querySelector('.container')
let itemProfundo = container.querySelector('.item-profundo')
querySelectorAll
querySelectorAll es un método que te ayuda a seleccionar múltiples elementos.
let allELements = document.querySelectorAll(selectors);
selectors, en este caso, tiene la misma sintaxis que querySelector. La única excepción es que se puede realizar múltiples selecciones separándolas con una coma (,).
<div class="cosa">Una cosa</div>
<div class="cosa">Otra cosa</div>
<div class="otra-cosa">Y otra cosa</div>
Aquí está la parte importante.
querySelectorAll devuelve un NodeList Si estás trabajando con navegadores modernos, puedes utilizar elementos individuales con la instrucción
Nodelist.forEach
let todasCosas = document.querySelectorAll('.cosa, .otra-cosa')
todasCosas.forEach(el => {/* hacer algo con el elemento */})
Si estás trabajando con navegadores antiguos, necesitas convertir el NodeList en un Array antes de pasarlo por el bucle forEach. La manera más sencilla de hacerlo es usando Array.from ().
let todasCosas = document.querySelectorAll('.cosa, .otra-cosa')
let todasCosasArray = Array.from(todasCosas)
De manera alternativa:
todasCosasArray.forEach(el => {/* hacer algo con el elemento */})
2. Añadir y eliminar event listeners
Los event listeners permiten a tu Javascript realizar una acción cuando se dispara un evento. Así es como tu sabes cuando un usario ha interactuado con el DOM. Un ejemplo de esto es cuando el usuario pincha en un botón. Para gestionar este tipo de eventos tan solo es necesario conocer dos métodos: addEventListener y removeEventListener
Añadir event listeners
Para añadir este tipo de eventos, primero se debes seleccionar tu elemento HTML, después llamar al método addEventListener con dos parámetros:
let cosa = document.querySelector('.cosa')
cosa.addEventListener(evento, callback)
evento es el nombre del evento que quieres que escuche. Estos eventos ya vienen predeterminados en las especificaciones. Aquí hay una lista a mano con los tipos de eventos más comunes que seguramente querrás.
Callback es la función que hace lo que tu quieres siempre que el evento es lanzado. Contiene un parámetro: el objeto evento.
Eliminar event listeners
Para eliminar este tipo de eventos se debe llamar al método removeEventListener pasándole dos parámetros –el tipo evento y el callback.
cosa.removeEventListener('click', callback)
Normalmente, solo se necesita eliminar un event listener después de que la tarea haya finalizado. Por ello, es común encontrar el método removeEventListener dentro de la llamada a addEventListner.
cosa.addEventListener('click', callback)
function callback () {
console.log('cosa has sido pinchada!')
// elimina el oyente de eventos
cosa.removeEventListener('click', callback)
}
3.Añadir y eliminar clases
- Para añadir una clase, se usa element.classList.add(‘classname’)
- Para eliminar una clase, se usa element.classList.remove(‘classname’)
- Para comprobar si una clase existe, se usa element.classList.contains(‘classname’)
El siguiente código muestra el funcionamiento de un botón comprobando si una clase existe. Si existe la elimina, si no, la crea.
let boton = document.querySelector('boton')
let nav = document.querySelector('nav')
boton.addEventListener('click', toggleNav)
function toggleNav() {
// Comprueba si nav contiene una clase abierta
if (nav.classList.contains('abierta')) {
// eliminar la clase abierta
nav.classList.remove('abierta')
} else {
// añade la clase abierta
nav.classList.add('abierta')
}
}
4.Añadir, cambiar y eliminar atributos
Los atributos son una parte importante de los elementos HTML. A veces, es necesario extraer información de esos atributos para dar sentido a tu Javascript. Otras veces, puedes utilizar esos atributos para ayudar a hacer interfaces más accesibles. Aquí hay una demostración del código anterior, escrita de un modo más accesible:
let boton = document.querySelector('boton')
let nav = document.querySelector('nav')
boton.addEventListener('click', toggleNav)
function toggleNav() {
let abierta = nav.classList.contains('abierta')
if (abierta) {
nav.classList.remove('abierta')
nav.setAttribute('aria-hidden', true)
boton.setAttribute('aria-expanded', false)
} else {
nav.classList.add('abierta')
nav.removeAttribute('aria-hidden')
boton.setAttribute('aria-expanded', true)
}
}
En este código han cambiado dos cosas:
- Se ha añadido aria-expanded al boton para decir a los readers que el menú está expandido.
- Se ha añadido aria-hidden a la nav para evitar a los readers leer el menú cuando este está escondido.
Así es como puedes extraer información de un atributo, editarlo o eliminarlo.
- Para seleccionar un atributo, usa getAttribute (‘atrribute-name’)
boton.getAttribute('aria-expanded')
- Para modificar/editar un atributo, usa setAttribute(‘attribute-name’, ‘attribute-value’)
boton.setAttribute('aria-expanded', true)
- Para eliminar un atributo, usa removeAttribute(‘attribute-name’)
boton.removeAttribute('aria-expanded')
5.Añadir y eliminar elementos HTML
Añadir elementos al DOM
Se necesitan tres pasos para añadir texto en el DOM:
- Crear un elemento HTML con document.createElement
let li = document.createElement('li')
- Añadir contenido al elemento HTML poniendo htmlProfundo
li.htmlProfundo = '¡Hola mundo de nuevo!'
- Añadirlo al DOM con parentNode.prepend o parentNode.append
ul.append(li)
Borrar elementos del DOM
Para eliminar elementos del DOM necesitas llamar parentNode.removeChild. Este método toma como parámetro el elemento a borrar.
ul.removeChild(li)
No podemos simplemente decir que se borre el elemento li y esperar que Javascript conozca que lista debe eliminar. Es necesario decirle a nuestro Javascript cuál es el que, explícitamente, hay que eliminar. Si usas querySelector para escoger qué elemento eliminar, este sería el método más sencillo de hacerlo:
let padre = document.querySelector('.padre')
let elaBorrar = document.querySelector('.elemento-a-borrar')
padre.removeChild(elaBorrar)
// O si no quieres escribir un querySelector separado
elaBorrar.parentNode.removeChild(elaBorrar)
En la demo de arriba no podemos hacerlo porque no hay manera de decirle cuál es el primer o último ítem con clases o ids. En vez de eso, podemos usar parentNode.children para conseguir un NodeList de los elementos dentro de ul, para después, usar el método Array para espcecifciar el elemento concreto a eliminar. Aquí está el código para eliminar el primer elemento hijo:
let lista = document.querySelector('ul')
removeFirst.addEventListener('click', e => {
if (lista.children.length) {
let primerNodo = lista.children[0]
list.removeChild(primerNodo)
}
})