En la introducción de esta serie, se dice que “los elementos HTML son los nodos que forman el Modelo de objetos del documento”. Ya hablamos sobre el tipo de nodos de elementos. En esta sección, analizamos las APIs de elementos que permiten consultar esos nodos.
El DOM y el AOM
El DOM es una API para acceder a documentos y manipularlos. El DOM es el árbol de todos los nodos del documento. Algunos nodos pueden tener elementos secundarios, mientras que otros no. El árbol incluye elementos, junto con sus atributos y nodos de texto.
Las herramientas del navegador no proporcionan visualizaciones de árbol como la anterior, pero puedes ver los nodos en el inspector de elementos.
La representación del árbol que se puede inspeccionar en las herramientas para desarrolladores del navegador es el árbol de accesibilidad. El AOM se basa en el DOM. Del mismo modo, el árbol de accesibilidad contiene objetos que representan todos los elementos de marcado, atributos y nodos de texto:
APIs de elementos HTML
La letra del medio de DOM es “o”. Al igual que el ejemplo de objeto person
o car
de la mayoría de las clases introductorias a la programación orientada a objetos, cada nodo del árbol de documentos es un objeto que se puede manipular con JavaScript.
El navegador proporciona varias APIs que ofrecen métodos, eventos y consultas y actualizaciones de propiedades compatibles de forma nativa.
Los nodos de elementos contienen información sobre todos los atributos establecidos en el elemento. Puedes usar interfaces HTML para acceder a información sobre los atributos de un elemento. Por ejemplo, podemos usar HTMLImageElement.alt
para obtener los atributos alt
de todas las imágenes:
let allImages = document.querySelectorAll('img');
allImages.forEach((imageInstance) => {
console.log(imageInstance.alt);
});
Las interfaces HTML proporcionan más que solo acceso a los atributos de un elemento; puedes acceder a mucha más información. Podemos encontrar el elemento HTMLElement.offsetHeight
de solo lectura para obtener la altura de cada sección de nuestra página en relación con el diseño.
let allSections = document.querySelectorAll('section');
allSections.forEach((sectionInstance) => {
console.log(sectionInstance.offsetHeight);
});
Si el usuario cambia la orientación del dispositivo o cambia el ancho del viewport, la altura de cada <section>
cambiará y las propiedades del DOM se actualizarán automáticamente con ella.
Las APIs de la interfaz HTML no se limitan a acceder a los valores de los atributos. El DOM proporciona estadísticas sobre el estado actual de la IU.
Las APIs de HTML pueden acceder a toda esa información. Puedes acceder a la duración de un video, a la posición de una vista en la reproducción actual y a si el video (o el audio) terminó de reproducirse con HTMLMediaElement.duration
, HTMLMediaElement.currentTime
y HTMLMediaElement.ended
, respectivamente.
Interfaces de elementos disponibles
La mayoría de los elementos HTML que hemos visto hasta ahora en esta serie y que aún no hemos visto, además de algunos elementos de sección, tienen una interfaz de DOM asociada. La interfaz base de todos los elementos se llama Element.
HTMLElement
hereda de Element y todas las interfaces específicas del elemento HTML heredan de él. Algunas interfaces específicas de elementos se implementan con varios elementos similares.
Las interfaces incluyen lo siguiente:
HTMLAnchorElement
:<a>
HTMLAreaElement
:<area>
HTMLAudioElement
:<audio>
HTMLBaseElement
:<base>
HTMLButtonElement
:<button>
HTMLCanvasElement
:<canvas>
HTMLDataElement
:<data>
HTMLDataListElement
:<datalist>
HTMLDetailsElement
:<details>
HTMLDialogElement
:<dialog>
HTMLEmbedElement
:<embed>
HTMLFieldSetElement
:<fieldset>
HTMLFormElement
:<form>
HTMLHtmlElement
:<html>
HTMLIFrameElement
:<iframe>
HTMLImageElement
:<img>
HTMLInputElement
:<input>
HTMLLabelElement
:<label>
HTMLLegendElement
:<legend>
HTMLLIElement
:<li>
HTMLLinkElement
:<link>
HTMLMapElement
:<map>
HTMLMediaElement
:<audio>
,<video>
HTMLMenuElement
:<menu>
HTMLMetaElement
:<meta>
HTMLMeterElement
:<meter>
HTMLModElement
:<ins>
,<del>
HTMLObjectElement
:<object>
HTMLOListElement
:<ol>
HTMLOptGroupElement
:<optgroup>
HTMLOptionElement
:<option>
HTMLOutputElement
:<output>
HTMLPictureElement
:<picture>
HTMLProgressElement
:<progress>
HTMLQuoteElement
:<q>
,<blockquote>
,<cite>
HTMLScriptElement
:<script>
HTMLSelectElement
:<select>
HTMLSlotElement
:<slot>
HTMLSourceElement
:<source>
HTMLStyleElement
:<style>
HTMLTableCellElement
:<td>
,<th>
HTMLTableColElement
:<col>
,<colgroup>
HTMLTableElement
:<table>
HTMLTableRowElement
:<tr>
HTMLTableSectionElement
:<thead>
,<tbody>
,<tfoot>
HTMLTemplateElement
:<template>
HTMLTextAreaElement
:<textarea>
HTMLTimeElement
:<time>
HTMLTitleElement
:<title>
HTMLTrackElement
:<track>
HTMLVideoElement
:<video>
La convención de nombres es “HTML”, seguida de un elemento o una agrupación de elementos en mayúsculas, seguida de “Elemento”, pero la parte del elemento o la agrupación de elementos no sigue un patrón exacto. No te preocupes. No es necesario que los memorices. Solo es importante saber que existen para que puedas buscarlas cuando lo necesites.
Si tienes una colección de elementos, también hay algunas interfaces de colección. Por ejemplo, el método HTMLCollection.namedItem()
muestra el primer elemento de la colección cuyo atributo id
o name
coincide con el parámetro, o nulo si no hay ningún elemento que coincida.
Más de 30 elementos no tienen una interfaz de DOM asociada que no sea HTMLElement
, incluidos <address>
, <article>
, <section>
, <nav>
, <header>
, <footer>
, <aside>
y <hgroup>
. Muchos elementos que no admiten atributos no obsoletos ni globales tienen interfaces específicas del elemento, como HTMLPElement
(el elemento <p>
) y HTMLUnknownElement
(<😃>
o cualquier otro elemento que no esté definido), pero esas interfaces no implementan propiedades ni métodos adicionales además de las propiedades y métodos heredados de HTMLElement
, y no se mencionan anteriormente.
Métodos y propiedades redundantes de la API
Si una interfaz tiene el mismo método o nombre de propiedad que una interfaz que hereda, el método o la propiedad de herencia reemplazan al heredado. En otras palabras, los métodos y las propiedades superiores anulan los secundarios. Cuando accedimos a las propiedades alt
y offsetHeight
en las APIs de elementos HTML con imageInstance.alt
y sectionInstance.offsetHeight
, respectivamente, el código no identificó a qué API se estaba accediendo. Por lo general, como en estos dos ejemplos, esto no es un problema.
Sin embargo, hay algunos casos en los que la redundancia puede causar un problema. Por ejemplo, HTMLCollection.length
es de solo lectura, mientras que la interfaz de herencia, HTMLOptionsCollection
, tiene una propiedad de longitud (que solo muestra la propiedad options
de <select>
) con acceso de lectura y escritura. HTMLOptionsCollection
se puede usar para establecer el tamaño de la colección.
Otras interfaces
Hay interfaces adicionales que permiten manipular las ubicaciones de las ramas de los nodos del DOM. Las interfaces Node
y Window
heredan la interfaz EventTarget
, que nos proporciona addEventListener()
y removeEventListener()
. A su vez, las interfaces de Element, Document y DocumentFragment (que vimos en elementos personalizados) heredan de Node, y la interfaz de HTMLElement hereda de Element.
La interfaz de node
Cada tipo de nodo DOM está representado por una interfaz basada en Node
, que proporciona información y métodos a medida que los elementos se relacionan con el árbol DOM. La interfaz Node
permite consultar y agregar nodos al árbol de nodos.
La famosa función "recorrer el DOM" de Douglas Crockford usa firstChild
de Node y las propiedades nextSibling
.
const walk_the_DOM = function walk(node, callback) {
callback(node);
node = node.firstChild;
while (node) {
walk(node, callback);
node = node.nextSibling;
}
};
Usamos los métodos appendChild()
y cloneNode()
de Node para definir elementos personalizados.
La interfaz de Node proporciona muchas propiedades y métodos útiles para consultar y manipular el DOM.
customElements.define('star-rating',
class extends HTMLElement {
constructor() {
super(); // Always call super first in constructor
const starRating = document.getElementById('star-rating-template').content;
const shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.appendChild(starRating.cloneNode(true));
}
});
El método attachShadow()
es un método de la interfaz de Element. También hay una interfaz shadowRoot
para la API de Shadow DOM que se renderiza por separado del árbol del DOM principal de un documento.
Las interfaces Document
y HTMLDocument
La interfaz Document
hereda de Node
. Representa la página web cargada en el navegador, ya sea que el documento sea HTML, SVG, XML, MathML o algún otro. La interfaz Document
también hereda de la interfaz HTMLDocument
.
document
permite un acceso rápido a los tipos de nodos y la capacidad de crear colecciones de tipos de elementos específicos, como document.body
y document.styleSheets
. HTMLDocument permite acceder a información relevante para el documento que no se encuentra en los nodos HTML, como Document.location
, Document.lastModified
y Document.Cookie
.
Hay varias APIs disponibles según las funciones que se muestran a través de la interfaz del documento, como la API de arrastrar y soltar y la API de FullScreen. Ambos heredan de Element
.
La interfaz de Window
La interfaz de Window incluye elementos disponibles a nivel global más allá del DOM que se pueden usar para manipularlo. Window proporciona funciones, espacios de nombres, objetos y constructores documentados en JavaScript y Referencias del DOM de MDN.
La interfaz Window es la API del objeto que contiene el documento. El objeto window
global es la ventana en la que se ejecuta la secuencia de comandos. Cada pestaña del navegador contiene su propio objeto Window. La interfaz de Window puede consultar el contenido de la pestaña, así como la ventana y el dispositivo en general. Por ejemplo, el método resizeTo()
se puede usar para cambiar el tamaño de la ventana del navegador, y la propiedad devicePixelRatio
proporciona acceso a los píxeles de la pantalla del dispositivo. Cuando accedes a la información de la pestaña en la que se encuentra el contenido en lugar del árbol DOM que muestra la pestaña, es probable que la ventana sea la interfaz que buscas.
Hay varias APIs disponibles según las funciones que se muestran a través de la interfaz de Window, incluidas las APIs de Web Workers y IndexedDB.
Verifica tu comprensión
Pon a prueba tus conocimientos sobre las APIs de HTML.
¿Qué significa la O en DOM?
¿Qué interfaz puede ayudarte a obtener información sobre la pestaña en la que se encuentra el contenido?