trasteando con el DOM 3: Anatomía elemental

Principales maneras de manipular los elementos del DOM

Tarsila do Amaral

archivado en: JavaScript / 4 octubre, 2014 / taller:

Sigo con esta serie sobre javaScript para diseñadores web.

Como ya sabemos, una página o aplicación web está formada por una montonera de etiquetas, que son los distintos nodos del DOM. Estos nodos se ramifican en una estructura arbórea que nos permite hablar de padres, hijos y hermanos. Por ejemplo, si tenemos esta lista...

<ul>

<li>Azul</li>

<li>verde</li>

<ul>

...los nodos <li> son hermanos e hijos de <ul>, que es su padre.

Los nodos pueden ser de varios tipos. Los dos más importantes son los tags normales (h1, img, ul, etcétera) y el texto que se incluye en un tag que lo permita. Por ejemplo, este fragmento de html:

<h1>Soy un titular</h1>

...está formado por dos tipos de nodo:

  1. Un ELEMENT_NODE, que es todo el conjunto del par de etiquetas <h1></h1>.
  2. Un TEXT_NODE, que sería la cadena «Soy un titular».

Todos los nodos son objetos y en tanto que tales tienen los métodos y propiedades del superobjeto Nodo (y ya veremos qué significa eso). Pero, además, los nodos del tipo elemento tienen los métodos y propiedades del superobjeto Elemento. Podríamos agruparlos de la siguiente manera (observad la diferencia entre Node y Element):

a) Propiedades relacionadas con la estructura del DOM.

Son propiedades que guardan relación con el parentesco del nodo que hemos seleccionado y se utilizan para seleccionar a su vez otro nodo a partir de este. Por ejemplo, es como si yo tuviera una propiedad que es hermanos, cuyo valor sería mi hermano Uri. Las propiedades más empleadas de este tipo son:

  • Node.childNodes: los nodos hijos.
  • Node.firstChild: el primer hijo.
  • Node.lastChild: el último.
  • Node.nextSibling: el primer hermano.
  • Node.previousSibling: el hermano anterior.
  • Node.parentElement: el padre del tipo elemento.
  • Node.parentNode: el nodo padre, sea cual sea.

Por ejemplo, así añadiríamos una clase al ul padre de un li.

<ul>

<li id="itemLista">Soy un nodo hijo</li>

<li>Soy el hermano del anterior</li>

</ul>

<script>

var miNodo = document.getElementById('itemLista');

miNodo.parentNode.setAttribute('class', 'claseAñadida');

</script>

b) Propiedades relacionadas la naturaleza del nodo.

Como ya vimos, podemos saber qué tipo de nodo es cada cual con alguna de estas propiedades:

  • Node.nodeName: el nombre del nodo.
  • Node.nodeType: el tipo de nodo.
  • Element.tagName: la etiqueta.

c) Propiedades relacionadas con el contenido del nodo.

  • Node.textContent: la cadena de texto que contiene el nodo.
  • Element.innerHTML: el contenido, incluido los tags html, del nodo.

Por ejemplo, así cambiaríamos el contenido de texto de un nodo:

<div id="texto">Soy el contenido original</div>

<script>

var miNodo = document.getElementById('texto');

miNodo.textContent = "Cambiado";

</script>

Y así si quisiéramos incluir tags de html:

miNodo.innerHTML = "<h1>Cambiado</h1>";

d) Propiedades relacionadas con el tamaño y la posición del nodo

  • Element.clientHeight: el alto.
  • Element.clientWidth: el ancho.
  • Element.clientLeft: su distancia respecto al margen izquierdo del navegador.
  • Element.clientTop: su distancia con el margen superior.
  • Element.offset: su posición x e y.

e) Propiedades y métodos relacionados con los atributos y estilos de un elemento.

  • Element.attributes: una colección con todos los atributos del elemento.
  • Element.classList: una DOMTokenList (ya veremos qué es eso) con todas las clases de un elemento. Podemos aplicarle los métodos add, remove, toggle y contains, que veremos luego.
  • Element.className: el nombre de las clases del elemento.
  • Element.id: el id.
  • Element.name: el atributo name en los tags que pueden llevarlo, como los relacionados con los formularios o los enlaces.
  • Element.setAttribute(): cambia el valor de un atributo.
  • Element.getAttribute(): selecciona un atributo.
  • Element.hasAttribute(): comprueba si tiene un atributo.
  • Element.removeAttribute(): remueve un atributo.
  • Element.style: para modificar algunos estilos en línea (ver lista de estilos disponibles);

f) Métodos relacionados con la inserción y eliminación de nodos.

Listados así, los métodos siguientes puede que nos suenen un poco a chino, pero en la segunda parte de esta entrada nos quedarán más claros.

  • Node.appendChild(): inserta un elemento al final de los contenidos del elemento padre en el que se está incluyendo.
  • Node.insertBefore(): justo al revés, lo inserta el primero.
  • Node.removeChild(): suprime un elemento.
  • Node.replaceChild(): lo reemplaza.
  • Node.cloneNode(): copia un elemento que luego podemos insertar mediante algún método.
  • Element.insertAdjacentHTML(): inserta un fragmento de HTML antes o después de un nodo.
  • document.createElement(): crea un elemento, que luego se inserta en el DOM con alguno de los métodos anteriores.

Hay tres formas principales de andar quitando y añadiendo nodos. Una es con el innerHTML que vimos antes, otra es con la combinación de un createElement() o un cloneNode() y luego un appendChild() o un insertBefore(). Por ejemplo, así insertaríamos un <li> al final de un listado.

<ul id="soyUnaLista">

<li>Item lista</li>

<li>Item lista 2</li>

</ul>

<script>

var miNuevoItem = document.createElement('li');

miNuevoItem.textContent = "Item lista nuevo";

var lista = document.getElementById('soyUnaLista');

lista.insertBefore(miNuevoItem);

</script>

Y la tercera forma es con insertAdjacentHTML(), que reúne los métodos after(), before(), append() y prepend() de jQuery. Su sintaxis es:

element.insertAdjacentHTML('posición', 'cadenaHTML');

Donde cadenaHTML es un fragmento de HTML y posición alguna de estas cuatro:

beforebegin

<p>

afterbegin

contenido del nodo

beforeend

</p>

afterend

No es evidente cuándo utilizar innerHML o insertAdjacentHTML() y cuándo createElement. El rendimiento es muy parecido y, más que en los tiempos de ejecución, debemos pensar en los tiempos de programación : ). InnerHTML e insertAdjacentHTML() son muy rápidos de armar. Basta con definir la cadena con el fragmento de HTML que necesitamos y enchufarlo; sin embargo, createElement es muy tedioso cuando el fragmento es complejo, ya que hay que ir añadiendo las cadenas y los atributos de a poquitos una vez definido el elemento. Por lo tanto, si es algo muy sencillo podemos usar este último método, para todo lo demás conviene recurrir a innerHTML e insertAdjacentHTML().

g) Métodos relacionados con la selección de nodos.

  • Son los que vimos en la primera entrada de esta serie y que recuerdo aquí:
  • document.getElementById('id').
  • document.querySelector('selector').
  • document.getElementsByTagName('nombreTag').
  • document.getElementsByClassName('nombreClase').
  • document.querySelectorAll('selector').

No he listado todos los métodos y propiedades, pero sí las más importantes en lo que nos atañe, el trabajo del DOM. Ahora vamos a retomar la máquina que empezamos en la entrada anterior.

Creando sapos

Recordemos que nuestra máquina es un div con dos botones.

<button id="addIngredientes">Añadir ingredientes</button>

<button id="crearSapo">Crear sapo</button>

<div id="maquina"></div>

Iniciamos el proceso cuando el documento esté cargado, poniéndole un onload al body que llama a una función init().

<body onload="init()">

En esa función lanzamos las escuchas de los botones.

function init() {

// Seleccionamos los botones

var botonAdd = document.getElementById('addIngredientes');

var botonCrear = document.getElementById('crearSapo');

// Lanzamos las escuchas

botonAdd.addEventListener('click', addIngredientes);

botonCrear.addEventListener('click', crearSapo);

// Reseteamos la máquina poniéndola vacía

var maquina = document.getElementById('maquina');

maquina.setAttribute('class', 'vacia');

}

En una función llenamos la máquina de ingredientes.

function addIngredientes() {

// El array con los ingredientes

var ingredientes = ['aspirinas', 'fotones', 'gramófono'];

// Armamos la cadena recorriendo el array

var cadena = "<ul>";

for (var i=0, len=ingredientes.length; i<len; i++) {

cadena += "<li>"+ingredientes[i]+"</li>";

}

cadena += "</ul>";

// Insertamos la cadena

var maquina = document.getElementById('maquina').innerHTML = cadena;

// Cambiamos el estado de la máquina

var clasesMaquina = document.getElementById('maquina').classList;

clasesMaquina.remove('vacia');

clasesMaquina.add('llena');

}

Y si la máquina está llena, creamos un sapo cuando se pulse el botón correspondiente.

function crearSapo() {

// Seleccionamos la máquina para tenerla ya almacenada para todas las operaciones que vienen ahora

var maquina = document.getElementById('maquina');

var sapo = "<div>Soy un sapo de colores que baila swing</div>";

// Comprobamos que la máquina está llena

if ( maquina.classList.contains('llena') ) {

// Añadimos un sapillo

maquina.insertAdjacentHTML('afterend', sapo);

}

}

ver demo en plunker

Bueno, por hoy vamos a dejarlo aquí.

|| Tags:

valoración de los lectores sobre trasteando con el DOM 3: Anatomía elemental

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 5 sobre 5 (4 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Los comentarios están cerrados.