3 de julio de 2022

Modificando el documento

La modificación del DOM es la clave para crear páginas “vivas”, dinámicas.

Aquí veremos cómo crear nuevos elementos “al vuelo” y modificar el contenido existente de la página.

Ejemplo: mostrar un mensaje

Hagamos una demostración usando un ejemplo. Añadiremos un mensaje que se vea más agradable que un alert.

Así es como se verá:

<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<div class="alert">
  <strong>¡Hola!</strong> Usted ha leído un importante mensaje.
</div>

Eso fue el ejemplo HTML. Ahora creemos el mismo div con JavaScript (asumiendo que los estilos ya están en HTML/CSS).

Creando un elemento

Para crear nodos DOM, hay dos métodos:

document.createElement(tag)

Crea un nuevo nodo elemento con la etiqueta HTML dada:

let div = document.createElement('div');
document.createTextNode(text)

Crea un nuevo nodo texto con el texto dado:

let textNode = document.createTextNode('Aquí estoy');

La mayor parte del tiempo necesitamos crear nodos de elemento, como el div para el mensaje.

Creando el mensaje

Crear el div de mensaje toma 3 pasos:

// 1. Crear elemento <div>
let div = document.createElement('div');

// 2. Establecer su clase a "alert"
div.className = "alert";

// 3. Agregar el contenido
div.innerHTML = "<strong>¡Hola!</strong> Usted ha leído un importante mensaje.";

Hemos creado el elemento. Pero hasta ahora solamente está en una variable llamada div, no aún en la página, y no la podemos ver.

Métodos de inserción

Para hacer que el div aparezca, necesitamos insertarlo en algún lado dentro de document. Por ejemplo, en el elemento <body>, referenciado por document.body.

Hay un método especial append para ello: document.body.append(div).

El código completo:

<style>
.alert {
  padding: 15px;
  border: 1px solid #d6e9c6;
  border-radius: 4px;
  color: #3c763d;
  background-color: #dff0d8;
}
</style>

<script>
  let div = document.createElement('div');
  div.className = "alert";
  div.innerHTML = "<strong>¡Hola!</strong> Usted ha leído un importante mensaje.";

  document.body.append(div);
</script>

Aquí usamos el método append sobre document.body, pero podemos llamar append sobre cualquier elemento para poner otro elemento dentro de él. Por ejemplo, podemos añadir algo a <div> llamando div.append(anotherElement).

Aquí hay más métodos de inserción, ellos especifican diferentes lugares donde insertar:

  • node.append(...nodos o strings) – agrega nodos o strings al final de node,
  • node.prepend(...nodos o strings) – insert nodos o strings al principio de node,
  • node.before(...nodos o strings) –- inserta nodos o strings antes de node,
  • node.after(...nodos o strings) –- inserta nodos o strings después de node,
  • node.replaceWith(...nodos o strings) –- reemplaza node con los nodos o strings dados.

Los argumentos de estos métodos son una lista arbitraria de lo que se va a insertar: nodos DOM o strings de texto (estos se vuelven nodos de texto automáticamente).

Veámoslo en acción.

Aquí tenemos un ejemplo del uso de estos métodos para agregar items a una lista y el texto antes/después de él:

<ol id="ol">
  <li>0</li>
  <li>1</li>
  <li>2</li>
</ol>

<script>
  ol.before('before'); // inserta el string "before" antes de <ol>
  ol.after('after'); // inserta el string "after" después de <ol>

  let liFirst = document.createElement('li');
  liFirst.innerHTML = 'prepend';
  ol.prepend(liFirst); // inserta liFirst al principio de <ol>

  let liLast = document.createElement('li');
  liLast.innerHTML = 'append';
  ol.append(liLast); // inserta liLast al final de <ol>
</script>

Aquí la representación visual de lo que hacen los métodos:

Entonces la lista final será:

before
<ol id="ol">
  <li>prepend</li>
  <li>0</li>
  <li>1</li>
  <li>2</li>
  <li>append</li>
</ol>
after

Como dijimos antes, estos métodos pueden insertar múltiples nodos y piezas de texto en un simple llamado.

Por ejemplo, aquí se insertan un string y un elemento:

<div id="div"></div>
<script>
  div.before('<p>Hola</p>', document.createElement('hr'));
</script>

Nota que el texto es insertado “como texto” y no “como HTML”, escapando apropiadamente los caracteres como <, >.

Entonces el HTML final es:

&lt;p&gt;Hola&lt;/p&gt;
<hr>
<div id="div"></div>

En otras palabras, los strings son insertados en una manera segura, tal como lo hace elem.textContent.

Entonces, estos métodos solo pueden usarse para insertar nodos DOM como piezas de texto.

Pero ¿y si queremos insertar un string HTML “como html”, con todas las etiquetas y demás funcionando, de la misma manera que lo hace elem.innerHTML?

insertAdjacentHTML/Text/Element

Para ello podemos usar otro métodos, muy versátil: elem.insertAdjacentHTML(where, html).

El primer parámetro es un palabra código que especifica dónde insertar relativo a elem. Debe ser uno de los siguientes:

  • "beforebegin" – inserta html inmediatamente antes de elem
  • "afterbegin" – inserta html en elem, al principio
  • "beforeend" – inserta html en elem, al final
  • "afterend" – inserta html inmediatamente después de elem

El segundo parámetro es un string HTML, que es insertado “como HTML”.

Por ejemplo:

<div id="div"></div>
<script>
  div.insertAdjacentHTML('beforebegin', '<p>Hola</p>');
  div.insertAdjacentHTML('afterend', '<p>Adiós</p>');
</script>

…resulta en:

<p>Hola</p>
<div id="div"></div>
<p>Adiós</p>

Así es como podemos añadir HTML arbitrario a la página.