Document Object Model (DOM) en JavaScript
El DOM (document object model) es una plataforma y lenguaje neutral de interfaz (API) que permite el acceso dinámico y actualización de contenido, estructura y estilo en objetos HTML, XHTML y XML. El DOM es la estructura vertebral mediante la cual JavaScript accede a todos los objetos del HTML. En este post entenderás cómo funciona y cómo manipularlo.
Especificación oficial
Las descripción del lenguaje, así como sus listas de correo e información en general se pueden encontrar en la página oficial del W3C (World Wide Web Consortium). Sin embargo el living standard, que vendría a ser como la especificación viva y actualizada constantemente está a cargo de la WHATWG (respaldado igualmente por W3C).
Árbol DOM
Los navegadores web renderizan los documentos HTML convirtiéndolos en un arbol DOM (Document Object Model). Un árbol DOM es una representación en memoria de un documento. Un árbol DOM puede contener varios tipos de nodos, entre los que se encuentran el nodo DocumentType, el nodo Element, los nodos Text, los Comment, entre otros. Observa por ejemplo el siguiente documento HTML.
<!DOCTYPE html>
<html>
<head>
<title>Mi primer documento HTML</title>
</head>
<body>
<h1>Mi primer documento HTML</h1>
<p>Documento de ejemplo</p>
<!-- Esto es un comentario -->
</body>
</html>
Este documento está representado en memoria por el siguiente árbol DOM.
Cómo se puede observar, no solamente se representan los elementos HTML sino también los espacios en blanco, saltos de línea y comentarios. Entender cómo funciona el DOM es necesario para manipular los objetos de la página con lenguajes como CSS y JavaScript.
En el DOM, los documentos tienen una estructura lógica a modo de árbol, cada elemento puede contener otros elementos dentro de sí y anidarse cuantas veces sea necesario.
Manipulación del DOM
Para manipular el DOM tenemos una amplia interfaz definida en la documentación de la especificación. Aquí vamos a ver algunos de los métodos más comunes para dicha manipulación.
document.querySelector
Este método obtiene el primer elemento con el cual se halle una coincidencia utilizando selectores CSS.
document.querySelector('h1')
Veamos este ejemplo en donde se utiliza este selector para llegar hasta el elemento h1 y cambiar su texto.
document.querySelectorAll
Este método obtiene una lista de nodos de elementos con los cuales se halle una coincidencia utilizando selectores CSS. La ventaja de que el resultado sea un NodeList
es que podemos utilizar métodos como forEach
para iterar los elementos. Modifiquemos un poco el HTML para tener dos párrafos como sigue:
<!DOCTYPE html>
<html>
<head>
<title>Mi primer documento HTML</title>
</head>
<body>
<h1>Nuevo texto</h1>
<p>Párrafo 1</p>
<p>Párrafo 2</p>
<!-- Esto es un comentario -->
</body>
</html>
Con la siguiente instrucción tomamos los dos párrafos para modificar su color de fondo a rojo.
let elements = document.querySelectorAll('p')
elements.forEach(item => item.style.backgroundColor = 'red')
Atributos
Como sabes los atributos en los elementos HTML se componen de una clave y un valor, por ejemplo src="logo.png"
. La interfaz de JavaScript nos permite fácilmente manipular los atributos para agregar, editar o borrarlos de manera eficiente. Vemos el siguiente código.
<!DOCTYPE html>
<html>
<head>
<title>Mi primer documento HTML</title>
</head>
<body>
<h1>Title</h1>
<p class="foo bar">Párrafo 1</p>
<img src="logo.png" alt="logo" />
</body>
</html>
Con el siguiente código podemos verificar si existe el atributo src
en la imagen y reemplazarlo por uno diferente.
let img = document.querySelector('img')
img.hasAttribute('src'); // true
img.setAttribute('src', 'image.jpeg')
También puedes eliminar un atributo de la siguiente manera.
img.removeAttribute('alt')
El atributo especial className
Uno de los problemas de hace algunos años al intentar manipular las clases de los elementos HTML es que cuando tienes varias clases se hace engorroso identificar una clase para eliminarla o para verificar si ya existe y agregarla. Cuando obtenemos un elemento hoy día tenemos acceso a la propiedad classList
que nos facilita esta tarea. Veamos el siguiente código.
<!DOCTYPE html>
<html>
<head>
<title>Mi primer documento HTML</title>
</head>
<body>
<h1>Title</h1>
<p class="foo bar">Párrafo 1</p>
<p>Párrafo 2</p>
<!-- Esto es un comentario -->
</body>
</html>
Observa cómo podemos quitar la clase bar
y agregar la clase baz
.
let list = document.querySelector('.foo.bar').classList
list.remove('bar')
list.add('baz')
Adicional a esto tienes la posibilidad de utilizar el método toogle
tal y cómo recordarás de jQuery pero nativo!.
list.toggle('baz')
También podemos hacer uso del método replace
para reemplazar una clase.
list.toggle('foo', 'new_class')
Creación de elementos
Con JavaSCript también podemos crear nuevos elementos en el árbol DOM haciendo uso del método document.createElement
. Veamos el siguiente HTML.
<!DOCTYPE html>
<html>
<head>
<title>Mi primer documento HTML</title>
</head>
<body>
<h1>Title</h1>
<p>Párrafo 1</p>
<p>Párrafo 2</p>
</body>
</html>
Ahora veamos cómo agregar un nuevo párrafo justo después del último con el método append
.
let p = document.createElement('p')
p.innerHTML = 'Párrafo 3'
document.querySelector('body').append(p)
Si lo que necesitas es agregar un elemento justo antes de todos los demás debes utilizar el métod prepend
.