10

Como manipular el DOM con Javascript

¿Qué es el DOM?

Todos los navegadores lo usan para trabajar y renderizar una pagina web. Todo comienza con un proceso conocido como Critical Rendering Path, el cual es un proceso que hacen todos los navegadores para que todo nuestro código HTML, CSS y Javascript se conviertan en pixeles en la pantalla de los usuarios. En este paso el navegador crea dos arboles, el primero de ellos DOM (Document Object Model) y el segundo CSSOM, se les dice árbol porque esa es la estructura de datos que representa, donde cada elemento es un nodo. El DOM esta compuesto por nodo, donde cada nodo son etiquetas HTML, y el CSSOM trabaja con el árbol de estilos.

Por tanto, tenemos los siguientes puntos

DOM

  • Es una representación del HTML.
  • Estructura en forma de árbol que contiene nodos.
  • Es dinámico, es decir, puede cambiar.

CSSOM

El Modelo de objetos CSS (CSS Object Model) es un conjunto de APIs que permite manipular CSS desde JavaScript. Así como el DOM (Document Object Model) es para HTML, el CSSOM (CSS Object Model) es para CSS. Permite leer y modificar el estilo de CSS de forma dinámica.

Web API

Es una mezcla de DOM + Javascript. Una Web API nos permite conectar el DOM con Javascript para que podamos manipularlo (Agregar, edita y quitar elementos). Existe más de 70, el DOM es una de ellas, existen otras para hacer animaciones, manejo de archivos, Drag and drop.

Leer Nodos

  • document.getElementById

    Nos permite obtener un elemento del DOM a través de su ID. Retorna un único nodo del HTML, porque solo en una página cada id debe ser único, es decir, no puede haber mas de un elemento con el mismo ID. Un ejemplo seria obtener el elemento con el id firstName, lo hacemos de la siguiente manera:

    document.getElementById("firstName");
    
    
Imgur
  • document.getElementsByTagName

    Nos permite obtener una lista (NodeList) con todos los nodos que tienen definida la etiqueta proporcionada. Es un método que puede traer 0, 1 o n Nodos. Un ejemplo seria obtener de nuestro documento todos los elemento que sean un span, lo hacemos de la siguiente manera:

    document.getElementsByTagName("span");
    
    
Imgur
  • document.getElementByClassName

    Funciona similar al anterior, pues nos retorna una lista, pero en este caso nos devuelve los nodos que entre sus clases contenga la especificada en el argumento del método, es decir, vamos a identificar una clase y traemos todos los elementos que contengan dicha clase, supongamos que queremos obtener todos los nodos que contengan la clase container, lo haríamos de la siguiente manera:

    document.getElementsByClassName("container");
    
    
Imgur
  • document.querySelector

    Nos permite obtener cualquier elemento del DOM de acuerdo al argumento que le indiquemos, podemos pasarle una cadena de caracteres que contiene uno o mas selectores CSS, estos deben ir separado por comas. Este método retorna el primer elemento que coincida con el filtro, es decir, si existen varios elementos que coincidan con la búsqueda este nos retornara el primero que encuentre. Si no encuentra ningún elemento retorna null. Veamos un ejemplo donde buscaremos un elemento que contenga la clase container.

    document.querySelector(".container");
    
    

    Como vemos debemos especificar el símbolo del selector, similar como ocurre en CSS, si queremos obtener por clase (".container"), ID (#container), etiqueta directamente (“h1”).

Imgur
  • document.querySelectorAll

    Este método es casi igual al anterior a diferencia de que este devuelve una lista (NodeList) donde se encuentran todos los elementos que coincidan con el o los selectores indicados. Supongamos que queremos hacer la misma búsqueda del ejemplo del ítem anterior, obtener los elementos con la clase container

    document.querySelectorAll(".container");
    
    

    A diferencia del método anterior que nos devuelve la primera coincidencia, aquí vamos a obtener todos esos elementos que coincidan con el selector indicado.

Diferencias entre NodeList y Array

Un NodeList puede parecer mucho a un Array, pero la realidad es que son dos estructuras completamente distintas. Por un lado NodeList es una colección de nodos del DOM, extraidos del HTML y un Array es un tipo de dato especial en Javascript, donde podemos almacenar cualquier tipo de dato. Ambos tienen similitudes, como acceder a la longitud, a través de length, acceder a los elementos a través de su indice usando [indice]. Ahora, hay que aclara que en un NodeList no tenemos disponibles los principales métodos de Array que nos facilitan la vida, como map(), filter(), reduce(), some(). Un dato curioso y super interesante del NodeList es que es una especie de colección en vivo, ¿y que quiere decir esto? Que si se agrega o se elimina algún elemento del DOM los cambios son aplicados inmediatamente y de forma automática al NodeList.

Es recomendable transformar los NodeList a Array, pues la mayoría de los motores de Javascript están optimizados para trabajar con Arrays, en especial el motor V8 de Google. Ahora veamos dos formas de transformar un NodeList en un array.

// Forma 1: Spread Operatorconst inputs = document.querySelectorAll("input");
const inputsArray = [...inputs];

// Usando la clase Array y su método fromconst inputs = document.querySelectorAll("input");
const inputsArray = Array.from(inputs);

Crear nodos

  • document.createElement

    Crea un elemento HTML especificado por su tagName. Este elemento es solo creado, es decir, se crea en memoria, normalmente es asignado en una variable, pero no pertenece al DOM, no forma parte de los nodos hasta que lo indiquemos. Supongamos que queremos crear un elemento div, lo hacemos de la siguiente manera

    document.createElement("div");
    
    
Imgur
  • document.createTextNode

    Este método nos permite crear un nodo de texto, generalmente es usado para escapar caracteres HTML. Recibe una cadena de texto que contiene los datos a poner en el nodo. Veamos un ejemplo,

    document.createTextNode("Este es un nodo de texto");
    
    
Imgur
  • document.createAttribute

    Este método nos permite crear un nodo de tipo atributo. El DOM no impone que tipo de atributos pueden ser agregados a un particular elemento. Funciona de igual forma a los demás, solo crea un nodo, que puede o no en el DOM, veamos un ejemplo,

    document.createAttribute("href");
    
    

Agregar Nodos

  • parentElement.appendChild

    Este método nos permite agregar un elemento (Nodo) al final de la lista de hijos de un elemento padre previamente especificado, es decir, agrega un elemento dentro de un padre, y este es colocado al final. Es importante resaltar que si el Nodo que se esta insertando existe en el documento actual, es una referencia, este sera removido del padre actual y sera puesto dentro del padre que se esta especificando. por otro lado este método retorna o devuelve el elemento Nodo insertado. Supongamos que tenemos una lista, y queremos insertar un nuevo elemento con el texto “Item 3”, lo haremos de la siguiente manera

    const list = document.querySelector("#list");
    const item = document.createElement("li");
    const text = document.createTextNode("Item 1");
    
    // Insertamos el texto dentro del item
    item.appendChild(text);
    
    // Insertando el item en la lista
    container.appendChild(item);
    
    
Imgur
  • parentElement.append

    Este método es una evolución de appendChild, donde podemos agregar más de un nodo, cosa que no podemos hacer en el método anterior, podemos agregar texto. Este también agrega los nodos al final de los hijos del elemento padre especificado, y no retorna ningún elemento. No tiene soporte adecuado para IE 11. Veamos un ejemplo, donde insertaremos un texto en un elemento li, y ademas agregaremos un nuevo hijo, simulando un menú de varios niveles.

    const container = document.querySelector("ul.container");
    const item = document.createElement("li");
    const subItem = document.createElement("ul");
    
    // Agregamos el texto de item, adicional insertamos la nueva lista
    item.append("Categorias", subItem);
    
    // Agremos el item al menu
    container.append(item);
    
    
Imgur
  • parentElement.insertBefore

    Este método permite insertar o agregar un nodo, antes del nodo que pasemos de referencia, y que pertenece al padre del que estamos accediendo a dicho método. Si insertamos un Nodo que ya esta en nuestro DOM el método lo cambia de lugar, es decir, lo quita de donde se encuentra actualmente y lo inserta en el sitio al que estamos haciendo referencia. Este método recibe dos argumentos, el primero de ellos es el Nodo que queremos insertar, y el segundo es el Nodo de referencia. Si el segundo argumento es null entonces el nodo se insertar al final de la lista de hijos del padre, es decir, actúa como el appendChild. Veamos un ejemplo,

    const parent = document.querySelector(".container");
    const item = document.querySelector(".contact");
    const newItem = document.createElement("li");
    const text = document.createTextNode("Blog");
    
    newItem.append(text);
    
    /* Insertamos el nuevo elemento al padre, lo insertaremos antes del
    elemento con clase contact */
    parent.insertBefore(newItem, item);
    
    
Imgur
  • parentElement.insertAdjacentElement

    Este método permite insertar un nodo de acuerdo a una posición especificada, y lo ubica con respecto al elemento sobre el cual es llamado. Es uno de los más complicados de usar, pero el que más opciones de inserción nos proporciona. Este método recibe 2 argumentos, el primero de ellos donde se insertará el nuevo nodo, para esto contamos con cuatro opciones, las cuales son:

    • beforebegin: Inserta el elemento antes de la referencia. Es decir, antes del nodo que llama al método en cuestión.
    • afterbegin: Insertar el nodo dentro del elemento referencia, pero ademas de esto lo inserta antes de su primer hijo.
    • beforeend: Al igual que la opción anterior lo agrega dentro del elemento referencia, con la particularidad de que ahora lo inserta después de su ultimo hijo.
    • afterend: Inserta el elemento después del nodo referencia, es decir, despues del nodo que llama al método.

Otras formas de agregar HTML

Existen otras formas de agregar el HTML, estas tambien funcionan para leer fragmentos de nuestro código, son las siguientes propiedades innerHTML y outerHTML, veamos que hace cada una de ellas

Imgur
  • element.innerHTML:
    Esta propiedad devuelve o establece la sintaxis HTML descrita dentro del elemento al que hace referencia, es decir, esta propiedad devuelve todo el contenido que esta dentro del Nodo (element) que la llama. Al acceder a esta propiedad obtenemos un fragmento de código (DOMString) que contiene todo el extracto serializado de todos los descendientes. Esta propiedad también es usada para reemplazar todo el HTML descendiente del elemento que la invoca. Supongamos que tenemos un div que contiene un párrafo p dentro, ahora, queremos cambiar el contenido de ese div, esto lo hacemos de la siguiente manera

    // Elemento base<div class="container"><p>Bienvenido a este sitio</p></div>// Obtenermos el elemento al que queremos cambiar el contenido
    let container = document.querySelector(".container");
    
    // Reemplazamos el contenido
    container.innerHTML = "<span>Bienvenidos<span>";
    
    // Resultado<div class="container"><span>Bienvenidos<span></div>

    Esta propiedad no es recomendable porque puedes sufrir de ataques decross-site scripting, ya que puedes ejecutar código Javascript maligno, por la forma en que puedes ejecutar javascript sin necesidad de tener la etiqueta

Imgur
  • element.outerHTML: Es similar a la propiedad anterior, pero la única diferencia es que este toma el elemento padre (element) y reemplaza el contenido completo, incluyendo el elemento contenedor, veamos como quedaría el ejemplo anterior si usamos outerHTML

    // Elemento base<div class="container"><p>Bienvenido a este sitio</p></div>// Obtenermos el elemento al que queremos cambiar el contenido
    let container = document.querySelector(".container");
    
    // Reemplazamos el contenido
    container.outerHTML = "<span>Bienvenidos<span>";
    
    // Resultado<span>Bienvenidos<span>

Atributos

En nuestro documento le podemos asignar atributos a cada elemento del DOM, ¿Pero que son los atributos? son valores adicionales que agregamos a las etiquetas para configurar o ajustar su comportamiento de muchas formas, con el fin de cumplir con los criterios que requieren los usuarios.

Con javascript podemos acceder a esos atributos definidos en el HTML, veamos un ejemplo de como podemos hacer esto, supongamos que tenemos un input que recibe el nombre completo de una persona

// Nuestro input
<input class="form-control" 
       id="persona-nombre" 
       placeholder="Nombre completo" />

// Obtenemos elinput
const input = document.querySelector("#persona-nombre");

// Obtenemos los atributos
input.className // salida:"form-control"input.id // salida:"persona-nombre"input.placeholder // salida:"Nombre completo"

Como vimos podemos acceder a cada atributo como lo hacemos cuando queremos obtener una propiedad en un objeto de javascript, con esto podemos verificar que valor esta tomando cada atributo. Si en el input escribimos texto desde el navegador, podemos acceder a ese valor a través de input.value.

Javascript cuenta ademas con otras métodos que permiten manipular los atributos de los nodos, estos son element.setAttribute(), element.getAttribute() y element.removeAttribute(). Veamos como funciona cada uno

Imgur
  • element.setAttribute()

    Este método establece el valor de un atributo en el elemento indicado, recibe dos argumentos, el primero de ellos un string donde se indica el nombre del atributo, y el segundo el valor que tomará dicho atributo. Es importante mencionar que si el atributo ya existe en el elemento, el valor será actualizado. supongamos que al input del ejemplo anterior queremos agregarle el atributo name, lo hacemos de la siguiente manera

    input.setAttribute("name", "fullName");
    
    // Ahora elinput quedará de la siguiente manera
    
    <input class="form-control" 
           id="persona-nombre" 
           placeholder="Nombre completo" 
    			 name="fullName" />
    
Imgur
  • element.getAttribute()

    Este método retorna el valor del atributo especificado en el elemento. Si el atributo al que se hace referencia no esta definido en el elemento, el valor que retornará dicho método es null. Supongamos que queremos obtener el valor del atributo name agregado en el ejemplo anterior.

    input.getAttribute("name"); // Salida:"fullName"
Imgur
  • element.removeAttribute()

    Este método elimina el atributo del elemento que lo invoca, con esto podemos quitar atributos que ya no necesitemos, supongamos que queremos eliminar el atributo name del input de los ejemplos anteriores, lo hacemos de la siguiente forma

    input.removeAttribute("name");// input final
    <input class="form-control" 
           id="persona-nombre" 
           placeholder="Nombre completo" />
    

Remover elementos

  • parent.removeChild

    Este método elimina el nodo hijo del DOM, y lo retorna. Cabe destacar que este método funciona solo para hijos directos, es decir, para que el nodo se elimine tiene que ser hijo inmediato del elemento que invoca al método. Veamos con un ejemplo

    // Nuestro HTML
    <div class="parent">
    	<p class="p-child">Titulo</p>
    	<span class="span-child">Subtitulo</span>
    </div>
    
    // Obtenemos el nodo padreconst parent = document.querySelector(".parent");
    
    // Obtenemos el nodo a eliminarconst nodoAEliminar = document.querySelector(".p-child");
    
    // Eliminamos el nodo
    parent.removeChild(nodoAEliminar);
     
    
Imgur
  • Node.remove

    Es una mejora del método anterior, este nos permite eliminar un nodo del DOM con solo invocarlos desde el elemento que queremos eliminar, es decir, para este método no hace falta conocer el padre del elemento, solo lo invocamos y elimina el nodo. Veamos como funciona con el ejemplo anterior

    // Nuestro HTML
    <div class="parent">
    	<p class="p-child">Titulo</p>
    	<span class="span-child">Subtitulo</span>
    </div>
    
    // Obtenemos el nodo a eliminarconst nodoAEliminar = document.querySelector(".p-child");
    
    // Eliminamos el nodo
    nodoAEliminar.removeChild();
    
Imgur
  • Node.replaceChild

    Este método reemplaza un nodo hijo del elemento especificado por otro. Recibe dos argumentos, el primero de ellos es el nuevo elemento, y como segundo argumento el nodo que sera reemplazado por el nuevo. Veamos como funciona usando el ejemplo anterior, supongamos que queremos reemplazar el span por un párrafo.

    // Nuestro HTML
    <div class="parent">
    	<p class="p-child">Titulo</p>
    	<span class="span-child">Subtitulo</span>
    </div>
    
    // Obtenemos el nodo padreconst parent = document.querySelector(".parent");
    
    // Obtenemos el nodo a reemplazarconst nodoAReemplazar = document.querySelector(".p-child");
    
    // El nuevo elementoconst nodoNuevo = document.createElement("p");
    nodoNuevo.textContent = "Soy un nuevo nodo";
    
    // Reemplazamos el nodo
    parent.replaceChild(nodoNuevo, nodoAReemplazar);
    
Escribe tu comentario
+ 2
Ordenar por:
3
11161Puntos
4 años

Gracias, buen apunte!

0
6908Puntos
4 años

De nada, que bueno que te sirvió

1
17452Puntos
3 años

Gracias excelente aporte!!